Vue项目实用技巧整理
Posted haifeng8742
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Vue项目实用技巧整理相关的知识,希望对你有一定的参考价值。
1,css篇: 全局引入公共的scss或者其他预编译文件 ,主要依赖:sass-resources-loader, 详见我上一篇博客
2. js篇:
2.1:props和$emit
巧用修饰符语法糖sync来优雅的更新props ,父子组件的传值prop是很常用的业务,需要在子组件去更新prop的场景也很常见,但是prop是个只读属性,在子组件中直接修改其值因不符合单向数据流的设计,所以我们一般结合$emit来触发父组件的方法, 但是有些场景
只是简单的修改prop中的简单的值, 比如切换显示隐藏,更新type等等, 这时候就可以考虑使用sync修饰符了, 子组件更新prop的值也是必须要通过$emit来触发, 这并没有改变其单向数据流的设计的, 只是触发的方法名前面多了一个 update: ,说白了就是你在父组件中使用了sync, Vue会帮你声明一个method 名字就叫做 update:xxx 所以才免去你的手动添加这么一个方法, 开始就说了这不过是个语法糖 , 具体代码如下:
parent.vue:
<child :title.sync="title"></child>
child.vue:
export defalut {
props: {
title: String
},
methods: {
changeTitle(){
this.$emit(‘update:title‘, ‘hello‘)
}
}
2.2: provide和inject(主要在开发高阶插件/组件库时使用。并不推荐用于普通应用程序代码中。但是某些时候,或许它能帮助到我们)
这对选项需要一起使用,以允许一个祖先组件向其所有子孙后代注入一个依赖,不论组件层次有多深,并在其上下游关系成立的时间里始终生效。
简单来说,一个组件将自己的属性通过 provide
暴露出去,其下面的子孙组件 inject
即可接收到暴露的属性
代码如下:
App.vue:
export default {
provide() {
return {
app: this
}
}
}
child.vue:
export default {
inject: [‘app‘],
created() {
console.log(this.app) // App.vue实例
}
}
ps:在 2.5.0+ 版本可以通过设置默认值使其变成可选项:
export default {
inject: {
app: {
default: () => ({})
}
},
created() {
console.log(this.app)
}
}
如果你想为 inject
的属性变更名称,可以使用 from
来表示其来源:
export default {
inject: {
myApp: {
// from的值和provide的属性名保持一致
from: ‘app‘,
default: () => ({})
}
},
created() {
console.log(this.myApp)
}
}
2.3:巧用template
相信 v-if
在开发中是用得最多的指令,那么你一定遇到过这样的场景,多个元素需要切换,而且切换条件都一样,一般都会使用一个元素包裹起来,在这个元素上做切换。
<div v-if="status===‘ok‘">
<h1>Title</h1>
<p>Paragraph 1</p>
<p>Paragraph 2</p>
</div>
如果像上面的 div 只是为了切换条件而存在,还导致元素层级嵌套多一层,那么它没有“存在的意义”。
我们都知道在声明页面模板时,所有元素需要放在 <template>
元素内。除此之外,它还能在模板内使用,<template>
元素作为不可见的包裹元素,只是在运行时做处理,最终的渲染结果并不包含它。
<template>
<div>
<template v-if="status===‘ok‘">
<h1>Title</h1>
<p>Paragraph 1</p>
<p>Paragraph 2</p>
</template>
</div>
</template>
我们也可以在<template>上使用v-for指令, 这也不失为解决v-if和v-for同时使用报出警告的问题的方法之一了,(之前是通过过滤数据后渲染解决的)
<template v-for="item in 10">
<div v-if="item % 2 == 0" :key="item">{{item}}</div>
</template>
2.4: require.context (自动注册全局组件功能在之前的博客,请移步)
这个并不是Vue提供的功能, 而是强大的Webpack提供的, 他还有另外一个妙用就是自动引入模块
像 api 文件一般按功能划分模块,在组合时可以使用 require.context
一次引入文件夹所有的模块文件,而不需要逐个模块文件去引入。每当新增模块文件时,就只需要关注逻辑的编写和模块暴露,require.context
会帮助我们自动引入
代码如下: (可以做成插件形式 具体请查看vue插件机制 ) import Request from ‘../service/request‘
let importAll = require.context(‘./modules‘, false, /.js$/) class Api extends Request{ constructor(){ super() //importAll.keys()为模块路径数组 importAll.keys().map(path =>{ //兼容处理:.default获取ES6规范暴露的内容; 后者获取commonJS规范暴露的内容 let api = importAll(path).default || importAll(path) Object.keys(api).forEach(key => this[key] = api[key]) }) } } export default new Api()
路由懒加载(动态chunkName)
路由懒加载作为性能优化的一种手段,它能让路由组件延迟加载。通常我们还会为延迟加载的路由添加“魔法注释”(webpackChunkName),在打包时,该路由组件会被单独打包出来。
let router = new Router({
routes: [
{
path:‘/login‘,
name:‘login‘,
component: import(/* webpackChunkName: "login" */ `@/views/login.vue`)
},
{
path:‘/index‘,
name:‘index‘,
component: import(/* webpackChunkName: "index" */ `@/views/index.vue`)
},
{
path:‘/detail‘,
name:‘detail‘,
component: import(/* webpackChunkName: "detail" */ `@/views/detail.vue`)
}
]
})
上面这种写法没问题,但仔细一看它们结构都是相似的,作为一名出色的开发者,我们可以使用 map
循环来解决这种重复性的工作。
const routeOptions = [
{
path:‘/login‘,
name:‘login‘,
},
{
path:‘/index‘,
name:‘index‘,
},
{
path:‘/detail‘,
name:‘detail‘,
},
]
const routes = routeOptions.map(route => {
if (!route.component) {
route = {
...route,
component: () => import(`@/views/${route.name}.vue`)
}
}
return route
})
let router = new Router({
routes
})
在书写更少代码的同时,我们也把“魔法注释”给牺牲掉了。总所周知,代码中没办法编写动态注释。这个问题很尴尬,难道就没有两全其美的办法了吗?
强大的 webpack
来救场了,从 webpack 2.6.0 开始,占位符 [index] 和 [request] 被支持为递增的数字或实际解析的文件名。我们可以这样使用“魔法注释”:
const routes = routeOptions.map(route => {
if (!route.component) {
route = {
...route,
component: () => import(/* webpackChunkName: "[request]" */ `@/views/${route.name}.vue`)
}
}
return route
})
以上是关于Vue项目实用技巧整理的主要内容,如果未能解决你的问题,请参考以下文章