这篇文章总结了vue项目标所碰到的题目,包括跨域、用户认证、接口统一治理、路由设置、兼容性处置惩罚,机能优化等内容。
项目github地点 :
一、环境依靠装置
1. node环境
1.1 node和npm环境的装置
依据以下教程装置,然后设置好环境变量
http://www.runoob.com/nodejs/…
视频教程 http://101.110.118.22/github….
centos假如装不上看这里:https://www.rosehosting.com/b…
1.2 为npm变动源
npm默许运用的源的效劳器在国外下载速率慢,所以须要替代源
以下两种要领任选一种
1.2.1运用cnpm替代npm
参考链接:
https://npm.taobao.org/
# 装置
npm install -g cnpm --registry=https://registry.npm.taobao.org
#装置完cnpm,今后再根据依靠就要运用cnpm
cnpm install [包名]
1.2.2为npm替代源
修正源为淘宝的源
npm config set registry http://registry.npm.taobao.org/
我们在宣布本身包的时刻须要将官方的源改回来
npm config set registry https://registry.npmjs.org/
1.3 治理(更新)nodejs的版本
切换nodejs版本有两种体式格局,离别是
nvm
和
n
,n更简朴引荐运用
运用n治理nodejs版本
#装置
npm install -g n
#运用n下载所需node版本
n 版本号
#下载最新版本
n latest
# 切换版本
输入 n,
然后选中所需版本
#以指定的版原本实行版本
n use 7.4.0 index.js
linux运用n装置新版本nodejs今后,假如node -v
照样本来的版本,那末就须要转变一下环境变量
vim .bash_profile
export NODE_HOME=/usr/local #NODE_HOME改成新版本nodejs装置的目次,假如找不到,find / -name node
export PATH=$NODE_HOME/bin:$PATH
export NODE_PATH=$NODE_HOME/lib/node_modules:$PATH
修正环境变量参考:https://blog.csdn.net/yi412/a…
1.4 package.json文件详解
2. vue脚手架
vue-cli如今已更新到3版本,vue-cli3把webpack相干的设置隐蔽起来了,一切的设置都在vue.config.js文件夹中,所以运用vue-cli3须要的webpack程度较高,提议运用vue-cli2
3.1 vue-cli2.x装置
参考链接:https://github.com/vuejs/vue-…
装置:
npm install -g vue-cli
用法:
$ vue init < template-name > < project-name >
例:
$ vue init webpack my-project
如今可用的模块包括:
- webpack – 一个功用完全的Webpack + vue-loader设置,具有热重载,linting,测试和css提取功用。
- webpack-simple – 一个简朴的Webpack + vue-loader设置,用于疾速原型设想。
- browserify -全功用Browserify + vueify设置用热重装载,linting&单元测试。
- browserify -simple – 一个简朴的Browserify + vueify设置,用于疾速原型设想。
- pwa – 基于webpack模板的vue-cli的PWA模板
- simple – 单个HTML文件中最简朴的Vue设置
3.2 vue-cli3.x装置及设置(仅供参考)
vue-cli3x的官方文档:https://cli.vuejs.org/
Vue-cli3 中vue.config.js文件设置参考文档:https://cli.vuejs.org/zh/conf…
Vue CLI 的包称号由 vue-cli
改成了 @vue/cli
。 假如你已全局装置了旧版本的 vue-cli
(1.x 或 2.x),你须要先经由历程 npm uninstall vue-cli -g
或 yarn global remove vue-cli
卸载它。
装置
npm install -g @vue/cli
装置了vue-cli3假如还想运用vue-cli2的init功用,须要装置一个桥接功用
npm install -g @vue/cli-init
// vue.config.js 设置申明
//官方vue.config.js 参考文档 https://cli.vuejs.org/zh/config/#css-loaderoptions
// 这里只列一部份,细致设置参考文档
module.exports = {
// 布置临盆环境和开辟环境下的URL。
// 默许状况下,Vue CLI 会假定你的运用是被布置在一个域名的根途径上
//比方 https://www.my-app.com/。假如运用被布置在一个子途径上,你就须要用这个选项指定这个子途径。比方,假如你的运用被布置在 https://www.my-app.com/my-app/,则设置 baseUrl 为 /my-app/。
baseUrl: process.env.NODE_ENV === "production" ? "./" : "/",
// outputDir: 在npm run build 或 yarn build 时 ,天生文件的目次称号(要和baseUrl的临盆环境途径一致)
outputDir: "dist",
//用于安排天生的静态资本 (js、css、img、fonts) 的;(项目打包今后,静态资本会放在这个文件夹下)
assetsDir: "assets",
//指定天生的 index.html 的输出途径 (打包今后,转变体系默许的index.html的文件名)
// indexPath: "myIndex.html",
//默许状况下,天生的静态资本在它们的文件名中包括了 hash 以便更好的掌握缓存。你可以经由历程将这个选项设为 false 来封闭文件名哈希。(false的时刻就是让本来的文件名不转变)
filenameHashing: false,
// lintOnSave:{ type:Boolean default:true } 问你是不是运用eslint
`lintOnSave`: true,
//假如你想要在临盆构建时禁用 eslint-loader,你可以用以下设置
// lintOnSave: process.env.NODE_ENV !== 'production',
//是不是运用包括运转时编译器的 Vue 构建版本。设置为 true 后你便可以在 Vue 组件中运用 template 选项了,然则这会让你的运用分外增添 10kb 摆布。(默许false)
// runtimeCompiler: false,
/**
* 假如你不须要临盆环境的 source map,可以将其设置为 false 以加快临盆环境构建。
* 打包今后发明map文件过大,项目文件体积很大,设置为false便可以不输出map文件
* map文件的作用在于:项目打包后,代码都是经由紧缩加密的,假如运转时报错,输出的毛病信息没法准确得知是那里的代码报错。
* 有了map便可以像未加密的代码一样,准确的输出是哪一行哪一列有错。
* */
productionSourceMap: false,
// 它支撑webPack-dev-server的一切选项
devServer: {
host: "localhost",
port: 1111, // 端口号
https: false, // https:{type:Boolean}
open: true, //设置自动启动浏览器
// proxy: 'http://localhost:4000' // 设置跨域处置惩罚,只要一个代办
// 设置多个代办
proxy: {
"/api": {
target: "<url>",
ws: true,
changeOrigin: true
},
"/foo": {
target: "<other_url>"
}
}
}
};
二、开辟
以下内容依靠环境为 : vue-cli 版本2.9.x
项目github地点 :
装置完以上依靠后,便可以最先一个项目了,我们先看下后端api的定义
前后端交互报文定义以及数据api接口
前后端交互报文定义
要求
http request header{ //除登录注册之外的要求,提议要求时要在要求头中到场token
authorization:jwt
}
http request body{
}
返回
http response header{
}
http response body{
code:营业处置惩罚状况码
msg:营业处置惩罚形貌
token:jwt token
data:营业数据
}
项目中运用的背景api定义以下
注:效劳器端的host为118.24.85.97,端口为22222
1.测试api是不是可用
- uri: http://118.24.85.97:22222/api
- 形貌:测试接口是不是能用,能用的话返回 ‘API WORDS’字符串
- 要求范例 GET
- 要求参数 无
- 返回值 {‘Api Works’}
2.注册
- uri: http://118.24.85.97:22222/api/users/reg
- 形貌:注册
- 要求范例 POST
- 要求参数
序号 | 参数名 | 是不是必填 | 形貌 |
---|---|---|---|
1 | name | y | 用户名 |
2 | pass | y | 暗码 |
- 返回参数 不重要
3.登录
- uri: http://118.24.85.97:22222/api/users/login
- 形貌:登录
- 要求范例 POST
- 要求参数
序号 | 参数名 | 是不是必填 | 形貌 |
---|---|---|---|
1 | name | y | 用户名 |
2 | pass | y | 暗码 |
- 返回参数
序号 | 参数名 | 形貌 |
---|---|---|
1 | msg | ok |
2 | token | 用于考证用户身份的token |
4.猎取当前用户信息
- uri: http://118.24.85.97:22222/api/users/current
- 形貌:猎取用户信息
- 要求范例 GET
- 要求参数 无
- 返回参数
序号 | 参数名 | 形貌 |
---|---|---|
1 | id | 用户id |
2 | token | 用于考证用户身份的token |
0.初始化项目
在终端中输入
vue init webpack vue2_template
然后会有一些选项让你选,根据项目需求挑选,比方我不须要eslint,unit test,便可以选No,如今选no未来假如须要的话也可以本身装置
装置完成今后,根据提醒切换到相应目次,实行相应指令,然后在浏览器翻开网址,如许一个简朴的vue项目就启动起来了
1. 项目文件引见
全部文件引见:
注重:
- 开辟重要运用src文件夹
- webpack的设置文件设置文件详解看这里:https://segmentfault.com/a/11…
- package.json设置详解 http://javascript.ruanyifeng….
src目次引见
起首在src目次下新建一个文件夹views,用来放我们的重要页面,然后在assets文件夹中竖立fonts styles imgs,用来寄存相应的资本,建完今后,文件夹以下
2. 跨域、axios设置与api治理
在这个项目中,我们运用axios举行数据要求
axios中文文档:
https://www.kancloud.cn/yunye…
# 装置axios
npm/cnpm i axios -S # -S 指装置到package.json中的dependencies中
装置完成后,我们要在main.js中引入,然后测试一下是不是胜利引入
//main.js文件
import axios from 'axios'
axios.get('https://api.github.com/users?since=10') //运用github接口做一下测试
.then(res=>console.log(res))
.catch(err=>console.log(err))
浏览器显现以下信息,申明引入胜利
github供应的接口设置了cors,所以我们可以可以在浏览器平常接见到,但cors兼容性最低到ie10,而且背景不一定会设置cors,所以在开辟时我们须要设置一下跨域
参考链接:
2.1设置跨域
先找个没有设置cors的api运用axios接见一下
axios.get('http://118.24.85.97:22222/api')
.then(res=>console.log(res))
.catch(err=>console.log(err))
浏览器会因为同源战略报错
下面举行跨域的设置
设置目次 config/index.js 13行
proxyTable: {
'/apis':{
target:'http://118.24.85.97:22222',//背景地点 proxyTable 把/apis映射成target 即 /apis=http://118.24.85.97:22222
changeOrigin:true,//是不是跨域
pathRewrite:{
'^/apis':''
}
}
}
再举行接见数据时就要在接口前面加上/apis(/apis就相当于http://118.24.85.97:22222)
axios.get('/apis/api')
.then(res=>console.log(res))
.catch(err=>console.log(err))
然后就发明浏览器接见胜利了
proxyTable道理:跨域是浏览器制止的,效劳端并不制止跨域 ,所以浏览器可以发给本身的效劳端然后,由本身的效劳端再转发给要跨域的效劳端,做一层代办。proxyTable运用的是http-proxy-middleware
中间件,内部用的是http-proxy
以上设置的跨域是开辟环境下的,在临盆环境就自动失效了,而且如许设置我们开辟时接见接口时,都要写成/apis/xxx/xxx
花样,在布置到效劳器中时,我们要把/apis拿掉,才接见到准确的url。有两种要领,一种是在开辟环境中设置(经由历程axios的baseURL),另一种是在效劳器上修正nginx的设置设置。
2.2临盆环境去除/apis前缀
在这里细致说下第一种体式格局,道理是如许的:
经由历程检测是开辟环境和临盆环境,设置差别的baseURL,使临盆环境和开辟环境都能准确接见url
在src目次下新建一个apis
目次,然后在apis目次下新建一个api.config.js
文件
//推断是不是是临盆环境
//webpack在开辟环境和临盆环境离别实行差别的js文件,process.env.NODE_ENV设置了差别的值,process.env.NODE_ENV在临盆环境中值为'production'(这个值是在build/build.js中第4行设置的)
var isPro = process.env.NODE_ENV=== 'production'
// 假如是临盆环境 我们就运用效劳器的uri,假如是开辟环境,我们就增加/apis前缀
module.exports = {
baseUrl: isPro ? 'http://118.24.85.97:22222' : '/apis'
}
在main.js中引入这个文件,然后设置axios的baseURL
//引入api.config.js文件,然后设置axios的baseURL
import apiConfig from './apis/api.config'
axios.defaults.baseURL=apiConfig.baseUrl
再来测试一下不加/apis的接口
axios.get('/api')
.then(res=>console.log(res))
.catch(err=>console.log(err))
浏览器显现是ok的。如许我们今后运用axios接见接口便可以不加/apis了,打包后接见也没必要手动去除/apis
2.3 api统一治理
在vue项目开辟历程当中,会涉及到许多接口的处置惩罚,当项目足够大时,就须要统一治理接口。
细致要领应当挺多的,这里只引见一种:运用axios+async/await举行接口的统一治理
平常来讲,背景的接口是分模块的,比方我们背景的测试接口
- 身份认证 /api/login /api/reg
- 用户信息 /v1/api/user
我们起首在src目次下新建一个apis文件夹,背景供应的一切接口都在这里定义
第二步,根据背景供应的模块新建js文件,我们新建user.js
auth.js
第三步,引入axios,做相应的设置
在apis目次下新建一个http.js,在内里做axios相应的设置
- 我们上文中是在main.js文件引入的axios,设置的baseURL,以上代码可以去除,改成在http.js中引入
- 我们做的重如果:引入axios,建立一个axios的实例(实例的功用和axios一样)
import axios from 'axios'
import apiConfig from './api.config'
//建立axios的一个实例
var instance = axios.create({
baseURL:apiConfig.baseUrl,
timeout: 6000
})
//------------------- 一、要求阻拦器 背面引见
instance.interceptors.request.use(function (config) {
return config;
}, function (error) {
// 对要求毛病做些什么
return Promise.reject(error);
});
//----------------- 二、相应阻拦器 背面引见
instance.interceptors.response.use(function (response) {
return response.data;
}, function (error) {
// 对相应毛病做点什么
return Promise.reject(error);
});
/**
* 运用es6的export default导出了一个函数,导出的函数替代axios去帮我们要求数据,
* 函数的参数及返回值以下:
* @param {String} method 要求的要领:get、post、delete、put
* @param {String} url 要求的url:
* @param {Object} data 要求的参数
* @returns {Promise} 返回一个promise对象,实在就相当于axios要求数据的返回值
*/
export default function (method, url, data = null) {
method = method.toLowerCase();
if (method == 'post') {
return instance.post(url, data)
} else if (method == 'get') {
return instance.get(url, { params: data })
} else if (method == 'delete') {
return instance.delete(url, { params: data })
}else if(method == 'put'){
return instance.put(url,data)
}else{
console.error('未知的method'+method)
return false
}
}
第四步,在apis/xxx.js
文件中引入http.js导出的函数,拿个中一个文件auth.js
申明
//auth.js 用于定义用户的登录、注册、注销等
import req from './http.js'
//定义接口
//在这里定义了一个上岸的接口,把上岸的接口暴露出去给组件运用
export const LOGIN =params=>req('post','/api/users/login',params)
//这里运用了箭头函数,转换一下写法:
// export const LOGIN=function(params){
// return req('post','/api/login',params)
// }
//定义注册接口
export const REG =params=>req('post','/api/users/reg',params)
末了一步,在须要用的该api的组件中引入并挪用,我们在App.vue文件中测试下
<template>
<div>
<h2>登录</h2>
用户名<input type="text" v-model="user">
暗码<input type="password" v-model="pass">
<input type="button" @click="reg" value="注册">
<input type="button" @click="login" value="登录">
</div>
</template>
<script>
import {LOGIN,REG} from '../../apis/auth.js'
export default {
data() {
return {
user:'',
pass:'',
err:[]
}
},
methods: {
async reg(){
try {
const data = await REG({ name: this.user,pass: this.pass })
console.log(data)
alert(JSON.stringify(data))
this.cleanForm()
} catch (error) {
console.log(error)
}
},
async login(){
try {
const data = await LOGIN({ name: this.user,pass: this.pass })
alert(JSON.stringify(data))
this.cleanForm()
} catch (error) {
console.log(error)
}
},
cleanForm(){
this.user=''
this.pass=''
}
},
}
</script>
注:假如要翻开Login.vue,须要设置对应的路由
上面的代码引入了auth.js
定义的api,并在对应的要领中运用。代码顶用到了async/await,实在很简朴,可以假定async是个标识,申明这个函数中有异步要求,await翻译为’等’,背面接一个异步要求,等背面的异步要求实行完成今后,会把结果赋给=
左边的值
总结一下,像上面那样定义接口虽然贫苦点,但有两个优点:
- 代码看起来范例,一切的接口都在一个文件夹定义,没必要疏散的各个组件,保护起来简朴,比方背景的一些url变了,改起来也轻易
- 可以做到接口一次定义,随处运用
3. 路由设置
Vue Router官方文档
https://router.vuejs.org/zh/
3.1 最简设置
路由的设置文件在router/index.js文件中
先引入文件,再举行设置
起首在views目次中新建以下页面
,主页(Home/Home.vue),登录页(Login/Login.vue),测试页(Test/Test.vue)
然后设置下路由
import Vue from 'vue'
import Router from 'vue-router'
//@示意 src目次 webpack的设置在webpack.base.conf.js第29行 alias{'@':resolve('src')}
import Home from '@/views/Home/Home.vue'
import Login from '@/views/Login/Login.vue'
import Test from '@/views/Test/Test.vue'
Vue.use(Router)
export default new Router({
routes: [//路由划定规矩
{
path: '/',
name: 'Home',
component: Home
},
{
path:'/login',
name:'Login',
component:Login
},
{
path:'/test',
name:'Test',
component:Test
}
]
})
路由划定规矩在routes
中举行设置,routes
是一个数组,接收一系列路由划定规矩,每一个路由划定规矩是一个对象,包括途径、路由名字,和途径婚配的组件,提议给每一个路由加个名字,在背面可能会用到。
翻开浏览器,输入相应的url检察设置的路由是不是准确,不准确的话搜检下本身的设置
3.2设置路由懒加载
参考文档:
路由懒加载官方文档:https://router.vuejs.org/zh/g…
webpack之mainfest解读:https://github.com/younth/blo…
当打包构建运用时,Javascript 包会变得异常大,影响页面加载。假如我们能把差别路由对应的组件分割成差别的代码块,然后当路由被接见的时刻才加载对应组件,如许就越发高效了。所以,懒加载的寄义是当路由被接见时再去加载对应的js代码。
起首,不做路由懒加载的状况下,我们打包一下(切换到项目目次,实行npm run build
),然后会发明项目下临盆了3个js文件
简朴引见一下作用:
- vendor.js 第三方库,平常是 node_modules内里的依靠举行打包 体积最大
- app.js 进口js打包的结果,即我们编写的一切代码都邑打包进去
- manifest.js 重如果一些异步加载的完成要领(经由历程竖立script体式格局动态引入js),内容上包括异步js的文件名和途径。
然后我们完成一下路由懒加载 @/router/router.js
import Vue from 'vue'
import Router from 'vue-router'
// import Home from '@/views/Home/Home.vue'
// import Login from '@/views/Login/Login.vue'
// import Test from '@/views/Test/Test.vue'
// 懒加载体式格局
const Home=()=>import('@/views/Home/Home.vue')
const Login=()=>import('@/views/Login/Login.vue')
const Test=()=>import('@/views/Test/Test.vue')
Vue.use(Router)
export default new Router({
routes: [
{
path: '/',
name: 'Home',
component: Home
},
{
path:'/login',
name:'Login',
component:Login
},
{
path:'/test',
name:'Test',
component:Test
}
]
})
懒加载只是转变了一下组件的援用体式格局,由本来的直接引入变成异步引入,当我们接见对应的路由path时,才会加载相应的路由组件。
设置完成后再实行一次打包,结果以下:
我们会发明目次中多出来3个js文件,而且app.js
文件变小了。这申明设置了懒加载今后,app.js中其他组件的内容被抽离出来,分配到各自的js文件中。设置懒加载今后,刚最先翻开页面只会加载app.js文件,只要在用户点击相应路由时,才会加载对应的js代码。当我们的营业代码异常多时,懒加载是个很好的挑选。
3.3 设置history情势
设置history情势有两个缘由,一是因为hash情势看很丑,二是因为预加载要用到History情势,设置异常简朴,只须要设置属性mode
的值为’history’
const router = new VueRouter({
mode: 'history',
routes: [...]
})
不过这类体式格局须要背景的支撑,当婚配不到url时,返回url/index.html页面
nginx设置以下
location / {
try_files $uri /index.html;
}
4. 权限治理
参考链接:
json web token入门教程 http://www.ruanyifeng.com/blo…
jwt官网 https://jwt.io/
4.1 token考证
我们经由历程jwt举行用户认证,jwt的道理是:效劳器认证今后,天生一个json对象,发还给用户.
{
"id":"001",
"姓名":"小明",
"角色":"治理员",
"到期时候":"2019年3月3日12时30分"
}
今后用户与效劳端通讯的时刻,都要发还这个json对象。效劳器完端赖这个对象认定用户身份(平常是经由历程这个对象的中id去数据库要求数据)。为了防备用户修改数据,效劳器会在天生这个对象的时刻,加上署名。就像这类情势:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
关于JWT保留更新的营业流程以下:
- 保留:登录后保留token
- 增加:每次发送要求之前搜检token是不是存在,存在,增加到要求头中,发送要求
- 更新:每次发送要求效劳器返回数据今后更新token
重要逻辑包括:
- 登录今后,在
localStorage
中保留token - 每次发送要求之前,运用axios要求阻拦器将token放到要求头中
- 每次发送要求效劳器返回数据今后在axios的相应阻拦器中更新token
//1.登录今后保留token login.vue
async login(){
const data = await LOGIN({ name: this.user,pass: this.pass })
//保留token
localStorage.setItem('token',data.token)
//检察是不是保留胜利
console.log(localStorage.getItem('token'))
}
//每次发送要求之前,讲token放到要求头中 api/http.js
//---运用axios的要求阻拦器,每次发送要求之前阻拦一下
instance.interceptors.request.use(function (config) {
// 给头增加token
if (localStorage.getItem('token')){//存在token,到场头
config.headers.authorization=localStorage.getItem('token')
}
return config;
}, function (error) {
// 对要求毛病做些什么
return Promise.reject(error);
});
//完成今后,记得发送一个要求,看看是不是准确增加token
//---相应阻拦器,效劳器相应后先抵达这里
instance.interceptors.response.use(function (response) {
if(response.data.code=='2000'){//胜利相应,更新token
if(response.data.token){
localStorage.setItem('token',response.data.token)
}
}else{
//毛病处置惩罚 依据差别的状况码,举行毛病处置惩罚
}
return response.data;
}, function (error) {
// 对相应毛病做点什么
return Promise.reject(error);
});
4.2 对页面的接见权限
除了对token的操纵,我们还要推断用户有无权限接见这个页面(有些页面是用户必需登录才接见的),细致设置要运用Vue Router的导航守御
在全局前置守御中举行考证
//在router/index.js举行设置
//在每次举行路由跳转之前举行
router.beforeEach((to,from,next)=>{//增添登录考证
const isLogin=localStorage.getItem('token')?true:false;
if(to.path=='/login'){//假如是登录页面,不须要token
next();
}else{//假如不是登录页面就要推断是不是登录
isLogin?next():next('/login');
}
})
5. 将界面交给第三方UI库
iview官网:
https://www.iviewui.com/
为节约开辟时候,我们往往会运用一些第三方ui库,比方iview elementui等
我们在这里只引见iview,其他ui库迥然差别
iview的装置与引入
装置
cnpm i iview --save
按需引入组件
官网说,须要下载插件才按需引入,官网申明,然则不下彷佛也可以平常引入
//在main.js文件中引入项目须要的组件
import {Button,Table,Message} from 'iview'
//然后注册组件
Vue.component('Button',Button)
Vue.component('Table',Table)
Vue.component('Message',Message)
如许注册的话太烦琐,所以须要优化一下
//main.js
import {Button,Table,Message} from 'iview'
const iviewComs={Button,Table,Message}
Object.keys(iviewComs).forEach(key=>{Vue.component(key,component[key])})
代码都写在main.js中显得太拥堵,我们可以把代码拿出去,写成一个插件
我们在components文件夹中新建一个文件iview-coms
,用来放iview中引入的组件
//components/iview-coms.js
import {Button,Table,Message} from 'iview'
const components={Button,Table,Message}
const install = function(Vue, opts = {}){
Object.keys(components).forEach(key=>{
Vue.component(key,components[key])
})
}
export default install
然后在main.js中引入,use
这个插件
import iviewComs from './components/iview-coms'
Vue.use(iviewComs)
ok了,接下来看自定义主题
自定义主题
官网链接:https://www.iviewui.com/docs/…
道理很简朴,就是把ivew的less文件引入,而且掩盖掉,然后在main.js文件中引入本身的less文件
起首,我们须要下载剖析less文件的loader ,less
和less-loader
,这里有个坑,下载less的时刻要下载3版本以下的,不然会报一堆毛病
cnpm i less@2.7.2 less-loader -D
下载完就ok了,不须要在webpack中举行设置,因为已设置好了
然后,在assets/styles/base.less(没有须要本身新建)中,引入iview的款式文件,而且掩盖掉
默许变量列表:https://github.com/iview/ivie…
//assets/styles/base.less
//------ 引入iview款式
@import '~iview/src/styles/index.less';
//------ 掩盖iview的款式
@primary-color: #E91E63;
@error-color : #FF3300;
末了在main.js引入该less文件
//main.js
import './assets/styles/base.less'
此时,引入的组件便可以在.vue文件中运用了,看一下结果:
ok了。末了还要补充一下,在项目开辟历程当中,不可避免的要掩盖iview默许的款式,我们分为两种状况,一种是全局掩盖,一种是部份掩盖。
全局掩盖的话我们要新建一个less文件,比方叫cover-iview.less
一切掩盖iview款式的代码都放在这里,然后在base.less中引入这个文件。
部份掩盖的话要注重不要影响到别的款式,所以要充足利用less的作用域,比方我们只须要改home页面下的iview按钮款式,我们可以如许:
.home{
.ivu-btn{
}
}
6.开辟中注重题目
6.1编写本身的东西库插件
参考文档:
vue插件申明:https://cn.vuejs.org/v2/guide…
项目中往往会运用一些通用的函数,比方猎取当前时候、时候花样转化,防抖,撙节等,我们可以把这个公用的部份封装成插件,在main.js中引入。
起首,在src目次下新建utils
文件夹,在内里新建index.js
,utils.js
文件
我们在utils.js
中编写本身的东西库,然后导出
class Utils{
constructor(){
this.d=new Date();//date对象
this.instance=null;
}
static getInstance(){//单例情势
if(!this.instance){
this.instance = new Utils();
}
return this.instance;
}
pick(obj,arr){//pick({ a: 1, b: '2', 'c': 3 }, ['a', 'c']) =>{a:1,c:3}
return arr.reduce((acc,curr)=>{
return (curr in obj && (acc[curr] = obj[curr]), acc)
},{})
}
dateFormat(datetime,pattern=""){
let vWeek = ["礼拜天","礼拜一","礼拜二","礼拜三","礼拜四","礼拜五","礼拜六"];
let dt=new Date(datetime);
let y=dt.getFullYear();
let m=(dt.getMonth()+1).toString().padStart(2,'0');
let d=dt.getDate().toString().padStart(2,'0');
let hh=dt.getHours().toString().padStart(2,'0');
let mm=dt.getMinutes().toString().padStart(2,'0');
let ss=dt.getSeconds().toString().padStart(2,'0');
let vWeek_s = dt.getDay();//礼拜
if(pattern.toLowerCase() === 'yyyy-mm-dd'){
return `${y}-${m}-${d}`
}else if(pattern.toLowerCase() === 'mm-dd'){
return `${m}-${d}`
}else if(pattern.toLowerCase() === 'yyyymmddhhmmss'){
return `${y}${m}${d}${hh}${mm}${ss}`
}else {
return `${y}-${m}-${d} ${hh}:${mm}:${ss} ${vWeek[vWeek_s]}`
}
}
}
const UTIL = Utils.getInstance();
// console.log(UTIL.dateFormat(new Date(),'yyyymmddhhmmss')) //=>20190312110722
// console.log(UTIL.dateFormat(new Date()))//=>2019-03-12 11:07:22 礼拜二
// console.log(UTIL.pick({ a: 1, b: '2', 'c': 3 }, ['a', 'c']))//=>{a:1,c:3}
export default UTIL;
然后在index.js中编写插件,导出
//utils/index.js
import UTIL from './utils.js'
const UtilPlugin={}
UtilPlugin.install=function(Vue,options){//插件必需有install要领,接收两个参数,一个是Vue组织器,一个是参数
Vue.prototype.$utils=UTIL//在vue prototype上增加实例要领
}
export default UtilPlugin
末了在main.js中引入并use插件
// utils
import Util from './utils/index'
Vue.use(Util)
console.log(Vue.prototype.$util)//打印下是不是引入胜利
今后便可以在组件中经由历程运用this.$utils
挪用要领了
7. 兼容性处置惩罚
我们的目标是兼容到ie9,对ie8及以下的浏览器做相应的跳转处置惩罚(跳转到浏览器下载界面)
兼容性对一个顺序来讲是异常重要的,兼容性测试越早越好
7.1 对ie8及以下浏览器的跳转处置惩罚
在项目根目次下中的html中head中到场下面代码
<!--[if lte IE 8]><script>window.location.href="https://support.dmeng.net/upgrade-your-browser.html?referrer="+encodeURIComponent(window.location.href);</script><![endif]-->
目标是检测ie浏览器的版本,假如低于<=ie8,就跳转到下面这个页面
7.2 兼容ie9
7.2.1 ES6兼容
我们把浏览器调到ie9,然后看掌握台报错信息
报这个错的缘由是es6的新对象,新表达式,ie9不支撑,为处理这个题目,我们须要引入babel-polyfill
cnpm i babel-polyfill -D
装置完成今后,在main.js文件中引入
import 'babel-polyfill'
在项目运用 vue-cli
天生的代码中,根目次有一个 .babelrc
文件,这是项目运用 babel 的设置文件。在默许天生的模板内容中,增添 "useBuiltIns": "entry"
的设置内容,这是一个指定哪些内容须要被 polyfill(兼容) 的设置
useBuiltIns 有三个设置选项
-
false
– 不做任何操纵 -
entry
– 依据浏览器版本的支撑,将 polyfill 需求拆分引入,仅引入有浏览器不支撑的polyfill -
usage
– 检测代码中ES6/7/8
等的运用状况,仅仅加载代码顶用到的 polyfill
7.2.2竖立本身的polyfill
到场这些代码后,工程中大部份代码已可以兼容到ie9版本,但照样会有少部份不兼容的特征,比方requestAnimationFrame
、classList
等。关于这些内容,我们须要本身定义polyfill来处理,在src目次下新建一个文件夹polyfill,然后在polyfill文件夹下面建一个polyfill.js,我们在polyfill.js中到场我们的兼容代码
然后在main.js中引入这个文件
import './polyfill/polyfill'
处理兼容体式格局的准确姿态是:拿到ie9浏览器下的报错信息,去goole或许baidu搜刮,获得polyfill,然后到场到本身的polyfill.js文件中
三、优化
1. webpack3.x优化打包速率
我们实行一下npm run build
,结果以下:
全部打包历程花了32s摆布,如今我们的项目只是引入了相干的依靠,一些营业逻辑还没有写,打包速率就那末慢了,比及我们写完全部项目,打包速率还会继承变长,所以我们须要优化一下。
优化打包速率,我们修正的重如果
webpack.prod.conf.js
文件
替代代码紧缩东西
Webpack 默许供应的 UglifyJS 插件,因为采纳单线程紧缩,速率慢 ;
webpack-parallel-uglify-plugin 插件可以并行运转 UglifyJS 插件,越发充足而合理的运用 CPU 资本,这可以大大削减的构建时候;
//装置
cnpm i webpack-parallel-uglify-plugin -D
//设置 webpack.prod.conf.js
//起首删除项目中的 UglifyJsPlugin插件及设置,第二次打包时进步速率,要把.cache文件到场到gitignore中
// new webpack.optimize.UglifyJsPlugin({
// compress: {
// warnings: false,
// drop_console: true
// },
// sourceMap: true
// }),
//然后引入并运用我们适才装的插件
==注重:版本掌握东西提交时,要疏忽.cache
文件==
设置完后我们实行npm run build
,发明打包速率降到了23s
再实行一次npm run build
,发明打包速率降到了12s
时候下降那末多是因为文件没有修改,直接利用了缓存中的js文件
happypack开启多核构建项目
平常node.js是单线程实行编译,而happypack则是启动node的多线程举行构建,大大进步了构建速率。
起首装置,
修正webpack.base.conf.js
const HappyPack = require('happypack');
const os = require('os');
const happyThreadPool = HappyPack.ThreadPool({ size: os.cpus().length });
...
...
// 增添plugins
plugins: [
new HappyPack({
id: 'happy-babel-js',
loaders: ['babel-loader?cacheDirectory=true'],
threadPool: happyThreadPool,
})
]
...
...
// 修正对应loader
{
test: /\.js$/,
loader: 'happypack/loader?id=happy-babel-js',
include: [resolve('src'), resolve('test')],
}
设置完成,实行npm run build
what??并没有进步速率 不要用这个鬼东西了
hardSourceWebpackPlugin节约70%的时候
#装置
cnpm install --save-dev hard-source-webpack-plugin
运用,在webpack.prod.conf.js中引入并运用
const HardSourceWebpackPlugin = require('hard-source-webpack-plugin');
module.exports = {
context: // ...
entry: // ...
output: // ...
plugins: [
new HardSourceWebpackPlugin()
]
}
结果:
注:要第二次打包才见效
总结下,运用了三个插件,我们的打包速率从30s下降到4s,awesome!
2. webpack3.x优化首屏加载速率
起首要申明一下,首屏加载速率优化针对的是打包后dist文件。我们假如要在当地举行测试的话,须要当地有个效劳器,我们在这里运用nginx。
2.1当地装置nginx
在官网上找到本身体系合适的nginx版本,下载到当地
2.1.1window装置
- 解压文件
- 双击运转nginx.exe,在使命治理器中涌现nginx的历程,则示意装置胜利
2.1.2 mac/linux装置
#1.解压文件
tar -xzf nginx-1.14.0.tar.gz #mac可以运用解紧缩东西解压,没必要用敕令行
#2. 设置装置途径 --prefix指定装置途径 假定我要装到/usr/local/nginx文件夹中
./configure --prefix=/Users/best9/local/nginx
#编译
make
##装置
make install
装置完成后进入到—prefix
指定的文件夹中,实行ll
,会发明文件夹下有以下目次
我们要体贴就是我上面标出来的三个目次
进到sbin目次中,启动nginx顺序
cd sbin
#须要运用root权限,不然会报错 报错信息可以在日记中检察到,毛病日记目次 /logs/error.log
sudo ./nginx
平常的话,nginx会默许在localhost:80端口启动,在浏览器接见localhost
,就会显现默许界面
假如电脑的80端口被占用的话,在conf/nginx.conf
文件中修正端口
2.2 nginx常用敕令
nginx运用-s发送信号操纵运转中的历程,常用敕令以下:
注重:运用敕令须要在sbin
目次下
#启动nginx
./nginx
#马上住手效劳 -s stop
./nginx -s stop
#文雅地住手效劳 -s quit
./nginx -s quit
#重启效劳 -s reload
./nginx -s reload
2.3 nginx设置静态文件效劳器
我们在这里运用nginx设置一个最简朴的静态文件效劳器,更庞杂的设置稍后再讲
nginx的设置文件地点:conf/nginx.conf
运用vim或许其他编辑器翻开该文件,修正设置文件第43-45行:
vim conf/nginx.conf
location / {
alias /Users/best9/github/vue2_template/dist; #接见/相当于接见alias设置的目次
}
设置完成后保留,然后重启效劳
sudo ./sbin/nginx -s reload
要运用root权限重启
翻开浏览器接见localhost
因为没有登录,会自动跳转到登录界面
到这里静态文件效劳器就设置好了,但我们革新下页面,会报错404
这是因为我们运用了vue router的history情势,我们须要在nginx中到场以下设置
location / {
try_files $uri $uri/ /index.html;
}
然后重启nginx,再革新页面就没题目了
2.4 优化首屏加载速率
以上步骤停当后,我们便可以来优化加载速率了
翻开chrome的devTools面板,切换到Network
,禁用浏览器缓存,革新测试下加载速率,发明全部运用加载约莫须要1.97s,以下图:
把收集环境切换到Fast 3G
,再测试一次,发明加载用了7.56s,白屏时候6.89s
我们运用预衬着插件举行优化
2.4.1 预衬着
运用插件:prerender-spa-plugin
起首,装置 prerender-spa-plugin
,装置时件略长,因为其依靠了 phantomjs
cnpm install prerender-spa-plugin --save-dev
我们只在临盆环境中举行预衬着,修正 build/webpack.prod.conf.js
,在设置插件的处所到场以下代码。
//引入 预衬着插件
const PrerenderSpaP=require('prerender-spa-plugin')
//在plugins中设置
new PrerenderSpaP(
// 输出目次的绝对途径
path.join(__dirname,'../dist'),
//预衬着路由
['/home','/login']
)
再次实行打包,然后再举行测试:
发明白屏时候为4.10s,在弱网环境下,运用预衬着,约莫能缩减2.5秒的白屏时候
预衬着注重事项
- 预衬着的路由不能是动态加载的,不然会报webpackJsonp is not define的毛病,要想处理这个毛病,可以看这里 https://juejin.im/entry/5911a…
- 预衬着的路由不能是须要权限才接见的页面。预衬着的机制是在当地跑一个chromium浏览器,然后去爬取你预衬着页面的Html,假如你的页面须要权限(登录)才进入,就爬不到,也不会报错,终究只会衬着不须要权限的页面
举个例子:
插件设置以下:
new PrerenderPlugin({
staticDir:path.join(__dirname,'../dist')
routes:['/','/about','/login']
})
路由设置以下:
2.4.2 设置gzip紧缩
gzip官方文档
http://nginx.org/en/docs/http…
nginx默许是封闭gzip的,我们须要本身翻开,并举行一些设置:
gzip:on; #翻开gzip,封闭为off
gzip_min_length 1; #小于gzip_min_length,不举行紧缩(默许单元为byte)
gzip_comp_level 2; #紧缩级别
gzip_types text/plain text/css application/javascript text/javascript image/jpeg image/gif image/png;#指定范例举行gzip紧缩
设置完成后,我们再测试一下加载速率:
发明白屏时候为1.95s,加载文件的体积也变小了
四、布置
1. nginx设置反向代办
我们要在当地布置测试,所以背景的地点是127.0.0.1:22222
项目开辟完成后须要布置到效劳器,因为是前后端星散,所以前端的运用布置到nginx,后端的运用布置到本身对应的效劳器,所以我们须要设置一下,把后端的效劳器变成上游效劳,nginx做反向代办效劳器
反向代办:效劳器依据客户端的要求,从其关联的一组或多组后端效劳器上猎取资本,然后将这些资本返回给客户端。
因为上游效劳器(背景效劳器)要处置惩罚异常庞杂的逻辑,所以机能不怎么样,我们运用nginx作为反向代办效劳器后,可以将要求根据负载平衡算法代办给多台上游效劳器。设置以下:
以上设置是将一切的要求转发给上游效劳器,但假如我们只想将动态要求转发给上游效劳器,静态资本由nginx本身处置惩罚,便可以如许做:
推断是不是是背景api(依据location的婚配划定规矩),假如是的话,就举行转发
婚配划定规矩看这里:https://stackoverflow.com/que…
upstream local{
server 127.0.0.1:22222; #假定在当地布置
}
server{
listen:80;
server_name localhost;
location ~ /api/ { #以`/api/`开首的uri就行转发,不然不转发 ~代表正则表达式婚配
proxy_set_header: Host $host;
proxy_set_header: X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://local;
}
location / {
#... alias index等设置
}
}
这里须要注重一个题目:proxy_pass是转发要求的模块,当你接见localhost:80/api/users/login
时,会被转发到local
的地点,即127.0.0.1:22222/api/users/login
,所以开辟环境下接见背景接口的URI要写你布置到nginx的URI,而不是真正的背景地点(因为被转发了)
前端设置
//apis/api.config.js
//推断是不是是临盆环境
var isPro = process.env.NODE_ENV=== 'production'
module.exports = {
baseUrl: isPro ? 'http://localhost:80' : '/apis'//临盆环境下的baseURl是nginx的hoost:port
}
2. 延续布置
项目做完须要宣布到效劳器,但每次手动打包,然后ftp传上去的话就太贫苦了,所以我们的需求是:git或许svn提交后,自动打包宣布到效劳器。运用的东西是jenkins.
jenkins装置与启动
jenkins平常状况下会装在效劳器,但假如是同一个局域网的话,装在本机也可以
linux:
- https://blog.csdn.net/fenglai…
- https://www.jianshu.com/p/8a7… (centos)
- 设置文件地点 /etc/sysconfig/jenkins
- 事情空间 /var/lib/jenkins
windows下:
- 从Jenkins官网下载最新war文件。
- 运转
java -jar jenkins.war
即可。
mac:
- 从官网下载pkg文件
- 双击装置,装置今后本身就会启动
jenkins初始化
- jenkins的默许端口是8080,启动胜利后在浏览器翻开。
- 进入后会让我们输治理员暗码,翻开网页上提醒途径下的文件,复制暗码粘贴输入即可。
- 然后会让装置须要的插件,此处选默许即可,守候装置完成。
- 建立一个治理员账户。
- 上面都完成后会看到这个界面。
建立使命
在主页上点击建立
直接点保留
,然后去装置插件
装置插件
起首返回主页,然后点击左边菜单 体系治理
->插件治理
须要装置的插件有:
- Generic Webhook Trigger 完成git提交触发更新功用
- Publish Over SSH 完成效劳器布置功用
- nvm wrapper 引入node
装置插件的体式格局:
装置完插件今后重启一下jenkins(装置完插件后,有个重启的选项,勾选即可)
完成git钩子功用
当我们向github/码云等长途堆栈push我们的代码时,jenkins能晓得我们提交了代码,这是自动构建自动布置的条件,钩子的完成道理是在远端堆栈上设置一个Jenkins效劳器的接口地点,当当地向远端堆栈提议push时,远端堆栈会向设置的Jenkins效劳器的接口地点提议一个带参数的要求,jenkins收到后最先事情
翻开建立的项目(进入工程->点击设置
)
构建触发器
勾选 Generic Webhook Trigger
github堆栈设置钩子:
进入github项目中该项目页面,点击setting
->webhooks
,增加payload URL,
URL花样为 http://<User ID>:<API Token>@<Jenkins IP地点>:端口/generic-webhook-trigger/invoke
userid和api token在jenkins的体系治理
–治理用户
–挑选你的用户点进去
–左边设置
里
完成自动化构建
自动化构建:jenkins完成装置依靠,打包(npm install && npm run build),另外还可以实行一些测试行动
点击构建环境
,勾选nvm
,输入node版本
点击构建
,挑选实行shell
,输入实行敕令,多个敕令运用&&离开
npm config set registry http://registry.npm.taobao.org/ &&
npm install &&
npm run build