起源:公众号《前端全栈开发者》

当初,Vue.js已成为前端开发的热门框架。有很多工程师利用Vue.js的便利性和弱小性能。然而,咱们实现的某些解决方案可能未遵循最佳做法。好吧,让咱们看一下那些必备的Vue技术。

1. 函数组件

函数组件 是无状态的,没有生命周期或办法,因而无奈实例化

创立一个函数组件非常容易,你须要做的就是在SFC中增加一个 functional: true 属性,或者在模板中增加 functional。因为它像函数一样笨重,没有实例援用,所以渲染性能进步了不少。

函数组件依赖于上下文,并随着其中给定的数据而渐变。

<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 款式,移除 scope 或关上一个新的款式是不可能的。

当初,深层选择器 >>> /deep/ ::v-deep 能够帮忙你。

<style scoped>>>> .scoped-third-party-class {  color: gray;}</style><style scoped>/deep/ .scoped-third-party-class {  color: gray;}</style><style scoped>::v-deep .scoped-third-party-class {  color: gray;}</style>

3.高级“watcher”

立刻执行

当被监控的prop产生渐变时,watch handler就会触发。但有时,它是在组件被创立后才呈现的。

是的,有一个简略的解决方案:在 created 的钩子中调用处理程序,但这看起来并不优雅,同时也减少了复杂性。

或者,你能够向观察者增加 immediate 属性:

watch: {  value: {    handler: 'printValue',      immediate: true  }},methods : {  printValue () {    console.log(this.value)  }}

深度监听

有时,watch 属性是一个对象,然而其属性渐变无奈触发 wacher 处理程序。在这种状况下,为观察者增加 deep:true 能够使其属性的渐变可检测到。

请留神,当对象具备多个层时,深层可能会导致一些重大的性能问题。最好思考应用更扁平的数据结构。

data () {  return {    value: {      one: {        two: {          three: 3        }      }    }  }},watch: {  value: {    handler: 'printValue',    deep: true  }},methods : {  printValue () {    console.log(this.value)  }}

多个handlers

实际上,watch 能够设置为数组,反对的类型为 String、Function、Object。触发后,注册的watch处理程序将被一一调用。

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。

const router = new VueRouter({  routes: [{    path: '/:id',    component: Component,    props: true  }]})

这样,组件能够间接从props获取 params

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 时自定义使props和event。默认状况下,组件上的v-model应用value作为属性,Input作为事件,但一些输出类型,如复选框和单选按钮可能心愿应用value属性来实现不同的目标。在这种状况下,应用model选项能够防止抵触。

v-model 是家喻户晓的双向绑定。input 是默认的更新事件。能够通过 $emit 更新该值。惟一的限度是该组件须要<input> 标记能力与 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 修饰符。与 v-model 不同的是,它不须要你的组件有一个 <input> 标签并将值绑定到它下面。它仅触发 update:<your_prop> 通过事件系统对属性进行渐变。

<custom-component :value.sync="value" />

7.组件生命周期 Hook

通常,你能够像这样监听子组件的生命周期(例如 mounted

<!-- Child --><script>export default {  mounted () {    this.$emit('onMounted')  }}</script><!-- Parent --><template>  <Child @onMounted="handleOnMounted" /></template>

还有另一种简略的解决方案,你能够改用 @hook:mount 在Vue外部零碎中应用。

<!-- Parent --><template>  <Child @hook:mounted="handleOnMounted" /></template>

8.事件监听APIs

比方,在页面挂载时减少一个定时器,但销毁时须要革除定时器。这看起来不错。

坦率地说,只有在 beforeDestroy 中应用 this.timer 来获取计时器ID才有意义。并非厚道,而是变量越少,性能越好。

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种技术,心愿在本文中你能够对应用框架有更好的理解。如果你认为本文很棒,请在其余社交网络上分享。

举荐浏览

  • 2020年的12个Vue.js开发技巧和诀窍
  • 在Vue.js编写更好的v-for循环的6种技巧
  • React.js和Vue.js的语法并列比拟
  • Vue技巧 | 在Vue3中使元素在滚动视图时淡入
  • Vue 3教程(实用于Vue 2用户)