和渲染无关的数据不要放在data中
vue中data的数据默认便会进行双向数据绑定,若是将大量的和渲染无关的数据直接放置在data中,将会浪费双向数据绑定时所消耗的性能,将这些和渲染无关的数据进行抽离并配合Object.freeze进行处理
table中columns数据可以单独提取一个外部js文件作为配置文件,也可以在当前.vue文件中定义一个常量定义columns数据,因为无论如何都是固定且不会修改的数据,应该使用Object.freeze进行包裹,既可以提高性能还可以将固定的数据抽离,一些下拉框前端固定的数据也建议此操作。
const columnList = Object.freeze([
{ title: '姓名', key: 'name', align: 'center' },
{ title: '性别', key: 'gender', align: 'center' }
])
需要注意的是 Object.freeze() 冻结的是值,这时仍然可以将变量的引用替换掉,还有确保数据不会变才可以使用这个语法,如果要对数据进行修改和交互,就不适合使用冻结了。
Modal框的控制
一个页面种通常会存在很多个不同功能的弹框,若是每一个弹框都设置一个对应的变量来控制其显示,则会导致变量数量比较冗余和命名困难,可以使用一个变量来控制同一页面中的所有Modal弹框的展示 比如某个页面中存在三个Modal弹框
// bad
// 每一个数据控制对应的Modal展示与隐藏
new Vue({
data() {
return {
modal1: false,
modal2: false,
modal3: false,
}
}
})
// good
// 当modalType为对应的值时 展示其对应的弹框
new Vue({
data() {
return {
modalType: '' // modalType值为 modal1,modal2,modal3
}
}
})
debounce使用
例如远程搜索时需要通过接口动态的获取数据,若是每次用户输入都接口请求,是浪费带宽和性能的
当一个按钮多次点击时会导致多次触发事件,可以结合场景是否立即执行immediate
<Select :remote-method="remoteMethod">
<Option v-for="item in temoteList" :value="item.value" :key="item.id">{{item.label}}</Option>
</Select>
import {debounce} from 'lodash'
methods:{
remoteMethod: debounce(function (query) {
// to do ...
// this 的指向没有问题
}, 200),
}
路由组件传参
在组件中使用 $route 会使之与其对应路由形成高度耦合,从而使组件只能在某些特定的 URL 上使用,限制了其灵活性。
使用 props 将组件和路由解耦:
取代与 $route 的耦合
const User = {
template: '<div>User {{ $route.params.id }}</div>'
}
const router = new VueRouter({
routes: [
{ path: '/user/:id', component: User }
]
})
通过 props 解耦
这样你便可以在任何地方使用该组件,使得该组件更易于重用和测试。
const User = {
props: ['id'],
template: '<div>User {{ id }}</div>'
}
const router = new VueRouter({
routes: [
{ path: '/user/:id', component: User, props: true },
// 对于包含命名视图的路由,你必须分别为每个命名视图添加 `props` 选项:
{
path: '/user/:id',
components: { default: User, sidebar: Sidebar },
props: { default: true, sidebar: false }
}
]
})
data数据层级
data数据具有数据层级结构,切勿过度扁平化或者嵌套层级过深,若是过度扁平化会导致数据命名空间冲突,参数传递和处理,若是层级嵌套过深也会导致vue数据劫持的时候递归层级过深,若是嵌套层级丧心病狂那种的,小心递归爆栈的问题。而且层级过深会导致数据操作和处理不便,获取数据做容错处理也比较繁琐。一般层级保持2-3层最好。
若是只有一层数据,过于扁平
{
name: '',
age: '',
gender: ''
}
导致处理不方便
// 作为接口参数传递
ajax({
this.name, this.age, this.gender
})
// 接口获取数据,批量处理
ajax().then(res => {
const {name, age, gender} = res.data
this.name = name
this.age = age
this.gender = gender
})
适当的层级结构不仅增加代码的维护和阅读性,还可以增加操作和处理的便捷性
{
person: { // 个人信息
name: '',
age: '',
gender: ''
}
}
可以针对person进行操作
// 作为接口参数传递
ajax(this.person)
// 接口获取数据,批量处理
ajax().then(res => {
const {name, age, gender} = res.data
this.$set(this, 'person', {name, age, gender})
})
methods中的函数职责单一
任何时候尽量是的一个函数就做一件事情,而不是将各种逻辑全部耦合在一起,提高单个函数的复用性和可读性 每个页面都会在加载完成时进行数据的请求并展示到页面 created() { this.init(); }, methods: { // 将全部的请求行为聚合在init函数中 // 将每个请求单独拆分 init() { this.getList1() this.getList2() }, getList1() { // to do ... }, getList2() { // to do ... } }
v-bind
在日常的开发过程中, 提取和封装组件是一件很常规的操作,但是当组件需要的参数非常多时,会导致传递一堆的prop,不仅书写上面比较繁琐,对代码的维护和阅读不是一件有利的事情
例如组件test-demo需要一堆props传递
使用时
<template>
<test-demo
:data1="data1"
:data2="data2"
:data3="data3"
...假设还有一堆
/>
</template>
test-demo中需要接收处理
{
props: ['data1', 'data2', 'data3', ...]
}
// or
props: {
modalVisible: {
// 控制展示modal
type: Boolean,
default: false
},
data1: {
type: String,
default: '1'
},
data2: {
type: String,
default: '2'
},
data3: {
type: String,
default: '3'
}
}
- 建议 将子组件需要的数据收集起来,集中在一个对象中,使用v-bind传递将这个对象传递,子组件的使用和普通的props一样
<template>
<test-demo
v-bind="obj"
/>
</template>
export default {
data () {
return {
obj: { // 将需要传递给子组件的数据收集
data1: '1',
data2: '2',
data3: '3'
}
}
}
}
</script>
优先使用v-if
v-if 和 v-show 理论上都是作用于元素的显示隐藏,只是一个是直接对DOM,一个是通过CSS的 display 来操作的,只有当DOM频繁进行显示和隐藏的时候,才会优先考虑v-show
v-for和v-if不要一起使用
v-for的优先级其实是比v-if高的,所以当两个指令出现来一个DOM中,那么v-for渲染的当前列表,每一次都需要进行一次v-if判断。而相应的列表也会重新变化,这个看起来是非常不合理的。因此当你需要进行同步指令的时候。尽量使用计算属性,先将v-for不需要的值先过滤掉。他看起像是下面这样的。
// 计算属性
computed: {
filterList: function () {
return this.showData.filter(function (data) {
return data.isShow
})
}
// DOM
<ul>
<li v-for="item in filterList" :key="item.id">
{{ item.name }}
</li>
</ul>
v-for key避免使用index作为标识
其实大家都知道 v-for 是不推荐使用 index 下标来作为key的值,这是一个非常好理解的知识点,可以从图中看到,当index作为标识的时候,插入一条数据的时候,列表中它后面的key都发生了变化,那么当前的v-for都会对key变化的 Element 重新渲染,但是其实它们除了插入的 Element 数据都没有发生改变,这就导致了没有必要的开销。所以,尽量不要用index作为标识,而去采用数据中的唯一值,如 id 等字段。