接上一篇 Vue 3.0 项目配置。

本人最近研究了一遍 Vue 3.0 的英文文档,本来想分享下 API 用法的,结果看了下网上,Vue 3.0 + TypeScript 的教程已经满天飞了,另外本人搭建的 Vue 3.0 + Element plus 项目最近也遇到了不少 bug ,所以 Vue 3.0 的内容本人打算先放一放。

网上关于 Vue 3.0 的教程虽然很多,但是几乎没有一篇最佳实践。众所周知,在 Vue 3.0 中使用 setup 函数开发的风格跟 React 已经非常接近,但是很多习惯了 Vue 2.x 的同学可能会不适应,感觉写出来的代码很乱,很难维护。另外还有 ref 语法糖, <script setup> ,CSS 变量注入等在提案阶段。本人打算等后面版本稳定了再出一篇最佳实践。

BTW,现在网上有不少人已经用 Object.defineProperty 实现简易的 Vue 框架,但是应该还没多少人使用 Proxy 来实现的,本人打算抽空试试,顺带分享一篇教程。

进入正题,这篇教程算是补一下之前的坑,希望给各位从零开始搭建项目的同学提供参考。

1. vue-cli 脚手架安装

全局安装 vue-cli:

$ npm install -g @vue/cli

检查版本:

$ vue -V
本人写这篇文章的时候,最新的版本是 @vue/cli 4.5.11

2. 创建项目

执行下面的命令:

$ vue create demo-project

这里 demo-project 替换成自己的项目名称,后面就是傻瓜式安装,这个过程也会拉取依赖放到 node_modules 目录下。等待安装完成,运行下面的命令就可以启动本地开发服务器:

$ npm run serve

如果不清楚各种命令,可以到 package.json 里面的 scripts 配置项查看:

"scripts": {
    "serve": "vue-cli-service serve",
    "build": "vue-cli-service build",
    "lint": "vue-cli-service lint"
},

所以执行 npm run serve 其实就是在执行下面的命令:

$ npx vue-cli-service serve [options] [entry]
# --open    在服务器启动时打开浏览器
# --copy    在服务器启动时将 URL 复制到剪切版
# --mode    指定环境模式 (默认值:development)
# --host    指定 host (默认值:0.0.0.0)
# --port    指定 port (默认值:8080)
# --https   使用 https (默认值:false)
vue-cli-service serve 命令会启动一个开发服务器 (基于 webpack-dev-server) 并附带开箱即用的模块热重载 (Hot-Module-Replacement)

我们看到,这个命令支持传递命令行参数,用于设置本地开发服务器的各种配置。当然每次都在命令行中输入显然太麻烦,所以实际项目开发都是在 vue.config.js 中进行设置的,下面会介绍。

3. 配置文件

启动项目的时候,默认是没有浏览器自动打开的,默认端口也是 8080 ,如果想修改配置,可以到根目录下创建一个配置文件 vue.config.js ,这些配置会被 webpack-merge 合并到最终的 Webpack 配置里面。这里配置的内容比较多,可以根据自己的需要进行配置。

// vue.config.js
module.exports = {
    publicPath: '/',
    ourputDir: 'dist',
    assetsDir: 'assets',
    indexPath: 'index.html',
    filenameHashing: true,
    pages: undefined,
    lintOnSave: process.env.NODE_ENV !== 'production',
    runtimeCompiler: false,
    transpileDependencies: [],
    productionSourceMap: false,
    css: {
        requireModuleExtension: true,
        extract: process.env.NODE_EVN === 'production',
        sourceMap: false,
        loaderOptions: {}
    },
    parallel: true,
    pluginOptions: {},
    devServer: {
        open: true,
        host: '0.0.0.0',
        port: 8066,
        https: false,
        hotOnly: false,
        proxy: {
            '/api': {
                target: 'http://127.0.0.1:7001'
                changeOrigin: true
            }
        }
    },
    configureWebpack: config => {
        if (process.env.NODE_ENV === 'production') {
            // 为生产环境修改配置
        } else {
            // 为开发环境修改配置
        }
    }
}

Vue CLI 配置参考

4. 静态资源

使用 . 开头的相对路径,所有诸如 ![](...)background: url(...) 和 CSS @import 的资源 URL,会被 Webpack 处理,解析为一个模块依赖,例如:

import './style.less'
// 会被编译为
require('./style.less')

转换规则

如果 URL 是一个绝对路径 (例如 /images/foo.png),它将会被保留不变

如果 URL 以 . 开头,它会作为一个相对模块请求被解释且基于你的文件系统中的目录结构进行解析

如果 URL 以 ~ 开头,其后的任何内容都会作为一个模块请求被解析。这意味着你甚至可以引用 Node 模块中的资源

如果 URL 以 @ 开头,它也会作为一个模块请求被解析。它的用处在于 Vue CLI 默认会设置一个指向 <projectRoot>/src 的别名 @(仅作用于模版中)

需要注意的是,public 目录下的静态资源不会被 Webpack 处理,只会被简单复制到打包的目录中,因此 public 目录下的资源要使用绝对路径引用。

5. CSS 预编译器

使用 Vue CLI 创建的项目已经在 Webpack 的配置中支持了各种 CSS 预编译器,只需要安装依赖就可以直接在项目中使用:

$ npm install -D less-loader less

这边要注意下,Vue-cli 3.x 和 4.x 都有版本兼容问题(本人用的是 @vue/cli 4.5.13),直接用上面的命令安装,默认安装最新稳定版,例如本人装的是 less-loader@9.1.0,但是在组件中使用 less 编译时会报如下错误:

Syntax Error: TypeError: this.getOptions is not a function

使用如下命令查看 less-loader 版本:

$ npm view less-loader versions

然后安装一个 7.x 的版本,再次运行项目就没有报错了。

6. 环境变量

7. 配置 Vue router

安装 vue-router :

$ npm install vue-router

src 目录下建一个 router 目录:

- src
  |- router
     |- index.js

index.js 内容如下:

import Vue from 'vue'
import Router from 'vue-router'
import getCookie from '@/utils/cookies'

Vue.use(Router);

const meta = {
    requiresAuth: true, // 需要鉴权
};
const router = new Router({
    routes: [
        {
            path: '/',
            redirect: '/login'
        },
        {
            path: '/login',
            component: () => import('@/views/Login.vue')
        },
        {
            path: '/activity',
            component: () => import('@/views/Activity.vue'),
            meta: {
                ...meta,
            }
        }
    ]
})

router.beforeEach((to, from, next) => {
    if (to.meta.requiresAuth) {
        // 需要鉴权
        const token = getCookie("token");
        if (token && token !== 'undefined') {
            next();
        } else {
            next("/login");
        }
    } else {
        // 不需要身份校验 直接通过
        next();
    }
})

export default router;

然后在 main.js 中添加如下内容:

import Vue from 'vue'
import App from './App.vue'
import router from './router' // 引入路由模块

Vue.config.productionTip = false

new Vue({
  router, // 使用路由
  render: h => h(App),
}).$mount('#app')

8. 配置 vuex

安装 vuex :

$ npm install vuex

然后在 src 目录下建一个 store 目录:

- src
  |- store
     |- index.js
     |- state.js
     |- getters.js
     |- mutations.js
     |- actions.js

各个模块内容如下:

// state.js
const state = {}
export default state

// getters.js
const getters = {}
export default getters

// mutations.js
const mutations = {}
export default mutations

// actions.js
const actions = {}
export default actions

// index.js
import Vue from 'vue'
import Vuex from 'vuex'

import state from './state'
import getters from './getters'
import mutations from './mutations'
import actions from './actions'

Vue.use(Vuex)

const store = new Vuex.Store({
    state,
    getters,
    mutations,
    actions,
})

export default store

注意 new Vuex.StoreStore 必须大写,如果小写会报如下错误:

Uncaught TypeError: vuex__WEBPACK_IMPORTED_MODULE_1__.default.store is not a constructor

然后在 main.js 中添加如下内容:

import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store' // 引入 vuex

Vue.config.productionTip = false

new Vue({
  router,
  store, // 使用 vuex
  render: h => h(App),
}).$mount('#app')

9. 引入 antd vue 组件库

安装 ant-design-vue :

$ npm install ant-design-vue

然后在 main.js 中引入组件库及样式文件,这边采用的是全量引入:

import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
import Antd from 'ant-design-vue' // 引入Antd组件库
import 'ant-design-vue/dist/antd.css'; // 引入Antd样式

Vue.config.productionTip = false

Vue.use(Antd) // 使用Antd组件库

new Vue({
  router,
  store,
  render: h => h(App),
}).$mount('#app')

全量引入打包会慢一些,如果想按需加载,可以参考官网教程

https://www.antdv.com/docs/vu...

10. 配置 axios

安装 axios :

$ npm install axios

在 src 目录下创建两个目录:

- src
  |- api
  |  |- systemInfo.js
  |- utils
     |- request.js

request.js 中添加以下代码:

import axios from 'axios'

const service = axios.create({
    baseURL: '/',
    timeout: 1000000, // 请求超时时间
})

export default service
关于 axios 的封装这里不详细展开

然后在 systemInfo.js 中添加以下代码:

import request from '/@/utils/request'

let systemInfo = {};
systemInfo.login = function(data) {
    return request({
        url: '/api/fin-services/v1/system-info/login',
        data,
        method: 'post'
    })
}

export default systemInfo

在接口请求之前,确保 vue.config.js 中设置了代理,否则跨域请求会被浏览器同源策略阻止:

module.exports = {
    devServer: {
        open: true,
        host: '0.0.0.0',
        port: 8066,
        https: false,
        hotOnly: false,
        proxy: {
            '/api': {
                target: 'http://127.0.0.1:7001' // 后端实际地址
                changeOrigin: true
            }
        }
    },
}
后端如果响应头设置了 ACAO 也可以不用代理

vue-cli 文档:

https://cli.vuejs.org/zh/guid...

配置参考:

https://cli.vuejs.org/zh/conf...


一杯绿茶
199 声望17 粉丝

人在一起就是过节,心在一起就是团圆