根據實際狀況而定。 值得注意的Vue-Cli 初始化項目的命令是 vue create ××
,而不是以前的 vue init webpack ××
我這邊大體選了history路由、Vuex、less、eslint、unit test等javascript
// vue.config.js
const path = require('path')
const resolve = dir => {
return path.join(__dirname, dir)
}
// 線上打包路徑,請根據項目實際線上狀況
const BASE_URL = process.env.NODE_ENV === 'production' ? '/' : '/'
module.exports = {
publicPath: BASE_URL,
outputDir: 'dist', // 打包生成的生產環境構建文件的目錄
assetsDir: '', // 放置生成的靜態資源路徑,默認在outputDir
indexPath: 'index.html', // 指定生成的 index.html 輸入路徑,默認outputDir
pages: undefined, // 構建多頁
productionSourceMap: false, // 開啓 生產環境的 source map?
configureWebpack: { // webpack 的配置
plugins: [
new MyAwesomeWebpackPlugin()
]
},
chainWebpack: config => { // webpack的配置(鏈式操做)
// 配置路徑別名
// config.resolve.alias
// .set('@', resolve('src'))
// .set('_c', resolve('src/components'))
},
css: {
modules: false, // 啓用 CSS modules
extract: true, // 是否使用css分離插件
sourceMap: false, // 開啓 CSS source maps?
loaderOptions: {
less: {
modifyVars: { // 定製主題
'primary-color': '#1DA57A',
'link-color': '#1DA57A',
'border-radius-base': '2px',
},
javascriptEnabled: true,
}
}
},
devServer: {
port: 8080, // 端口
proxy: '' // 設置代理
}
}
複製代碼
使用babel-plugin-import
(按需加載組件代碼和央視的babel插件),下面的配置使用該插件引入 vue-antd-design
html
// babel.config.js
module.exports = {
presets: ["@vue/app"],
plugins: [
[
"import",
{ libraryName: "ant-design-vue", libraryDirectory: "es", style: true }
]
]
};
複製代碼
很少說。想說的是全局引入有13MB,50多個組件,所有引入有點大。其實在我之前作過的項目當中基本上都是全局引入,不知大佬們寫代碼會不會有「潔癖」,局部引入或是本身寫,哈哈vue
// main.js
import { Button } from "ant-design-vue"
import "ant-design-vue/dist/antd.less"
// 或者是
import "ant-design-vue/lib/button.less"
Vue.use(Button)
複製代碼
vue-and-design官方地址 配置就在上方的babel.config.js
中。 咱們下面看看main.js
是怎麼使用的java
// main.js
import { Button,Menu,Drawer,Radio,Layout,Icon} from 'ant-design-vue';
Vue.use(Drawer)
Vue.use(Button)
Vue.use(Menu)
Vue.use(Radio)
Vue.use(Layout)
Vue.use(Icon)
複製代碼
哎呀,貌似篇幅很長,不過加載的文件大小確實小了不少webpack
必定要配置路由,就得想好文件目錄怎麼設置。這裏參考了唐老師的搭建項目的目錄web
// router.js
import Vue from "vue";
import Router from "vue-router";
import { notification } from "ant-design-vue";
import NotFound from "./views/404";
import Forbidden from "./views/403";
Vue.use(Router);
const router = new Router({
mode: "history",
base: process.env.BASE_URL,
routes: [
{
path: "/user",
hideInMenu: true,
component: () =>
import( "./layouts/UserLayout"),
children: [
{
path: "/user",
redirect: "/user/login"
},
{
path: "/user/login",
name: "login",
component: () =>
import( "./views/User/Login")
}
]
},
{
path: "/",
meta: { authority: ["user", "admin"] }, // 用來作權限管理
component: () =>
import( "./layouts/BasicLayout"),
children: [
// dashboard
{
path: "/",
redirect: "/dashboard/analysis"
},
{
path: "/dashboard",
name: "dashboard",
meta: { icon: "dashboard", title: "儀表盤" },
component: { render: h => h("router-view") },
children: [
{
path: "/dashboard/analysis",
name: "analysis",
meta: { title: "分析頁" },
component: () =>
import( "./views/Dashboard/Analysis")
}
]
},
// form
{
path: "/form",
name: "form",
component: { render: h => h("router-view") },
meta: { icon: "form", title: "表單", authority: ["admin"] },
children: [
{
path: "/form/basic-form",
name: "basicform",
meta: { title: "基礎表單" },
component: () =>
import("./views/Forms/BasicForm")
},
{
path: "/form/step-form",
name: "stepform",
hideChildrenInMenu: true,
meta: { title: "分佈表單" },
component: () =>
import( "./views/Forms/StepForm"),
children: [
{
path: "/form/step-form",
redirect: "/form/step-form/info"
},
{
path: "/form/step-form/info",
name: "info",
component: () =>
import( "./views/Forms/StepForm/Step1")
}
]
}
]
}
]
},
{
path: "/403",
name: "403",
hideInMenu: true,
component: Forbidden
},
{
path: "*",
name: "404",
hideInMenu: true,
component: NotFound
}
]
});
export default router;
複製代碼
總結下分爲三部分:用戶模塊、主要內容、403/404頁面。 用戶下面有子模塊login,主要內容(通常是導航菜單的內容)有儀表盤dashboard
和表單form
,儀表盤下面有分析頁anlysis
,表單下面有基礎表單basicForm
vue-router
// App.vue
<div id="app">
<router-view />
</div>
複製代碼
BasicForm.vue vue-cli
路由大概到這裏 這個寫法以爲很巧妙npm
若是沒有權限跳到登錄頁面, 登錄成功以後沒有權限進入403頁面,更多路由守衛知識點擊
router.beforeEach((to, from, next) => {
// to 即將要進入的目標 路由對象
// from 當前導航正要離開的路由
// next
if (to.path !== from.path) {
NProgress.start();
}
const record = findLast(to.matched, record => record.meta.authority);
if (record && !check(record.meta.authority)) {
if (!isLogin() && to.path !== "/user/login") {
next({
path: "/user/login"
});
} else if (to.path !== "/403") {
notification.error({
message: "403",
description: "你沒有權限訪問,請聯繫管理員諮詢。"
});
next({
path: "/403"
});
}
NProgress.done();
}
next();
});
// 全局後置鉤子
router.afterEach(() => {
NProgress.done();
});
複製代碼
在路由配置那裏有個元數據信息,那裏設置了哪些用戶具備菜單權限。 在真實的環境中是後端返回這個用戶的菜單,有的話就渲染出來
// 檢查 用戶的權限
export function check(authority){
const current = getCurrentAuthority();
return current.some(item => authority.includes(item));
}
複製代碼
這裏是自定義指令的方式作的,更多自定義指令的參數點擊
import { check } from "../utils/auth";
function install(Vue, options = {}) {
Vue.directive(options.name || "auth", {
inserted(el, binding) {
if (!check(binding.value)) {
el.parentNode && el.parentNode.removeChild(el);
}
}
});
}
export default { install };
複製代碼
而後在main.js
中使用
// main.js
import Auth from './directives/auth';
Vue.use(Auth);
複製代碼
yarn add nprogress
npm install --save-dev nprogress
複製代碼
更多點擊
以前建立的錨點標題組件是比較簡單,沒有管理任何狀態,也沒有監放任何傳遞給它的狀態,也沒有生命週期方法。實際上,它只是一個接受一些 prop 的函數。 在這樣的場景下,咱們能夠將組件標記爲 functional,這意味它無狀態 (沒有響應式數據),也沒有實例 (沒有 this 上下文)。
<script>
import { check } from '../utils/auth'
export default {
functional: true,
props: {
authority: {
type: Array,
required: true
}
},
render(h, context){
const { props,scopedSlots } = context;
return check(props.authority) ? scopedSlots.default(): null
}
}
</script>
複製代碼
render()函數仍是一個挺有意思的存在
最後感謝極客時間唐金洲老師的視頻
不知道在哪裏看過一句話,碼而不思則殆,思而不碼仍是殆