其他章节请看:

vue 快速入门 系列

使用 vue-cli 3 搭建一个项目(上)

前面我们已经学习了一个成熟的脚手架(vue-cli),笔者希望通过这个脚手架快速搭建系统(或项目)。而展开搭建最好的方法是向优秀的项目学习,依葫芦画瓢。

这里通过研究 vue-admin-template 项目,逐一引入 element-uiaxiosmockiconfontnprogress权限控制布局多环境(.env)跨域vue.config.js,一步一步打造我们自己的架构。

Tip: vue-element-admin 是一个优秀的后台前端解决方案,把平时用到的一些组件或者经验分享给大家。而 vue-admin-template 就是它的一个简易版本。

:由于篇幅过长,决定将文本拆分为上下两篇

模板项目 - vue-admin-template

vue-admin-template 以 vue-cli webpack 模板为基础开发,并引入如下依赖:

  • element-ui 饿了么出品的 vue pc UI框架
  • axios 一个现在主流并且很好用的请求库 支持Promise
  • js-cookie 一个轻量的JavaScript库来处理cookie
  • normalize.css 格式化css
  • nprogress 轻量的全局进度条控制
  • vuex 官方状态管理
  • vue-router 官方路由
  • iconfont 图标字体
  • 权限控制
  • lint

Tip:vue-cli webpack模板:

  • 这个模板是 vue-cli verison 2.* 的主要模板
  • Vue-cli 3 包含此模板提供的所有功能(以及更多功能)
  • Vue-cli 3 来了,此模板现在被视为已弃用

下载项目并启动:

  1. > git clone https://github.com/PanJiaChen/vue-admin-template.git vue-admin-template
  2. > cd vue-admin-template
  3. vue-admin-template> npm i
  4. vue-admin-template> npm run dev
  5. > vue-admin-template@4.4.0 dev
  6. > vue-cli-service serve
  7. ...

创建项目

我们的项目 - myself-vue-admin-template

通过 vue-cli 创建项目

  1. // 项目预设 `[Vue 2] less`, `babel`, `router`, `vuex`, `eslint`
  2. $ vue create myself-vue-admin-template

目录结构如下:

  1. myself-vue-admin-template
  2. - mode_modules
  3. - public
  4. - favicon.ico
  5. - index.html
  6. - src
  7. - assets
  8. - logo.png
  9. - components
  10. - HelloWorld.vue
  11. - router
  12. - index.js
  13. - store
  14. - index.js
  15. - views
  16. - Aobut.vue
  17. - Home.vue
  18. - App.vue
  19. - mains.js
  20. - .browerslistrc
  21. - .editorconfig
  22. - .eslintrc.js
  23. - .gitignore
  24. - babel.config.js
  25. - package-lock.json
  26. - package.json
  27. - README.md

我们的项目 Vs 模板项目

项目 vue-admin-templatemyself-vue-admin-template 多了如下目录和文件,其他都相同:

  1. vue-admin-template
  2. + build
  3. + mock
  4. + src/api
  5. + src/icons
  6. + src/layout
  7. + src/styles
  8. + src/utils
  9. + src/permission.js
  10. + src/settings.js
  11. + .env.development
  12. + .env.production
  13. + .env.staging
  14. + .travis.yml
  15. + jest.config.js
  16. + jsconfig.json
  17. + postcss.config.js
  18. + README-zh.md
  19. + vue.config.js

使用的 @vue/cli 都是 4.x :

  1. // myself-vue-admin-template
  2. "devDependencies": {
  3. "@vue/cli-plugin-babel": "~4.5.0",
  4. "@vue/cli-plugin-eslint": "~4.5.0",
  5. "@vue/cli-plugin-router": "~4.5.0",
  6. "@vue/cli-plugin-vuex": "~4.5.0",
  7. "@vue/cli-service": "~4.5.0",
  1. // vue-admin-template
  2. "devDependencies": {
  3. "@vue/cli-plugin-babel": "4.4.4",
  4. "@vue/cli-plugin-eslint": "4.4.4",
  5. "@vue/cli-plugin-unit-jest": "4.4.4",
  6. "@vue/cli-service": "4.4.4",
  7. "@vue/test-utils": "1.0.0-beta.29",

element-ui

模板项目如何使用 element-ui

  1. // package.json
  2. "dependencies": {
  3. "element-ui": "2.13.2",
  4. }
  1. // main.js
  2. // ps: 无关代码未展示
  3. import Vue from 'vue'
  4. import ElementUI from 'element-ui'
  5. import 'element-ui/lib/theme-chalk/index.css'
  6. // 国际化-英文
  7. import locale from 'element-ui/lib/locale/lang/en' // lang i18n
  8. import App from './App'
  9. // set ElementUI lang to EN
  10. Vue.use(ElementUI, { locale })
  11. // 如果想要中文版 element-ui,按如下方式声明
  12. // Vue.use(ElementUI)
  13. new Vue({
  14. el: '#app',
  15. render: h => h(App)
  16. })
  • 这里引入 Element 是完整引入,另一种是按需引入
  • Element 组件内部默认使用中文,这里使用了英文
    • element 的国际化其实就是对 element 中组件的国际化(查看文件 node_modules/element-ui/lib/locale/lang/en 就清楚了)

添加 element-ui

思路如下:

  • 完整引入 element
  • 无需提供翻译,默认使用中文
  • 利用 vue-cli 提供的插件安装 element-ui

通过 vue-cli 直接安装

  1. myself-vue-admin-template> vue add vue-cli-plugin-element
  2. Installing vue-cli-plugin-element...
  3. Successfully installed plugin: vue-cli-plugin-element
  4. // 配置
  5. ? How do you want to import Element? Fully import
  6. ? Do you wish to overwrite Element's SCSS variables? No
  7. ? Choose the locale you want to load zh-CN
  8. Successfully invoked generator for plugin: vue-cli-plugin-element

:也可以使用 vue-cli GUI 的方式安装插件 vue-cli-plugin-element

接着通过 git status 就能查看 vue-cli 替我们修改的代码:

  1. myself-vue-admin-template> git status
  2. On branch master
  3. Changes not staged for commit:
  4. (use "git add <file>..." to update what will be committed)
  5. (use "git restore <file>..." to discard changes in working directory)
  6. modified: package-lock.json
  7. modified: package.json
  8. modified: src/App.vue
  9. modified: src/main.js
  10. Untracked files:
  11. (use "git add <file>..." to include in what will be committed)
  12. src/plugins/
  13. no changes added to commit (use "git add" and/or "git commit -a")

核心代码与模板项目中的相同,只是将 element 的引入封装到了 plugins/element.js 文件中。

启动服务,页面显示:

  1. ...
  2. if Element is successfully added to this project, you'll see an <el-button> below // {1}
  3. ...

我们会在行({1})下一行看见一个 element 的按钮,说明 element-ui 引入成功。

axios

模板项目如何使用 axios

  1. // package.json
  2. "dependencies": {
  3. "axios": "0.18.1",
  4. }

对 axios 进行封装:

  1. // src/utils/request.js
  2. import axios from 'axios'
  3. import { MessageBox, Message } from 'element-ui'
  4. // create an axios instance
  5. const service = axios.create({
  6. baseURL: process.env.VUE_APP_BASE_API, // url = base url + request url
  7. // withCredentials: true, // send cookies when cross-domain requests
  8. timeout: 5000 // request timeout
  9. })
  10. // request interceptor
  11. service.interceptors.request.use(
  12. config => {
  13. ...
  14. },
  15. error => {
  16. ...
  17. }
  18. )
  19. // response interceptor
  20. service.interceptors.response.use(
  21. response => {
  22. const res = response.data
  23. // if the custom code is not 20000, it is judged as an error.
  24. if (res.code !== 20000) {
  25. Message({
  26. message: res.message || 'Error',
  27. type: 'error',
  28. duration: 5 * 1000
  29. })
  30. // 50008: Illegal token; 50012: Other clients logged in; 50014: Token expired;
  31. if (res.code === 50008 || res.code === 50012 || res.code === 50014) {
  32. // to re-login
  33. MessageBox.confirm('You have been logged out, you can cancel to stay on this page, or log in again', 'Confirm logout', {
  34. confirmButtonText: 'Re-Login',
  35. cancelButtonText: 'Cancel',
  36. type: 'warning'
  37. }).then(() => {
  38. ...
  39. })
  40. }
  41. return Promise.reject(new Error(res.message || 'Error'))
  42. } else {
  43. return res
  44. }
  45. },
  46. error => {
  47. console.log('err' + error) // for debug
  48. Message({
  49. message: error.message,
  50. type: 'error',
  51. duration: 5 * 1000
  52. })
  53. return Promise.reject(error)
  54. }
  55. )
  56. export default service
  1. // api/table.js
  2. import request from '@/utils/request'
  3. export function getList(params) {
  4. return request({
  5. url: '/vue-admin-template/table/list',
  6. method: 'get',
  7. params
  8. })
  9. }
  1. // views/table/index.vue
  2. <script>
  3. import { getList } from '@/api/table'
  4. ...
  5. </script>

添加 axios

vue-cli 安装插件
  1. myself-vue-admin-template> vue add vue-cli-plugin-axios
  2. Installing vue-cli-plugin-axios...
  3. ...
  4. Successfully installed plugin: vue-cli-plugin-axios
  1. \myself-vue-admin-template> git status
  2. On branch master
  3. Changes not staged for commit:
  4. (use "git add <file>..." to update what will be committed)
  5. (use "git restore <file>..." to discard changes in working directory)
  6. modified: package-lock.json
  7. modified: package.json
  8. modified: src/main.js
  9. Untracked files:
  10. (use "git add <file>..." to include in what will be committed)
  11. src/plugins/axios.js

其中 axios.js 中的 Plugin 在 vscode 中提示已弃用,所以干脆把模板项目中有关 axios 的搬过来

照搬模板项目中的 axios

Tip: 先将 vue-cli 安装 axios 的代码还原

  1. myself-vue-admin-template> npm i -D axios@0.18.1

新建 request.js(来自模板项目 utils/request,注释掉和权限相关的代码):

  1. // utils/request.js
  2. import axios from 'axios'
  3. import { MessageBox, Message } from 'element-ui'
  4. // import store from '@/store'
  5. // import { getToken } from '@/utils/auth'
  6. // create an axios instance
  7. const service = axios.create({
  8. baseURL: process.env.VUE_APP_BASE_API, // url = base url + request url
  9. // withCredentials: true, // send cookies when cross-domain requests
  10. timeout: 5000 // request timeout
  11. })
  12. // request interceptor
  13. service.interceptors.request.use(
  14. config => {
  15. // do something before request is sent
  16. // if (store.getters.token) {
  17. // // let each request carry token
  18. // // ['X-Token'] is a custom headers key
  19. // // please modify it according to the actual situation
  20. // config.headers['X-Token'] = getToken()
  21. // }
  22. return config
  23. },
  24. error => {
  25. // do something with request error
  26. console.log(error) // for debug
  27. return Promise.reject(error)
  28. }
  29. )
  30. // response interceptor
  31. service.interceptors.response.use(
  32. /**
  33. * If you want to get http information such as headers or status
  34. * Please return response => response
  35. */
  36. /**
  37. * Determine the request status by custom code
  38. * Here is just an example
  39. * You can also judge the status by HTTP Status Code
  40. */
  41. response => {
  42. const res = response.data
  43. // if the custom code is not 20000, it is judged as an error.
  44. if (res.code !== 20000) {
  45. Message({
  46. message: res.message || 'Error',
  47. type: 'error',
  48. duration: 5 * 1000
  49. })
  50. // 50008: Illegal token; 50012: Other clients logged in; 50014: Token expired;
  51. if (res.code === 50008 || res.code === 50012 || res.code === 50014) {
  52. // to re-login
  53. MessageBox.confirm('You have been logged out, you can cancel to stay on this page, or log in again', 'Confirm logout', {
  54. confirmButtonText: 'Re-Login',
  55. cancelButtonText: 'Cancel',
  56. type: 'warning'
  57. }).then(() => {
  58. // store.dispatch('user/resetToken').then(() => {
  59. // location.reload()
  60. // })
  61. })
  62. }
  63. return Promise.reject(new Error(res.message || 'Error'))
  64. } else {
  65. return res
  66. }
  67. },
  68. error => {
  69. console.log('err' + error) // for debug
  70. Message({
  71. message: error.message,
  72. type: 'error',
  73. duration: 5 * 1000
  74. })
  75. return Promise.reject(error)
  76. }
  77. )
  78. export default service

Tip: VUE_APP_BASE_API 请查阅本篇的 多环境->base_url

新建 table.js,定义一个请求:

  1. // api/table.js
  2. import request from '@/utils/request'
  3. export function getList(params) {
  4. return request({
  5. url: '/vue-admin-template/table/list',
  6. method: 'get',
  7. params
  8. })
  9. }

About.vue 中引用 api/table.js

  1. // views/About.vue
  2. ...
  3. <script>
  4. import { getList } from '@/api/table'
  5. export default {
  6. created() {
  7. this.fetchData()
  8. },
  9. methods: {
  10. fetchData() {
  11. getList().then(response => {
  12. console.log('加载数据', response);
  13. })
  14. }
  15. }
  16. }
  17. </script>

Tip:保存代码可能会遇到如下信息,可以通过配置 lintOnSave 生产构建时禁用 eslint-loader

  1. myself-vue-admin-template\src\views\About.vue
  2. 7:1 error More than 1 blank line not allowed no-multiple-empty-lines
  3. 12:10 error Missing space before function parentheses space-before-function-paren
  4. 16:14 error Missing space before function parentheses space-before-function-paren
  5. 18:38 error Extra semicolon semi
  6. 20:7 error Block must not be padded by blank lines padded-blocks
  7. 5 problems (5 errors, 0 warnings)
  8. 5 errors and 0 warnings potentially fixable with the `--fix` option.
  1. // vue.config.js
  2. module.exports = {
  3. lintOnSave: process.env.NODE_ENV !== 'production'
  4. }

在 App.vue 中引入 About.vue,重启服务器,发现页面(About.vue)会报 404 的错误,所以接下来我们得引入 mock。

Tip: 请查阅本篇的 添加 mock 小节。

添加完 mock,接着启动服务,页面不会再输出 404 之类的提示,控制台会输出 mock 中模拟的数据,至此,表明 axiosmock 都已生效。

mock

模板项目如何使用 mock

这里使用的 npm 包是 mockjs,将需要拦截的请求统一放在 mock 目录中,最后在 main.js 中引入 mock。

里面有关于 mock 缺陷的修复,还有 mock-serve.js,有点复杂。

以下是一些核心代码:

  1. // main.js
  2. /**
  3. * If you don't want to use mock-server
  4. * you want to use MockJs for mock api
  5. * you can execute: mockXHR()
  6. *
  7. * Currently MockJs will be used in the production environment,
  8. * please remove it before going online ! ! !
  9. */
  10. if (process.env.NODE_ENV === 'production') {
  11. const { mockXHR } = require('../mock')
  12. mockXHR()
  13. }
  1. // mock/index.js
  2. const Mock = require('mockjs')
  3. const { param2Obj } = require('./utils')
  4. const user = require('./user')
  5. const table = require('./table')
  6. const mocks = [
  7. ...user,
  8. ...table
  9. ]
  10. // for front mock
  11. // please use it cautiously, it will redefine XMLHttpRequest,
  12. // which will cause many of your third-party libraries to be invalidated(like progress event).
  13. function mockXHR() {
  14. // mock patch
  15. // https://github.com/nuysoft/Mock/issues/300
  16. Mock.XHR.prototype.proxy_send = Mock.XHR.prototype.send
  17. ...
  18. }
  19. module.exports = {
  20. mocks,
  21. mockXHR
  22. }
  1. // vue.config.js
  2. devServer: {
  3. before: require('./mock/mock-server.js')
  4. },
  1. // api/table.js
  2. import request from '@/utils/request'
  3. export function getList(params) {
  4. return request({
  5. url: '/vue-admin-template/table/list',
  6. method: 'get',
  7. params
  8. })
  9. }
  1. // views/table/index.vue
  2. import { getList } from '@/api/table'

添加 mock

笔者换一种方式,直接通过 vue-cli 插件安装:

  1. myself-vue-admin-template> vue add vue-cli-plugin-mock
  2. Installing vue-cli-plugin-mock...
  3. Successfully installed plugin: vue-cli-plugin-mock

修改的文件有:

  1. myself-vue-admin-template> git status
  2. modified: package-lock.json
  3. modified: package.json
  4. Untracked files:
  5. (use "git add <file>..." to include in what will be committed)
  6. mock/

根据 vue-cli-plugin-mock 在 npm 中介绍,这里 mock 有两种写法,自动生成的代码使用写法一,笔者为了和模板项目中的相同,将 mock/index.js 改为写法二。

  1. // 写法一
  2. module.exports = {
  3. 'GET /api/user': {
  4. // obj
  5. id: 1,
  6. username: 'kenny',
  7. sex: 6,
  8. },
  9. ...
  10. };
  11. // 写法二
  12. module.exports = [
  13. {
  14. path: '/api/user',
  15. handler: (req, res) => {
  16. return res.json({ username: 'admin', sex: 5 });
  17. },
  18. },
  19. ...
  20. ];

mock已经安装完毕,可以直接使用,具体用法请看上面的 添加 axios 小节。

Tip: 可以将 mock 进一步优化,就像模板项目一样:

  • 将 mock 文件分模块,统一通过 mock/index.js 整合
  • mock 只在开发环境下生效
  1. // vue-admin-template/src/main.js
  2. if (process.env.NODE_ENV === 'production') {
  3. const { mockXHR } = require('../mock')
  4. mockXHR()
  5. }
  1. // vue-admin-template/mock/index.js
  2. const Mock = require('mockjs')
  3. const user = require('./user')
  4. const table = require('./table')
  5. const mocks = [
  6. ...user,
  7. ...table
  8. ]
  9. module.exports = {
  10. mocks,
  11. mockXHR
  12. }

iconfont

以前图标是用图片,后来出现了雪碧图,比如将很多小图标放在一张图片中,减少请求。在后来项目中甚至不使用本地图片,而使用font库,比如 font awesome、iconfont。

模板项目中的登录页,使用了4个图标

  1. // login/index.vue
  2. <svg-icon icon-class="user"/>
  3. <svg-icon icon-class="password" />
  4. <svg-icon :icon-class="passwordType === 'password' ? 'eye' : 'eye-open'" />

添加 iconfont

官网下载并初步体验

iconfont 官网选中2个图标放到购物车中,然后点击下载代码,解压后,双击打开 index.html 则会告诉我们如何使用,我们选择第三种方式(Symbol)。

将 iconfont 加入项目

新建 SvgIcon.vue:

  1. // src/components/SvgIcon.vue
  2. <template>
  3. <svg class="svg-icon" aria-hidden="true">
  4. <use :xlink:href="iconName"></use>
  5. </svg>
  6. </template>
  7. <script>
  8. export default {
  9. name: 'icon-svg',
  10. props: {
  11. iconClass: {
  12. type: String,
  13. required: true
  14. }
  15. },
  16. computed: {
  17. iconName() {
  18. return `#icon-${this.iconClass}`
  19. }
  20. }
  21. }
  22. </script>
  23. <style>
  24. .svg-icon {
  25. width: 1em;
  26. height: 1em;
  27. vertical-align: -0.15em;
  28. fill: currentColor;
  29. overflow: hidden;
  30. }
  31. </style>

iconfont.js 放入 src/utils 文件夹中,并修改 main.js

  1. ...
  2. import './utils/iconfont.js'
  3. //引入svg组件
  4. import IconSvg from '@/components/SvgIcon'
  5. //全局注册icon-svg
  6. Vue.component('icon-svg', IconSvg)

使用 icon,例如在 About.vue 中:

  1. <template>
  2. <div class="about">
  3. <h1>This is an about page</h1>
  4. <icon-svg icon-class="password" />
  5. <icon-svg icon-class="user" />
  6. </div>
  7. </template>
改造

iconfont.js 内容如下:

  1. !function(e){var t,n,o,c,i,d='<svg><symbol id="icon-password" viewBox="0 0 1024 1024"><path d="M780.8 354.58H66..." ></path></symbol><symbol id="icon-user" viewBox="0 0 1032 1024"><path d="M494.8704..." ></path></symbol></svg>',...

如果还需要添加第三个图片,就得修改 iconfont.js 文件,而且需要使用哪个 svg 也不直观,得看代码才知道。

模板项目中是直接引入 svg 文件,而且也没有 iconfont.js 文件,相关的包有两个:

  1. "devDependencies": {
  2. // 创建 SVG sprites
  3. "svg-sprite-loader": "4.1.3",
  4. // 基于Nodejs的SVG矢量图形文件优化工具
  5. "svgo": "1.2.2",
  6. },

我们也将 iconfont 改成这种方式,首先将之前的引入 iconfont 的代码去除,然后通过vue-cli 安装插件 vue-cli-plugin-svg-sprite:

  1. myself-vue-admin-template> vue add vue-cli-plugin-svg-sprite
  2. Installing vue-cli-plugin-svg-sprite...
  3. ...
  4. Successfully installed plugin: vue-cli-plugin-svg-sprite
  5. ? Add SVGO-loader to optimize your icons before the sprite is created? Yes
  6. Invoking generator for vue-cli-plugin-svg-sprite...
  7. Installing additional dependencies...

插件安装成功后,我们查看改变的文件:

  1. myself-vue-admin-template> git status
  2. On branch master
  3. Changes not staged for commit:
  4. (use "git add <file>..." to update what will be committed)
  5. (use "git restore <file>..." to discard changes in working directory)
  6. modified: package-lock.json
  7. // 得知安装了三个包:svgo、svgo-loader、vue-cli-plugin-svg-sprite
  8. modified: package.json
  9. modified: vue.config.js
  10. Untracked files:
  11. (use "git add <file>..." to include in what will be committed)
  12. // svg 封装的组件
  13. src/components/SvgIcon.vue

Tip:vue.config.js 会添加如下内容:

  1. module.exports = {
  2. // 略
  3. chainWebpack: config => {
  4. config.module
  5. .rule('svg-sprite')
  6. .use('svgo-loader')
  7. .loader('svgo-loader')
  8. }
  9. }

接着我们需要全局注册 svg 组件:

  1. // main.js
  2. import SvgIcon from '@/components/SvgIcon'// svg component
  3. // register globally
  4. Vue.component('svg-icon', SvgIcon)

最后我们得测试 iconfont 是否生效。

先将 svg 文件下载并保存到 assets/icons 目录,然后修改 About.vue:

  1. <template>
  2. <div class="about">
  3. <h1>This is an about page</h1>
  4. <svg-icon name="password" />
  5. <svg-icon name="open" />
  6. </div>
  7. </template>

重启服务,页面成功显示两张 svg 图片,至此,我们的 iconfont 就引入成功了。

nprogress

在模板项目中,切换试图,在页面顶部会有一个进度条的东西,使用的就是 nprogress(Ajax'y 应用程序的细长进度条。受 Google、YouTube 和 Medium 的启发)。

模板项目:

  1. "dependencies": {
  2. "nprogress": "0.2.0",
  3. }

添加 nprogress

由于 vue-cli ui 搜索不到 nprogress 相应的插件,所以我们只能通过 npm 老老实实的安装:

  1. $ npm i -D nprogress

接下来使用 nprogress,给 About.vue 添加如下代码,重启服务即可看到效果:

  1. // About.vue
  2. <script>
  3. import NProgress from 'nprogress' // progress bar
  4. import 'nprogress/nprogress.css' // progress bar style
  5. // 通过将其设置为 false 来关闭加载微调器。
  6. NProgress.configure({ showSpinner: false }) // NProgress Configuration
  7. export default {
  8. created () {
  9. // Simply call start() and done() to control the progress bar.
  10. NProgress.start();
  11. // 可以尝试直接调用 NProgress.done() 或者不执行 NProgress.done()
  12. setTimeout(function(){
  13. NProgress.done()
  14. }, 10000)
  15. },
  16. }
  17. </script>

Tip:直接在模板项目中搜索关键字 NProgress 就能找到上面的代码。NProgress.start() 和 NProgress.done() 出现在模板项目中的 permission.js 文件里面,并且也在路由中。

normalize.css

normalize.css,CSS 重置的现代替代方案

添加 normalize.css

  1. $ npm i -D normalize.css

在入口文件中引入 normalize.css

  1. // main.js
  2. import 'normalize.css/normalize.css' // A modern alternative to CSS resets

重启服务,body 的 margin 会重置为 0,说明已生效。

js-cookie

js-cookie,用于处理 cookie,简单的、轻量级的 JavaScript API。

模板项目如何使用 js-cookie

相关代码如下:

  1. // package.json
  2. "dependencies": {
  3. "js-cookie": "2.2.0",
  4. },
  1. // src/utils/auth.js
  2. import Cookies from 'js-cookie'
  3. const TokenKey = 'vue_admin_template_token'
  4. export function getToken() {
  5. return Cookies.get(TokenKey)
  6. }
  7. export function setToken(token) {
  8. return Cookies.set(TokenKey, token)
  9. }
  10. export function removeToken() {
  11. return Cookies.remove(TokenKey)
  12. }

添加 js-cookie

  1. $ npm i -D js-cookie

About.vue 中使用一下:

  1. // About.vue
  2. <script>
  3. import Cookies from 'js-cookie'
  4. export default {
  5. created () {
  6. Cookies.set('sex', 'man')
  7. alert(Cookies.get('sex'))
  8. },
  9. }
  10. </script>

重启服务,页面弹出 man 则说明成功引入。

其他

npm 必须使用 TLS 1.2 or higher

某天运行 npm i 报错如下:

  1. npm notice Beginning October 4, 2021, all connections to the npm registry - including for package installation - must use TLS 1.2 or higher. You are currently using plaintext http to connect. Please visit the GitHub blog for more information: https://github.blog/2021-08-23-npm-registry-deprecating-tls-1-0-tls-1-1/

可以查看这篇文章:npm registry正在弃用TLS 1.0和TLS 1.1

Uncaught (in promise) Error: Redirected when going from

Uncaught (in promise) Error: Redirected when going from "/login" to "/" via a navigation guard.

可以查看这篇文章:Uncaught (in promise) Error: Redirected when going from

其他章节请看:

vue 快速入门 系列

vue 快速入门 系列 —— 使用 vue-cli 3 搭建一个项目(上)的更多相关文章

  1. vue 快速入门 系列 —— vue-cli 上

    其他章节请看: vue 快速入门 系列 Vue CLI 4.x 上 在 vue loader 一文中我们已经学会从零搭建一个简单的,用于单文件组件开发的脚手架:本篇,我们将全面学习 vue-cli 这 ...

  2. vue 快速入门 系列 —— vue-cli 下

    其他章节请看: vue 快速入门 系列 Vue CLI 4.x 下 在 vue loader 一文中我们已经学会从零搭建一个简单的,用于单文件组件开发的脚手架:本篇,我们将全面学习 vue-cli 这 ...

  3. vue 快速入门 系列 —— 使用 vue-cli 3 搭建一个项目(下)

    其他章节请看: vue 快速入门 系列 使用 vue-cli 3 搭建一个项目(下) 上篇 我们已经成功引入 element-ui.axios.mock.iconfont.nprogress,本篇继续 ...

  4. vue 快速入门 系列 —— 虚拟 DOM

    其他章节请看: vue 快速入门 系列 虚拟 DOM 什么是虚拟 dom dom 是文档对象模型,以节点树的形式来表现文档. 虚拟 dom 不是真正意义上的 dom.而是一个 javascript 对 ...

  5. vue 快速入门 系列 —— 初步认识 vue

    其他章节请看: vue 快速入门 系列 初步认识 vue vue 是什么 Vue (读音 /vjuː/,类似于 view) 是一套用于构建用户界面的渐进式框架. 所谓渐进式,就是你可以一步一步.有阶段 ...

  6. vue 快速入门 系列 —— 侦测数据的变化 - [基本实现]

    其他章节请看: vue 快速入门 系列 侦测数据的变化 - [基本实现] 在 初步认识 vue 这篇文章的 hello-world 示例中,我们通过修改数据(app.seen = false),页面中 ...

  7. vue 快速入门 系列 —— 侦测数据的变化 - [vue 源码分析]

    其他章节请看: vue 快速入门 系列 侦测数据的变化 - [vue 源码分析] 本文将 vue 中与数据侦测相关的源码摘了出来,配合上文(侦测数据的变化 - [基本实现]) 一起来分析一下 vue ...

  8. vue 快速入门 系列 —— vue 的基础应用(上)

    其他章节请看: vue 快速入门 系列 vue 的基础应用(上) Tip: vue 的基础应用分上下两篇,上篇是基础,下篇是应用. 在初步认识 vue一文中,我们已经写了一个 vue 的 hello- ...

  9. vue 快速入门 系列 —— vue 的基础应用(下)

    其他章节请看: vue 快速入门 系列 vue 的基础应用(下) 上篇聚焦于基础知识的介绍:本篇聚焦于基础知识的应用. 递归组件 组件是可以在它们自己的模板中调用自身的.不过它们只能通过 name 选 ...

随机推荐

  1. docker run 参数

    一.格式 docker run [OPTIONS] IMAGE [COMMAND] [ARG...] 二.OPTIONS 参数 简写, 名称参数 默认参数 描述 --add-host 添加自定义主机到 ...

  2. 记一次centos挂载ceph存储的坑

    起因 生产有两台服务器,准备用来跑工作流,执行的资源的是放在ceph存储集群中,第一步挂载ceph 执行命令:mount -t ceph xxx:xxx -o name=admin,secret=AQ ...

  3. python基础知识三——try与except处理异常语句

    try/except介绍 与其他语言相同,在python中,try/except语句主要是用于处理程序正常执行过程中出现的一些异常情况,如语法错(python作为脚本语言没有编译的环节,在执行过程中对 ...

  4. Shiro 550反序列化漏洞分析

    Shiro 550反序列化漏洞分析 一.漏洞简介 影响版本:Apache Shiro < 1.2.4 特征判断:返回包中包含rememberMe=deleteMe字段. Apache Shiro ...

  5. Springboot在有锁的情况下如何正确使用事务

    1. 概述 老话说的好:想要赚钱,就去看看有钱人有什么需求,因为有钱人钱多,所以赚的多. 言归正传,在Java项目的研发中,"锁"这个词并不陌生,最经典的使用场景是商品的超卖问题. ...

  6. iOS实现XMPP通讯(二)XMPP编程

    项目概述 这是一个可以登录jabber账号,获取好友列表,并且能与好友进行聊天的项目. 使用的是第三方库XMPPFramework框架来实现XMPP通讯. 项目地址:XMPP-Project 项目准备 ...

  7. The Data Way Vol.1|风口下的开源市场:如何看待开源与商业的关系?

    关于「The Data Way」 「The Data Way」是由 SphereEx 公司出品的一档播客节目.这里有开源.数据.技术的故事,同时我们关注开发者的工作日常,也讨论开发者的生活日常:我们聚 ...

  8. 时序数据库InfluxDB的基本语法

    一 了解InfluxDB的必要性 时序数据库主要存放的数据 Time series data is a series of data points each associated with a spe ...

  9. 2021年1月-第02阶段-前端基础-HTML+CSS进阶-VS Code 软件

    软件安装 VSCode软件 能够安装 VS Code 能够熟练使用 VS Code 软件 能够安装 VS Code 最常用的插件 1. VS Code简介 1.1 VS Code 简介 Visual ...

  10. 初学python-day3 元组

    day2 列表已更新!