Axios
一、安装
npm install vue-axios --save
二、main.js引入
import axios from 'axios' Vue.prototype.$axios = axios //全局注册,使用方法为:this.$axios
三、使用
<script> export default{ data(){ return{ userId:666, token:'', } }, created(){ this.$axios({ method:'post', url:'api', data:this.qs.stringify({ //这里是发送给后台的数据 userId:this.userId, token:this.token, }) }).then((response) =>{ //这里使用了ES6的语法 console.log(response) //请求成功返回的数据 }).catch((error) => console.log(error) //请求失败返回的数据 }) } } </script>
四、请求拦截器
// http request 拦截器 instance.interceptors.request.use( config => { const token = sessionStorage.getItem('token') if (token ) { // 判断是否存在token,如果存在的话,则每个http header都加上token config.headers.authorization = token //请求头加上token } return config }, err => { return Promise.reject(err) })
五、响应拦截器
// http response 拦截器 instance.interceptors.response.use( response => { //拦截响应,做统一处理 if (response.data.code) { switch (response.data.code) { case 1002: store.state.isLogin = false router.replace({ path: 'login', query: { redirect: router.currentRoute.fullPath } }) } } return response }, //接口错误状态处理,也就是说无响应时的处理 error => { return Promise.reject(error.response.status) // 返回接口返回的错误信息 })
六、在需要的页面导入就可以使用了
import instance from './axios' /* 验证登陆 */ export function handleLogin (data) { return instance.post('/ds/user/login', data) }
管理系统中使用的图标
项目中的图标需要集中管理起来,方便维护,减少一些图片重复引入
如果对安全没什么特殊要求:推荐使用iconfont
如果对安全有特别要求:把图标统一存放在内部服务
定制主题及动态切换主题
结合ElementUI使用
(Tips: 广东靓仔看到业界关于动态主题大约有6种方案,选了其中一种)
修改ElementUI提供的变量,先根据实际情况修改变量值
// 参考:https://element.eleme.cn/#/zh-CN/component/custom-theme /* 改变主题色变量 */ $--color-primary: #545C64; $--color-success: #27B6AF; $--menu-background-color: #1D212A; $--menu-item-font-color: #B3B8C3; $--menu-item-hover-fill: #1F2D3D; $--main-padding: 15px; /* 改变 icon 字体路径变量,必需 */ $--font-path: '~element-ui/lib/theme-chalk/fonts'; // 通用的布局等样式 @import "../common";
common.scss
片段:
// 自定义变量 $---menu--inline-background-color: #13161C !default; $---index-header-height: 50px !default; $---padding-common: 15px !default; $---margin-common: 15px !default; $---border-line-color: #E6E6E6 !default; @import "~element-ui/packages/theme-chalk/src/index"; .el-menu-item.is-active { color: $--color-white; background-color: $--menu-item-hover-fill; font-weight: $--font-weight-primary; } // .............更多见GitHub源文件
在main.js
中引入
// 样式配置 import './assets/css/main.scss'
动态主题
定义好模板主题文件,这里列举了defaut、simple两个主题
main.scss
主要内容:
// 实际样式引入 .theme-simple { @import "src/assets/themes/simple/index"; } .theme-default { @import "src/assets/themes/default/index"; }
切换主题
改变body的样式名称即可,调用$changeTheme(theme)
:
const $themeList = [ { id: 'theme-default', name: '默认主题' }, { id: 'theme-simple', name: '简单主题' } ] Vue.prototype.$changeTheme = function (theme = $themeList[0]) { const body = document.querySelector('body') $themeList.forEach(t => { body.classList.remove(t.id) }) body.classList.add(theme.id) store.dispatch('Theme/changeTheme', theme) // 暂时保存到store里面 }
Tips: 图标在主题样式显示有点问题,使用font-face兼容下
//***********这块font定义是为了修复问题******************** $--font-path: '~element-ui/lib/theme-chalk/fonts'; @font-face { font-family: 'element-icons'; src: url('#{$--font-path}/element-icons.woff') format('woff'), url('#{$--font-path}/element-icons.ttf') format('truetype'); font-weight: normal; font-display: auto; font-style: normal; }
做好国际化
i18n
一、 使用国际化来更改咱们的项目语言
简单介绍下i18n如何用
1. 安装:
//使用yarn yarn add vue-i18n //npm npm i vue-i18n -S
2. 使用:
系统中使用它,必须通过 Vue.use() 明确地安装 vue-i18n:
src/i18n/index.js
//src/i18n/index.js import Vue from 'vue' import VueI18n from 'vue-i18n' Vue.use(VueI18n) // 准备翻译的语言环境信息 const messages = { en: { message: { hello: 'hello world' } }, ja: { message: { hello: 'こんにちは、世界' } } } // 通过选项创建 VueI18n 实例 const i18n = new VueI18n({ locale: 'ja', // 设置地区 messages // 设置地区信息 })
3. 将i18n实例挂载在Vue的option中
import Vue from 'vue' import i18n from "./src/i18n/index.js" new Vue({ i18n })
4. 视图显示
<div id="app"> <p>{{ $t("message.hello") }}</p> </div> ------------------------------------ <!-- 展示效果如下 --> <div id="app"> <p>hello world</p> </div>
在插值中使用$t
函数就可以了
二、vue-cli项目中使用
1. 创建i18n文件结构
目录结构如下:
这里列举了两种语言分别是:en
英文
和zh
中文
en.js
export default { table: { // 假如用于翻译表格 date: "Date", name: "Name", address: "Address" }, menu: {}, // 假如项目中日后还有菜单 tabs: {} // tab切换等 }
zh.js
export default { table: { date: "日期", name: "姓名", address: "地址" }, menu: {}, tabs: {} }
config文件夹下面的index.js,代码如下(二者都可以):
乞丐版:
import en from './config/en' import id from './config/id' import ja from './config/ja' import ae from './config/ae' import am from './config/am' import ca from './config/ca' import al from './config/al' .....
至尊版:
import Vue from "vue" import VueI18n from "vue-i18n" Vue.use(VueI18n)//注入到所有的子组件 //require.context(path,deep,regExp) //有3个方法 分别是keys() // 至尊版 let langFileds = require.context('./config', false, /\.js$/) let regExp = /\.\/([^\.\/]+)\.([^\.]+)$/ //正则用于匹配 ./en.js中的'en' // regExp.exec('./en.js') let messages = {} //声明一个数据模型,对应i18n中的message属性 langFileds.keys().forEach(key => { let prop = regExp.exec(key)[1] //正则匹配en|zh这样的值 //messages[prop]相当于 messages['en'] = {table:{...}} messages[prop] = langFileds(key).default }) console.log(messages); console.log(langFileds('./en.js')); let locale = localStorage.getItem('lang') || "zh" //从localstorag中获取 export default new VueI18n({ locale,//指定语言字段 messages//定义语言字段 })
2. 修改main.js
import Vue from 'vue' import App from './App.vue' import ElementUI from "element-ui" // 需要安装 element-ui import 'element-ui/lib/theme-chalk/index.css'; Vue.config.productionTip = false Vue.use(ElementUI) import i18n from "./i18n" // new Vue({ render: h => h(App), i18n // 挂载 }).$mount('#app')
3. 具体使用demo
app.vue
<template> <div id="app"> <template> <el-table :data="tableData" style="width: 100%"> <el-table-column prop="date" :label="$t('table.date')" width="180"> </el-table-column> <el-table-column prop="name" :label="$t('table.name')" width="180"> </el-table-column> <el-table-column prop="address" :label="$t('table.address')"> </el-table-column> </el-table> </template> <el-button type="primary" @click="change('zh')">点击切换中文</el-button> <el-button type="primary" @click="change('en')">点击切换英文</el-button> <el-button type="primary" </div> </template> <script> export default { mounted() { console.log(this.$i18n.t('table.date')); }, methods: { change(lang) { //切换方法 localStorage.setItem('lang', lang) window.location.reload() //localSotrage是不响应的,为了演示效果所以直接调用刷新 } }, data() { return { tableData: [{ date: '2016-05-02', name: '王小虎', address: '上海市普陀区金沙江路 1518 弄' }] } } } </script> <style> #app { width: 50%; } </style>
构建打包发布
1. 打包配置如下:
build: { env: require('./prod.env'), index: path.resolve(__dirname, '../dist/index.html'), assetsRoot: path.resolve(__dirname, '../dist'), assetsSubDirectory: 'static', assetsPublicPath: './', productionSourceMap: true, // 默认情况下,Gzip 关闭了许多流行的静态主机,例如 // Surge 或 Netlify 已经为您压缩了所有静态资产。 // 在设置为 `true` 之前,请确保: // npm install --save-dev compression-webpack-plugin productionGzip: false, productionGzipExtensions: ['js', 'css'], // 运行带有额外参数的构建命令 // 构建完成后查看包分析器报告: // `npm run build --report` // 设置为 `true` 或 `false` 以始终打开或关闭它 bundleAnalyzerReport: process.env.npm_config_report }
2. 一般部署,我们会结合Nginx一起使用
安装&启动
# 安装,安装完成后使用nginx -v检查,如果输出nginx的版本信息表明安装成功 sudo apt-get install nginx # 启动 sudo service nginx start
3. 修改nginx配置
nginx的配置文件就在/etc/nginx文件夹
/etc/nginx/sites-available/default
nginx代理的根目录是/var/www/html
mkdir /www echo 'Hello world' > /www/index.html
4. 同步到服务器
在git-bash或者powershell使用scp指令,如果是linux环境开发,还可以使用rsync指令:
scp -r dist/* root@117.78.4.26:/www 或 rsync -avr --delete-after dist/* root@117.78.4.26:/www
package.json脚本,方便,提高效率
"scripts": { "build": "vue-cli-service build", "push": "yarn build && scp -r dist/* root@117.78.4.26:/www" },
当然啦,对于history、与hash模式,对应微调下即可~
做好组件的单元测试
Vue 的单文件组件使得为组件撰写隔离的单元测试这件事更加直接
组件的单元测试有很多好处:
- 提供描述组件行为的文档
- 节省手动测试的时间
- 减少研发新特性时产生的 bug
- 改进设计
- 促进重构
一个简单的Demo:
<template> <div> <div class="message"> {{ message }} </div> Enter your username: <input v-model="username"> <div v-if="error" class="error" > Please enter a username with at least seven letters. </div> </div> </template> <script> export default { name: 'Foo', data () { return { message: 'Welcome to the Vue.js cookbook', username: '' } }, computed: { error () { return this.username.trim().length < 7 } } } </script>
单元测试,代码如下:
import { shallowMount } from '@vue/test-utils' import Foo from './Foo' const factory = (values = {}) => { return shallowMount(Foo, { data () { return { ...values } } }) } describe('Foo', () => { it('renders a welcome message', () => { const wrapper = factory() expect(wrapper.find('.message').text()).toEqual("Welcome to the Vue.js cookbook") }) it('renders an error when username is less than 7 characters', () => { const wrapper = factory({ username: '' }) expect(wrapper.find('.error').exists()).toBeTruthy() }) it('renders an error when username is whitespace', () => { const wrapper = factory({ username: ' '.repeat(7) }) expect(wrapper.find('.error').exists()).toBeTruthy() }) it('does not render an error when username is 7 characters or more', () => { const wrapper = factory({ username: 'Lachlan' }) expect(wrapper.find('.error').exists()).toBeFalsy() }) })
Tips: 工厂函数将 values
对象合并到了 data
并返回了一个新的 wrapper
实例。好处有两个:
1. 不需要在每个测试中重复 const wrapper = shallowMount(Foo)
。
2. 当我们想为更复杂的组件在每个测试中伪造或存根一个方法或计算属性时,你只需要声明一次即可。
Vue Test Utils 及庞大的 JavaScript 生态系统提供了大量的工具促进 100% 的测试覆盖率。
推荐阅读:
https://v1.test-utils.vuejs.org/zh/guides/#%E8%B5%B7%E6%AD%A5
四、总结
在我们阅读完官方文档后,我们一定会进行更深层次的学习,比如看下框架底层是如何运行的,以及源码的阅读。
这里广东靓仔给下一些小建议:
- 在看源码前,我们先去官方文档复习下框架设计理念、源码分层设计
- 阅读下框架官方开发人员写的相关文章
- 借助框架的调用栈来进行源码的阅读,通过这个执行流程,我们就完整的对源码进行了一个初步的了解
- 接下来再对源码执行过程中涉及的所有函数逻辑梳理一遍