Vue-Cli 3.0从0 开始搭建项目(篇1)

本文围绕Vue项目展开,介绍了Vue - Cli初始化项目命令,提及按需加载组件代码以减小文件大小。阐述了项目目录设置,分为用户模块、主要内容、403/404页面。还讲解了路由配置、路由守卫、自定义指令等知识,最后提到组件标记为functional及相关库。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

从0开始搭建项目,相信更多人都做过,但是你真的独立搭建整个项目了吗,有没有考虑周全,是否从UI的框架的选型、权限、图标、路由、登陆拦截、第三方工具库、性能优化等多方面搭建出适合本公司项目的人员和环境。本文总结的是Vue-Cli3.0构建项目
搭建项目

根据实际情况而定。 值得注意的Vue-Cli 初始化项目的命令是 vue create ××,而不是之前的 vue init webpack ×× 我这边大致选了history路由、Vuex、less、eslint、unit test等

Vue-Cli官方地址

webpack、babel、vue.config.js的配置
vue.config.js的相关配置
// 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: '' // 设置代理
  }
}
复制代码

Vue.config.js官方地址

babel.config.js

使用babel-plugin-import(按需加载组件代码和央视的babel插件),下面的配置使用该插件引入 vue-antd-design

// babel.config.js
module.exports = {
  presets: ["@vue/app"],
   plugins: [
     [
       "import",
     { libraryName: "ant-design-vue", libraryDirectory: "es", style: true }
    ]
  ]
};
复制代码
UI框架(Ant-design-vue)
全局引入

不多说。想说的是全局引入有13MB,50多个组件,全部引入有点大。其实在我以前做过的项目当中基本上都是全局引入,不知大佬们写代码会不会有“洁癖”,局部引入或是自己写,哈哈

局部引入
// 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)
复制代码
使用babel-plugin-import(高级配置)

vue-and-design官方地址 配置就在上方的babel.config.js中。 我们下面看看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)
复制代码

哎呀,貌似篇幅很长,不过加载的文件大小确实小了很多

路由配置

一定要配置路由,就得想好文件目录怎么设置。这里参考了唐老师的搭建项目的目录

路由配置,篇幅有限。我只选出一部分

// 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

// App.vue
  <div id="app">
        <router-view />
  </div>
复制代码

BasicForm.vue

路由大概到这里 这个写法觉得很巧妙

路由守卫

如果没有权限跳到登陆页面, 登陆成功之后没有权限进入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);
复制代码
其它相关
Nprogress 过渡组件
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()函数还是一个挺有意思的存在

loash库

resize-detector

最后感谢极客时间唐金洲老师的视频

不知道在哪里看过一句话,码而不思则殆,思而不码还是殆

# URL: http://kongkong.fence.wmdev2.lsh123.com/ # jl-mis(接龙后台管理系统) 项目是基于vue-cli 3+ 构建的,请先将vue-cli升级到3+版本,vue-cli3 传送门(https://cli.vuejs.org/zh/)。 ## 技术栈 vue2 + vuex + vue-router + element-ui + webpack + ES6/7 + axios + less + flex + svg ### 项目图形化管理界面 ``` vue ui ``` ## 项目运行 #### 注意:由于涉及大量的 ES6/7 等新属性,node 需要 8.0 以上版本 ``` npm install npm run serve ``` ### 打包 ``` npm run build ``` ### 代码的 lint ``` npm run lint ``` # 项目布局 ``` . ├── public // HTML 和静态资源 │   ├── favicon.ico // 图标 │   ├── index.html // 入口html文件 ├── src // 源码目录 │   ├── assets // 静态资源 │   │   ├── images // 公共图片 │   ├── components // 组件 │   │   ├── common // 公共组件 │   │   ├── page // 页面 │   ├── libs // 封装库 │   │   ├── storage.js // 对cookie 和 localStorage 的封装 │   ├── plugins // 引用的插件 │   │   ├── axios.js // 对axios的的封装(拦截器相关) │   │   ├── element.js // 引入element-ui │   ├── router │   │   └── router.js // 路由配置 │   ├── service // 数据交互统一调配 │   │   ├── service.js // 获取数据的统一调配文件,对接口进行统一管理 │   ├── store // vuex的状态管理 │   │   ├── actions.js // 配置actions │   │   ├── getters.js // 配置getters │   │   ├── store.js // 引用vuex,创建store │   │   ├── modules // store模块 │   │   │   ├── urlGroups.js // 路由分组(权限相关) │   │   ├── mutation-types.js // 定义常量muations名 │   │   └── mutations.js // 配置mutations │   └── style // 样式字体相关 │   ├── fonts // 字体相关 │   ├── utility.less // 公共样式文件 │   ├── mixin.less // 样式配置文件 │   └── normalize.css // 样式重置 │   ├── App.vue // 页面入口文件 │   ├── main.js // 程序入口文件,加载各种公共组件 ├── vue.config.js // vue-cli 3+ 暴露出来的webpack相关的配置文件 . ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值