这9个Vue技巧你掌握了吗?
最初在pitayan.com
https://pitayan.com/posts/vue-techniques/
我们还有好看的代码亮点:p。
如今,Vue.js已成为前端开发的热门框架。许多工程师正在利用Vue.js的便捷性和强大功能。然而,我们所做的一些解决方案可能并非最佳实践。那么,让我们来看看那些必须掌握的Vue技巧。
内容:
- 1. 功能组件
- 2. 深度选择器
- 3.高级“观察者”
- 4.事件参数:$event
- 5. 路由器参数解耦
- 6. 自定义组件的双向绑定
- 7. 组件生命周期钩子
- 8. 事件监听器 API
- 9. 以编程方式挂载组件
- 参考
1. 功能组件
函数式组件是无状态的,没有lifecycle
或methods
。因此它无法被实例化
创建函数式组件非常简单,只需functional: true
在 SFC 或functional
模板中添加属性即可。由于它像函数一样轻量,没有实例引用,因此渲染性能得到了显著提升。
功能组件依赖于context
并随着其中给定的数据而变异。
<template functional>
<div class="book">
{{props.book.name}} {{props.book.price}}
</div>
</template>
<script>
Vue.component('book', {
functional: true,
props: {
book: {
type: () => ({}),
required: true
}
},
render: function (createElement, context) {
return createElement(
'div',
{
attrs: {
class: 'book'
}
},
[context.props.book]
)
}
})
</script>
2. 深度选择器
有时甚至需要修改第三方组件的 CSS 样式scoped
,无法移除sc ope
或开启新的样式。
现在深度选择器 >>>
或/deep/
进入正确的地方寻求帮助。
<style scoped>
>>> .scoped-third-party-class {
color: gray;
}
</style>
<style scoped>
/deep/ .scoped-third-party-class {
color: gray;
}
</style>
3.高级“观察者”
立即执行
watch
当被监控的 prop 发生突变时,处理程序会触发。但有时,它会在组件 icreated 之后立即触发。
是的,有一个简单的解决方案:在created
钩子中调用处理程序。但这看起来并不优雅,同时也增加了复杂性。
或者你可以immediate
向观察者添加一个属性:
watch: {
value: {
handler: 'printValue',
immediate: true
}
},
methods : {
printValue () {
console.log(this.value)
}
}
深度聆听
有时,watcher 属性是一个Object
。但其属性突变无法触发 watcher 处理程序。在这种情况下,添加deep: true
watcher 可以使其属性突变可被检测到。
请注意,当你的数据层数较多时,这deep
可能会导致严重的性能问题Object
。最好考虑使用更扁平的数据结构。
data () {
return {
value: {
one: {
two: {
three: 3
}
}
}
}
},
watch: {
value: {
handler: 'printValue',
deep: true
}
},
methods : {
printValue () {
console.log(this.value)
}
}
多个处理程序
实际上,watcher 可以设置为Array
。支持的类型有String
| Function
| Object
。已注册的 watcher 处理程序将在触发时逐一调用。
watch: {
value: [
'printValue',
function (val, oldVal) {
console.log(val)
},
{
handler: 'printValue',
deep: true
}
]
},
methods : {
printValue () {
console.log(this.value)
}
}
订阅多个变量突变
watcher
无法监听多个变量,但我们可以将目标组合在一起作为一个新的变量computed
并观察这个新的“变量”。
computed: {
multipleValues () {
return {
value1: this.value1,
value2: this.value2,
}
}
},
watch: {
multipleValues (val, oldVal) {
console.log(val)
}
}
4.事件参数:$event
$event
是事件对象的一个特殊变量,它在某些场景下为复杂的功能提供了更多的可选参数。
本土事件
在原生事件中,该值与默认事件(DOM 事件或窗口事件)相同。
<template>
<input type="text" @input="handleInput('hello', $event)" />
</template>
<script>
export default {
methods: {
handleInput (val, e) {
console.log(e.target.value) // hello
}
}
}
</script>
自定义事件
在自定义事件中,值是从其子组件捕获的值。
<!-- Child -->
<template>
<input type="text" @input="$emit('custom-event', 'hello')" />
</template>
<!-- Parent -->
<template>
<Child @custom-event="handleCustomevent" />
</template>
<script>
export default {
methods: {
handleCustomevent (value) {
console.log(value) // hello
}
}
}
</script>
5. 路由器参数解耦
我相信大多数人都是这样处理组件中的路由器参数的:
export default {
methods: {
getRouteParamsId() {
return this.$route.params.id
}
}
}
在组件内部使用$route
会与特定的 URL 产生强耦合,限制了组件的灵活性。
正确的解决方案是添加props
到Router
。
const router = new VueRouter({
routes: [{
path: '/:id',
component: Component,
props: true
}]
})
这样组件就可以params
直接从props中获取了。
export default {
props: ['id'],
methods: {
getParamsId() {
return this.id
}
}
}
此外,您还可以传入一个函数来返回props
以实现自定义目的。
const router = new VueRouter({
routes: [{
path: '/:id',
component: Component,
props: router => ({ id: route.query.id })
}]
})
6. 自定义组件的双向绑定
允许自定义组件自定义与 v-model 一起使用时使用的 prop 和事件。默认情况下,组件上的 v-model 使用 value 作为 prop,使用 input 作为事件,但某些输入类型(例如复选框和单选按钮)可能希望将 value prop 用于其他用途。在这种情况下,使用 model 选项可以避免冲突。
v-model
以双向绑定而闻名。input
是默认的更新事件。可以通过 更新值$emit
。唯一的限制是组件需要一个<input>
标签来与 prop 绑定value
。
<my-checkbox v-model="val"></my-checkbox>
<template>
<input type="checkbox" :value="value" @input="handleInputChange(value)" />
</template>
<script>
export default {
props: {
value: {
type: Boolean,
default: false
}
},
methods: {
handleInputChange (val) {
console.log(val)
}
}
}
</script>
双向绑定还有另一种解决方案,那就是sync
modifier。与 不同v-model
,它不需要你的组件拥有<input>
标签并将值绑定到标签上。它只update:<your_prop>
通过事件系统触发 prop 的修改。
<custom-component :value.sync="value" />
7. 组件生命周期钩子
mounted
通常,你可以像这样监听子组件的生命周期(例如
<!-- Child -->
<script>
export default {
mounted () {
this.$emit('onMounted')
}
}
</script>
<!-- Parent -->
<template>
<Child @onMounted="handleOnMounted" />
</template>
还有另一种简单的解决方案。你可以使用@hook:mounted
。它在 Vue 内部系统中使用。
<!-- Parent -->
<template>
<Child @hook:mounted="handleOnMounted" />
</template>
8. 事件监听器 API
例如,在页面挂载时添加一个计时器,但在页面销毁时需要清除该计时器。这个设计看起来不错。
坦白说,this.timer
只有在获取计时器 ID 时才有意义beforeDestroy
。我不是故意的,只是响应变量越少,性能就越好。
export default {
data () {
return {
timer: null
}
},
mounted () {
this.timer = setInterval(() => {
console.log(Date.now())
}, 1000)
},
beforeDestroy () {
clearInterval(this.timer)
}
}
使其仅在生命周期钩子内可访问。用它$once
来摆脱不必要的东西。
export default {
mounted () {
let timer = null
timer = setInterval(() => {
console.log(Date.now())
}, 1000)
this.$once('hook:beforeDestroy', () => {
clearInterval(timer)
})
}
}
9. 以编程方式挂载组件
$popup()
在某些情况下,以编程方式加载组件会更加优雅。例如,可以通过全局上下文或来打开弹窗或模态框$modal.open()
。
import Vue from 'vue'
import Popup from './popup'
const PopupCtor = Vue.extend(Popup)
const PopupIns = new PopupCtr()
PopupIns.$mount()
document.body.append(PopupIns.$el)
Vue.prototype.$popup = Vue.$popup = function () {
PopupIns.open()
}
Element UI实现了一个结构良好的模态组件,允许使用自定义 API 来控制实例的生命周期。其原理与我上面演示的大致相同。
以上就是关于 Vue 2.x 的 9 项技巧。希望通过本文,你能更好地了解如何使用该框架。
如果你觉得这篇文章很棒,请分享到其他社交媒体平台。
谢谢阅读!
参考
- https://vuejs.org
- https://www.digitalocean.com/community/tutorials/vuejs-add-v-model-support
- https://vue-loader.vuejs.org/guide/scoped-css.html#child-component-root-elements
最初发表于pitayan.com
https://pitayan.com/posts/vue-techniques/