2019独角兽企业重金招聘Python工程师标准>>>
Vue进阶
一、搭建项目
1、vue-cli架构
npm i -g vue-cli: 安装vue-cli模块
vue init webpack my-project: 利用webpack创建一个项目文件,文件名为my-project.
cd my-project: 进入my-project文件夹
npm install: 安装依赖,npm会根据package.json中包的信息来装环境。
npm run dev 运行服务,启动服务。
默认在localhost:8080端口可以打开当前的index.html页面。
(1)、执行完之后,修改App.vue和main.js,以及创建vue文件这些操作,来进行开发页面了。
(2)、要开发vue文件,需要webpack进行配合,
vue-cli可以提供一个webpack的压缩环境,不需要自己写webpack的文件,拿来就能用。
(3)、默认端口是可以更改的,在config/index.js里面,dev的port即为端口号。
tips:在vue init webpack my-project的过程中,将会要求对项目的基本信息进行配置,
有两个需要注意的点,一是需不需要ESLint进行规范代码,二是需不需要单元测试的内容。
若开启了ESLint,该项目将开启严格模式,vue代码将会标准化,多一个空格少一个空格将会报错。
2、CDN
对于常用的包,可以通过cdn来减少本地的资源。
jqueryCDN,
谷歌CDN:https://ajax.googleapis.com/ajax/libs/jquery/2.2.4/jquery.min.js
百度CDN:http://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js
3、生产环境
npm run dev命令用于开发中的本地环境搭建,
npm run build命令将开发环境的代码生成静态文件。
(1)、npm run build后,生成dist文件夹,内有static文件夹和index.html。
(2)、在服务器环境下,static和index.html放到根目录,监听配置好的端口,即可运行起该项目。
(3)、static文件夹内有js文件和用到的css文件。
tips:build指令对文件进行了压缩编译,若编译发生错误,
即文件间引用错误,生成的静态文件将无法执行,build的过程将会报错。
项目基本配置更改
config
config文件夹核心内容为index.js
index.js
// see http://vuejs-templates.github.io/webpack for documentation.
var path = require('path')
module.exports = {
/**
* [@desc](https://my.oschina.net/u/2009802) 1、build 为打包之后的vue文件配置,即生产环境的代码配置
*/
build: {
//1.1、env:环境变量
env: require('./prod.env'),
//1.2、配置压缩后代码的html文件的路径和文件名,作为html的入口文件
index: path.resolve(__dirname, '../dist/index.html'),
//1.3、配置压缩后代码的路径,默认配置为所有文件存放到dist文件夹
assetsRoot: path.resolve(__dirname, '../dist'),
//1.4、配置dist文件的二级目录,主要用于存放html文件需要用到的js和css,img等
assetsSubDirectory: 'static',
//1.5、资源的CDN路径,如果需要将资源和入口html分离,
//可以配置资源的CDN路径,作为发布的路径
assetsPublicPath: '/',
//1.6、是否使用sourceMap,sourceMap是webpack的一项功能,
//设置为true,控制台的source的webpack文件夹中可以看到源代码信息
//设置为false,控制台将只能看到压缩后的代码的信息
productionSourceMap: true,
// Gzip off by default as many popular static hosts such as
// Surge or Netlify already gzip all static assets for you.
// Before setting to `true`, make sure to:
// npm install --save-dev compression-webpack-plugin
//1.7、是否开启GZIP压缩,如果要开启,要下载一个compression-webpack-plugin插件
productionGzip: false,
//1.8、在开启了GZIP压缩后,设置需要压缩的文件,以后缀名进行区分
productionGzipExtensions: ['js', 'css'],
// Run the build command with an extra argument to
// View the bundle analyzer report after build finishes:
// `npm run build --report`
// Set to `true` or `false` to always turn it on or off
//1.9、显示webpack代码压缩之后的分析报告
bundleAnalyzerReport: process.env.npm_config_report
},
/**
* [@desc](https://my.oschina.net/u/2009802) 2、dev为开发环境的基本配置
*/
dev: {
//2.1、dev的环境变量
env: require('./dev.env'),
//2.2、指定项目运行后的端口号
port: 8123,
//2.3、在项目环境搭建成功后是否自动打开浏览器
autoOpenBrowser: true,
//2.4、设置静态资源的文件夹,这里设置成了static
assetsSubDirectory: 'static',
//2.5、设置根目录,这里设置的根目录为项目index.html所在的目录
assetsPublicPath: '/',
//2.6、代理,这里可以配置响应的请求到相应的代理,可以用来解决跨域
proxyTable: {
'/login': {
target: 'http://10.0.1.17:9999',
changeOrigin: true,
pathRewrite: {
'^/login': '/login'
}
},
'/user': {
target: 'http://10.0.1.9:8081',
changeOrigin: true,
pathRewrite: {
'^/user': '/user'
}
},
},
// CSS Sourcemaps off by default because relative paths are "buggy"
// with this option, according to the CSS-Loader README
// (https://github.com/webpack/css-loader#sourcemaps)
// In our experience, they generally work as expected,
// just be aware of this issue when enabling this option.
//2.7、是否开启webpack的cssSourceMap
cssSourceMap: false
}
}
build
1、dev-server.js
2、webpack.base.conf.js
反向代理配置
理论上跨域问题可以由后端一次性解决,但也有开发过程中需要用到前端解决跨域的场景。
vue-cli支持反向代理解决跨域问题。
index.js
dev: {
env: require('./dev.env'),
port: configData.config.port,
autoOpenBrowser: true,
assetsSubDirectory: 'static',
assetsPublicPath: '/',
proxyTable: {
'/api': {
target: 'https://api.douban.com/v2',
changeOrigin: true,
pathRewrite: {
'^/api': '/'
}
},
},
1、/api为代理后的名称
2、target为目标的请求地址;
3、changeOrigin置为true,即开启了反向代理;
4、pathRewrite为地址重写,
例如本例中,/api只做代理域名作用,因此只写'^/api':'/'
请求的url:/api/book/1220562
等同于:https://api.douban.com/v2/book/1220562
tips:若进行配置pathRewrite,例如'^/api':'/api'
请求的url:/api/book/1220562
等同于:https://api.douban.com/v2/api/book/1220562
二者有区别。
二、细节技巧
父子组件传值
1、子组件传值给父组件
(1)、在子组件中,进行$emit向父组件调用方法
this.$emit("closeSignUpPop",'false');
(2)、父组件中,假定子组件的名称为Signup
首先在子组件的调用上接收这个方法
接着在父组件的methods里写入这个function
closeSignUpPop(){
//这里写需要操作的内容,可以是改变父组件中变量的值,
//也可以是调用其他方法
}
2、父组件传值给子组件
官方在2.0版本中停止了broadcast的使用,采用bind的方式来完成
(1)在父组件中,定义一个变量,假定其名为isClose
data:function(){
return{
isClose:""
}
}
(2)假设在父组件中调用的子组件名称为Signup,将isClose绑入子组件的调用中即可。
(3)接着到子组件中,使用props来接收这个变量,写在和data的平级属性中;
export default{
props:["isClose"]
data:function(){
return{
}
}
}
此时,在子组件中,就存在了isClose这个变量,可以在子组件中的methods操作这个变量。
tips:需要注意的是,props传入的值,也绑入到了$data中,
因此data里面无需重新定义一个变量名为isClose,重新定义将发生变量名冲突。
3、父组件$refs方式
$refs可以调用子组件的方法
(1)、在父组件调用子组件时,写入ref
(2)、在子组件Signup中,假定有一个methods为close
methods:{
close(){
//在子组件中执行的方法
}
}
(3)、回到父组件,这时候的父组件,
可以通过this.$refs.child_1.close()触发子组件的方法
tips:父组件要调用$refs,不能写入mounted钩子函数中,否则将会undefined;
正确调用:
this.nextTick(() => { this.$refs.xxx })
变量扩展
在main.js中,扩展Vue的原型方法。
//1、main_config.vue
const cookie = {
get:function(){},
set:function(){},
del:function(){}
}
export default
{
cookie
}
//2、main.js
import global_ from './main_config/main_config.vue'
Vue.prototype.GLOBAL = global_
//3、然后在组件中间就可以调用main_config中的方法了
this.GLOBAL.cookie.get()
延迟加载组件
import Index from "./j_index/index.vue"
————————————————→
const Index = resolve => require([ './j_index/index.vue'],resolve);
优化URL
router的history模式,可以去除#号
mode:'history'
Vue拦截器
Vue.http.interceptors.push((request, next) ={
// modify request
//在每一次的请求之前,加上请求头header
request.headers.set('Authorization',rsaEncrypt("userId","token"))
//在请求之前可以进行一些预处理和配置
next((response) ={return response;});
});
路由跳转拦截
router.beforeEach((to,from,next) ={
if(to.matched.some( m =m.meta.auth)){
// 对路由进行验证
if(global_.cookie.get('userId')) { // 已经登陆
next() // 正常跳转到你设置好的页面
}else{
// 未登录则跳转到登陆界面,query:{ Rurl: to.fullPath}表示把当前路由信息传递过去方便登录后跳转回来;
var url = { Rurl: to.fullPath};
if(url.Rurl.indexOf('company') 0){
next({path:'/company_index'})
}
if(url.Rurl.indexOf('candidate') 0){
next({path:'/'})
}
}
} else{ next() }
})
{
path: 'offline',
name: 'EmployerOrderOffline',
component: EmployerOrderOffline,
meta:{auth:true}
}
指定路径显示对应组件
视图与数据不同步
由于 JavaScript 的限制, Vue 不能检测以下变动的数组:
利用索引直接设置属性值,例如: vm.items[indexOfItem] = newValue
修改数组的长度,例如: vm.items.length = newLength
手动更新视图
在手动操作了DOM元素的时候,可能会发生数据已经更新,而视图没有更新的情况。
这时可以使用$set手动更新视图。
假设在当前组件的data中,有一个变量名为param_1
data:function(){
return{
param_1:'xxx',
param_2:{
innerParam:'yyy'
}
}
}
this.$set(this.$data,'param_1','zzz');
this.$set(this.param_2,'innerParam','ccc');
tips:$set接收三个参数,
第一个参数是根变量,
第二个参数为内部变量,
第三个参数为需要赋值给内部变量的值,
因此存在两种方式,第一种传入this.$data,第二种直接传入this.param_2;
注意,第二个参数应该打上引号,否则报错undefined。
router-link传参
query中的属性将会加到path的后缀中作为参数传递。
结果:/candidate/job_moreinfo?jobId=xxx&type=type
tips:手动跳转路由时的传参同理。
三、vuex
vuex的作用类似于全局变量,在页面刷新后,vuex内的数据将会被重置为初始值。
四、个人见解
1、vuex用于所有组件共同拥有同一个状态,
(1)、组件A是组件B的前提,如果没有组件A的值的变化,组件B将不能进入;
(2)、页面中有组件A和B,组件A中mounted进行操作state里的值,并存入state,
在组件B中可以获取到这个state的变化,即完成了平行同级组件之间的相互数据交互
(3)、某些情况下,高度的将methods提取写入到mutations和actions里面,data都用vuex来管理,
代码的阅读性会被牺牲,因为产生了多个文件间的调用,
因此,共通的方法可以用vuex来保管,私有方法写在组件内更为合适。
2、$refs的方式使用在router-view中,有可能会在控制台中报错undefined
3、safari浏览器在解析js时,简写语法将不会被识别,报错;
例如,有一个文件名叫website.js,向外export时,简写成:
module.exports = {
config,rsaEncrypt
}
谷歌和firefox可以识别,但是safari将会报错,同时,npm run build时也将报错。
正确写法:
module.exports = {
config:config,
rsaEncrypt:rsaEncrypt,
}
4、手动跳转路由,不建议使用location.href
有时候需要在methods进行操作路由跳转,这时不建议用location.href,会增加代码维护的难度。
推荐写法:
this.$router.push({name:"EmployerOrderPrice"})
采用name识别的方式,当指定路由路径更改时,只需要改router.js的path即可。
tips:手动跳转路由的传参和router-link写法一样。
5、重置component的data状态
Object.assign(this.$data, this.$options.data())
但是必须要注意在默认的样式中不应该取变量,例如i18n,abc:this.$t("xxx.xxx"),否则将会报错。