I believe many people have done it before, but have you really built the whole project independently? Have you considered thoroughly? Have you built the personnel and environment suitable for our company’s project from the selection of UI framework, permissions, ICONS, routing, login interception, third-party tool library, performance optimization and other aspects? This article summarizes the VUE-CLI3.0 build project
Set up the project

It depends on the actual situation. Note that the vuE-CLI initialproject command is Vue create ×× instead of the previous Vue init webpack ××. I have roughly chosen the history route, Vuex, less, ESLint, Unit test, etc

Vue-cli official address

Webpack, Babel, vue.config.js configuration
Related configuration of vue.config.js
// vue.config.js
const path = require('path')

const resolve = dir => {
  returnPath. join(__dirname, dir)} const BASE_URL = process.env.node_env === ='production' ? '/' : '/'

module.exports = {
  publicPath: BASE_URL,
  outputDir: 'dist'// The directory to package the generated production environment build files assetsDir:' '// Place the generated static resource path at outputDir indexPath by default:'index.html'// Specify the generated input path of index.html, default outputDir pages: undefined, // build productionSourceMap:false// Start the production environmentsourcemap? ConfigureWebpack: {// Plugins for webpack: [new MyAwesomeWebpackPlugin()]}, chainWebpack: Config => {// webpack configuration (chain operation) // configure path alias // config.resolve.alias //.set(The '@', resolve('src'))
    //   .set('_c', resolve('src/components'))
  },
  css: {
    modules: false, // Enable CSS modules extract:true, // Whether to use CSS separation plug-inssourceMap: false// Enable the CSSsourcemaps? LoaderOptions: {less: {modifyVars: {// Customize the theme'primary-color': '#1DA57A'.'link-color': '#1DA57A'.'border-radius-base': '2px',
                  },
          javascriptEnabled: true}}}, devServer: {port: 8080, // port proxy:' '// Set the proxy}}Copy the code

Vue. Config. js official address

babel.config.js

Using babel-plugin-import(loading component code and CCTV’s Babel plug-in on demand), the following configuration uses this plug-in to introduce VUE-ANTD-Design

// babel.config.js
module.exports = {
  presets: ["@vue/app"],
   plugins: [
     [
       "import",
     { libraryName: "ant-design-vue", libraryDirectory: "es", style: true}}]].Copy the code
UI framework (Ant – design – vue)
Introduced the global

Not much said. I want to say that the global import is 13MB, more than 50 components, all import is a bit large. In fact, I have done in the past projects are basically global introduction, I do not know if the big guys will have “cleanliness” code, local introduction or write their own, ha ha

Local introduction
// main.js
import { Button } from "ant-design-vue"
import "ant-design-vue/dist/antd.less"// Or import"ant-design-vue/lib/button.less"
Vue.use(Button)
Copy the code
Use babel-plugin-import(advanced configuration)

The official address configuration of vue-and-design is at the top in babel.config.js. How do we use main.js

// 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)
Copy the code

Heck, it sounds like a lot of space, but the file size is actually much smaller

The routing configuration

To configure routing, you have to think about how to set up files and directories. Here we refer to the catalogue of Teacher Tang’s construction projects

// 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: "Dashboard" },
          component: { render: h => h("router-view") },
          children: [
            {
              path: "/dashboard/analysis",
              name: "analysis",
              meta: { title: "Analysis page" },
              component: () =>
                import( "./views/Dashboard/Analysis")
            }
          ]
        },
        // form
        {
          path: "/form",
          name: "form",
          component: { render: h => h("router-view") },
          meta: { icon: "form", title: "The form", authority: ["admin"] },
          children: [
            {
              path: "/form/basic-form",
              name: "basicform",
              meta: { title: "Basic form" },
              component: () =>
                import("./views/Forms/BasicForm")
            },
            {
              path: "/form/step-form",
              name: "stepform",
              hideChildrenInMenu: true,
              meta: { title: "Distributed form" },
              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;
Copy the code

The summary is divided into three parts: user module, main content, 403/404 page. The user has a submodule login, a dashboard dashboard and a form (usually a navigation menu), an analysis page (anlysis) under the dashboard, and a basicForm (basicForm) under the form

// App.vue
  <div id="app">
        <router-view />
  </div>
Copy the code

BasicForm.vue

The route goes somewhere like this and I think this is a neat way to write it

Routing guard

If you do not have the permission to jump to the login page, you do not have the permission to enter 403 page after the login is successful, click for more route guard knowledge

Route. beforeEach((to, from, next) => {// to target route object to enter // from current navigation route to leave // nextif(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: "You do not have access, please contact the administrator."
      });
      next({
        path: "/ 403"}); } NProgress.done(); } next(); }); AfterEach (() => {nprogress.done (); });Copy the code
Rights management
Menu routing

There is metadata information in the routing configuration that sets which users have menu permissions. In the real world, the backend returns the user’s menu and renders it if it exists

// Check user permissionsexport function check(authority){
    const current = getCurrentAuthority();
    return current.some(item => authority.includes(item));
}
Copy the code
Button permissions

Here is the custom instruction way to do, more custom instruction parameters click

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 };
Copy the code

Then use it in main.js

// main.js
import Auth from './directives/auth';
Vue.use(Auth);
Copy the code
Other related
Nprogress transition component
yarn add nprogress
npm install --save-dev nprogress
Copy the code

Functional component

Click on the more

The anchor title component created earlier is relatively simple, does not manage any state, does not listen for any state passed to it, and has no lifecycle methods. Really, it’s just a function that accepts some prop. In such a scenario, we can mark the component as functional, which means it is stateless (no responsive data) and has no instance (no this context).

<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>
Copy the code

The Render () function is also an interesting thing

Loash library

resize-detector

Finally, thank you for geek time tang Jinzhou’s video

I don’t know where to read a sentence, code without thought is dangerous, thought without code is dangerous