我们在键盘上留下的余温, 也将随时代传递到更远的将来


:D 获取中...

记录一下开发中使用的 vue 技巧

路由参数解耦

一般在组件内使用路由参数, 大多数人会这样做:

1
2
3
4
5
6
7
export default {
methods: {
getParamsId () {
return this.$route.params.id
}
}
}

在组件中使用 $route 会使之与其对应路由形成高度耦合, 从而使组件只能在某些特定的 URL 上使用, 限制了其灵活性.

正确的做法是通过 props 解耦

1
2
3
4
5
6
7
const router = new VueRouter({
routes: [{
path: '/user/:id',
component: User,
props: true
}]
})

将路由的 props 属性设置为 true 后, 组件内可通过 props 接收到 params 参数

1
2
3
4
5
6
7
8
export default {
props: ['id'],
methods: {
getParamsId () {
return this.id
}
}
}

另外你还可以通过函数模式来返回 props

1
2
3
4
5
6
7
8
9
const router = new VueRouter({
routes: [{
path: '/user/:id',
component: User,
props: route => ({
id: route.query.id
})
}]
})

文档: 路由组件传参 | Vue Router

函数式组件

函数式组件是无状态, 它无法实例化, 没有任何的生命周期和方法. 创建函数式组件也很简单, 只需要在模板添加 functional 声明即可. 一般适合只依赖于外部数据的变化而变化的组件, 因其轻量, 渲染性能也会有所提高.

组件需要的一切都是通过 context 参数传递. 它是一个上下文对象, 具体属性查看文档. 这里 props 是一个包含所有绑定属性的对象.

函数式组件

1
2
3
4
5
6
7
8
<template functional>
<div class="list">
<div class="item" v-for="item in props.list" :key="item.id" @click="props.itemClick(item)">
<p>{{item.title}}</p>
<p>{{item.content}}</p>
</div>
</div>
</template>

父组件使用

1
2
3
4
5
<template>
<div>
<List :list="list" :itemClick="item => (currentItem = item)"></List>
</div>
</template>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import List from '@/components/List.vue'
export default {
components: {
List
},
data () {
return {
list: [{
title: 'title',
content: 'content'
}],
currentItem: ''
}
}
}

文档: 函数式组件

watch

触发 watch 监听执行多个方法

使用数组可以设置多项, 形式包括字符串、函数、对象

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
export default {
data: {
name: 'Joe'
},
watch: {
name: [
'sayName1',
function (newVal, oldVal) {
this.sayName2()
},
{
handler: 'sayName3',
immediate: true
}
]
},
methods: {
sayName1 () {
console.log('sayName1==>', this.name)
},
sayName2 () {
console.log('sayName2==>', this.name)
},
sayName3 () {
console.log('sayName3==>', this.name)
}
}
}

watch 监听多个变量

watch 本身无法监听多个变量. 但我们可以将需要监听的多个变量通过计算属性返回对象, 再监听这个对象来实现 “监听多个变量”

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
export default {
data () {
return {
msg1: 'apple',
msg2: 'banana'
}
},
computed: {
msgObj () {
const {
msg1,
msg2
} = this
return {
msg1,
msg2
}
}
},
watch: {
msgObj: {
handler (newVal, oldVal) {
if (newVal.msg1 != oldVal.msg1) {
console.log('msg1 is change')
}
if (newVal.msg2 != oldVal.msg2) {
console.log('msg2 is change')
}
},
deep: true
}
}
}

文档: watch

程序化的事件侦听器

比如, 在页面挂载时定义计时器, 需要在页面销毁时清除定时器. 这看起来没什么问题. 但仔细一看 this.timer 唯一的作用只是为了能够在 beforeDestroy 内取到计时器序号, 除此之外没有任何用处.

1
2
3
4
5
6
7
8
9
10
export default {
mounted () {
this.timer = setInterval(() => {
console.log(Date.now())
}, 1000)
},
beforeDestroy () {
clearInterval(this.timer)
}
}

如果可以的话最好只有生命周期钩子可以访问到它. 这并不算严重的问题, 但是它可以被视为杂物.

我们可以通过 $on$once 监听页面生命周期销毁来解决这个问题:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
export default {
mounted () {
this.createInterval('hello')
this.createInterval('world')
},
createInterval (msg) {
let timer = setInterval(() => {
console.log(msg)
}, 1000)
this.$once('hook:beforeDestroy', function () {
clearInterval(timer)
})
}
}

使用这个方法后, 即使我们同时创建多个计时器, 也不影响效果. 因为它们会在页面销毁后程序化的自主清除.

文档: 程序化的事件侦听器


 评论

 无法加载Disqus评论系统,请确保您的网络能够正常访问。