1. 处理加载状态在大型项目中,我们可能需要将组件分成小块,只有在需要时才从服务器上加载。为了更容易做到这一点,Vue允许我们将组件定义为一个工厂函数,异步地解析组件定义。Vue只会在组件需要渲染的时候触发工厂函数,并把结果缓存起来以备后面的重新渲染。2.3版的新内容是,异步组件工厂还可以返回以下格式的对象。

const AsyncComponent = () => ({
  // 需要加载的组件 (应该是一个 `Promise` 对象)
  component: import('./MyComponent.vue'),
  // 异步组件加载时使用的组件
  loading: LoadingComponent,
  // 加载失败时使用的组件
  error: ErrorComponent,
  // 展示加载时组件的延时时间。默认值是 200 (毫秒)
  delay: 200,
  // 如果提供了超时时间且组件加载也超时了,
  // 则使用加载失败时使用的组件。默认值是:`Infinity`
  timeout: 3000
})

使用这种方法,我们有额外的选项,包括加载和错误状态、组件获取的延迟和超时。

2.通过 ​​v-once​​ 创建低开销的静态组件

渲染普通的 HTML 元素在 Vue 中是非常快速的,但有的时候你可能有一个组件,这个组件包含了大量静态内容。在这种情况下,我们可以在根元素上添加 ​​v-once​​ attribute 以确保这些内容只计算一次然后缓存起来,就像这样:

Vue.component('terms-of-service', {
  template: `
    <div v-once>
      <h1>Terms of Service</h1>
      ... a lot of static content ...
    </div>
  `
})

更多详细内容看官网:https://cn.vuejs.org/v2/guide/components-edge-cases.html

3.递归组件

组件是可以在它们自己的模板中调用自身的。不过它们只能通过 ​​name​​ 选项来做这件事:

name: 'unique-name-of-my-component'

当你使用 ​​Vue.component​​ 全局注册一个组件时,这个全局的 ID 会自动设置为该组件的 name 选项。

Vue.component('unique-name-of-my-component', {
  // ...
})

稍有不慎,递归组件就可能导致无限循环:

name: 'stack-overflow',
template: '<div><stack-overflow></stack-overflow></div>'

类似上述的组件将会导致​​“max stack size exceeded”​​​错误,所以请确保递归调用是条件性的 (例如使用一个最终会得到 ​​false​​​ 的 ​​v-if​​)。

4.内联模板

当 ​​inline-template​​​ 这个特殊的 ​​attribute​​ 出现在一个子组件上时,这个组件将会使用其里面的内容作为模板,而不是将其作为被分发的内容。这使得模板的撰写工作更加灵活。

<my-component inline-template>
  <div>
    <p>These are compiled as the component's own template.</p>
    <p>Not parent's transclusion content.</p>
  </div>
</my-component>

内联模板需要定义在 Vue 所属的 DOM 元素内。

不过,​​inline-template​​​ 会让模板的作用域变得更加难以理解。所以作为最佳实践,请在组件内优先选择 ​​template​​​ 选项或 .vue 文件里的一个 ​​<template>​​ 元素来定义模板。

5. 动态指令参数

指令的参数可以是动态的。例如,在 ​​v-mydirective:[argument]="value"​​​ 中,​​argument​​参数可以根据组件实例数据进行更新!这使得自定义指令可以在应用中被灵活使用。

例如你想要创建一个自定义指令,用来通过固定布局将元素固定在页面上。我们可以像这样创建一个通过指令值来更新竖直位置像素值的自定义指令:

<div id="dynamicexample">
  <h3>Scroll down inside this section ↓</h3>
  <p v-pin:[direction]="200">I am pinned onto the page at 200px to the left.</p>
</div>
Vue.directive('pin', {
  bind: function (el, binding, vnode) {
    el.style.position = 'fixed'
    var s = (binding.arg == 'left' ? 'left' : 'top')
    el.style[s] = binding.value + 'px'
  }
})

new Vue({
  el: '#dynamicexample',
  data: function () {
    return {
      direction: 'left'
    }
  }
})

6.事件 & 按键修饰符

对于 ​​.passive​​​、​​.capture​​​ 和 ​​.once​​ 这些事件修饰符,Vue 提供了相应的前缀可以用于 on:


修饰符

前缀

.passive

&

.capture

!

.once

~

.capture.once 或.once.capture

~!

例如:

on: {
  '!click': this.doThisInCapturingMode,
  '~keyup': this.doThisOnce,
  '~!mouseover': this.doThisOnceInCapturingMode
}

对于所有其它的修饰符,私有前缀都不是必须的,因为你可以在事件处理函数中使用事件方法:


修饰符

处理函数中的等价操作

​.stop​

​event.stopPropagation()​

​.prevent​

​event.preventDefault()​

​.self​

​if (event.target !== event.currentTarget) return​

按键:​​.enter​​​, ​​.13​

​if (event.keyCode !== 13) return​​​ (对于别的按键修饰符来说,可将 ​​13​​ 改为另一个按键码)

修饰键:​​.ctrl​​​, ​​.alt​​​, ​​.shift​​​, ​​.meta​

​if (!event.ctrlKey) return​​​ (将 ​​ctrlKey​​​ 分别修改为 ​​altKey​​​、​​shiftKey​​​ 或者 ​​metaKey​​)

7.依赖注入

在Vue中,有几种方法可以让两个组件进行通信,所有这些方法都有优点和缺点。​​2.2​​​版本中引入的一种新方法是使用 ​​Provide/Inject​​ 的依赖注入。

这对选项一起使用,允许一个祖先组件作为其所有后代的依赖注入器,无论组件层次有多深,只要它们在同一个父链上。如果你熟悉React,这与React的上下文功能非常相似。

// parent component providing 'foo'
var Provider = {
  provide: {
    foo: 'bar'
  },
  // ...
}

// child component injecting 'foo'
var Child = {
  inject: ['foo'],
  created () {
    console.log(this.foo) // => "bar"
  }
  // ...
}