Vue 学习笔记 - 深入了解组件

组件注册

组件名

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

该组件名就是 Vue.component 的第一个参数。
当直接在 DOM 中使用一个组件 (而不是在字符串模板单文件组件) 的时候,官方强烈推荐遵循W3C 规范中的自定义组件名 (字母全小写且必须包含一个连字符)。这会帮助你避免和当前以及未来的 HTML 元素相冲突。
你可以在风格指南中查阅到关于组件名的其它建议。

组件名大小写

命名方式 定义 使用
kebab-case 短横线分隔 Vue.component(’my-component-name’, { /* … */ }) <my-component-name>
PascalCase首字母大写 Vue.component(’MyComponentName’, { /* … */ }) <my-component-name> 和 <MyComponentName>

注意直接在 DOM (即非字符串的模板) 中使用时只有 kebab-case 是有效的

全局注册

注册之后新创建的任何根实例都可以用。

Vue.component('my-component-name', {
  // ... 选项 ...
})

局部注册

var ComponentA = { /* ... */ }
var ComponentB = { /* ... */ }
var ComponentC = { /* ... */ }

new Vue({
  el: '#app',
  components: {
    'component-a': ComponentA,
    'component-b': ComponentB
  }
})
  1. 实例初始化时创建,只在实例内有效。
  2. components 中每个propertykey是组件名value是组件对象
  3. 局部注册的组件在其子组件中不可用。如果想 ComponentAComponentB 中可用,则需要这样写:
var ComponentA = { /* ... */ }

var ComponentB = {
  components: {
    'ComponentA': ComponentA // 可以直接简写为:ComponentA。组件名字和值都是 ComponentA
  },
  // ...
}

模块系统

在模块系统中局部注册

  • src\components下为每个组件创建一个目录(同组件名)
  • 然后你需要在局部注册之前导入每个你想使用的组件。例如,在一个假设的ComponentB.jsComponentB.vue 文件中:
import ComponentA from './ComponentA'
import ComponentC from './ComponentC'

export default {
  components: {
    ComponentA,
    ComponentC
  },
  // ...
}

现在 ComponentAComponentC 都可以在 ComponentB 的模板中使用了。

基础组件的自动化全局注册

如果有很多基本的通用组件,如上的一个个注册,太复杂。
如果你恰好使用了webpackVue CLI 3+(在内部使用了 webpack),那么就可以使用 require.context 对想要的组件进行全局注册。

  • 全局注册要在new Vue 实例之前才有意义。
  • 基本流程就是:
    1. 通过require.context获取指定文件夹下所有文件,可以正则过滤文件名,可以控制是否查询其子目录
    2. 遍历文件列表。拼出组件名字,逐个调用Vue.component进行注册。
    3. 例子代码如下:
import Vue from 'vue'
import upperFirst from 'lodash/upperFirst'
import camelCase from 'lodash/camelCase'

const requireComponent = require.context(
  // 其组件目录的相对路径
  './components',
  // 是否查询其子目录
  false,
  // 匹配基础组件文件名的正则表达式
  /Base[A-Z]\w+\.(vue|js)$/
)

requireComponent.keys().forEach(fileName => {
  // 获取组件配置
  const componentConfig = requireComponent(fileName)

  // 获取组件的 PascalCase 命名
  const componentName = upperFirst( //首字大写
    camelCase( // 转为驼峰
      fileName
        .split('/') //把文件路径拆分后最后一个就是文件名
        .pop() // 弹出最后一个
        .replace(/\.\w+$/, '') // 将后缀名去掉
    )
  )

  // 全局注册组件
  Vue.component(
    componentName,
    // 如果这个组件选项是通过 `export default` 导出的,
    // 那么就会优先使用 `.default`,
    // 否则回退到使用模块的根。
    componentConfig.default || componentConfig
  )
})

Prop

Prop 的大小写 (camelCase vs kebab-case)

prop中用驼峰,标签属性还是得写成分隔线

Vue.component('blog-post', {
  // 在 JavaScript 中是 camelCase 的
  props: ['postTitle'],
  template: '<h3>{{ postTitle }}</h3>'
})
<blog-post post-title="hello!"></blog-post>

重申一次,如果你使用字符串模板,那么这个限制就不存在了。(这名我还没理解)

Prop 类型

数组形式默认值为字符串

props: ['title', 'likes', 'isPublished', 'commentIds', 'author']

想定义类型用对象:

props: {
  title: String,
  likes: Number,
  isPublished: Boolean,
  commentIds: Array,
  author: Object,
  callback: Function,
  contactsPromise: Promise // or any other constructor
}

你会在这个页面接下来的部分看到类型检查和其它 prop 验证

传递静态或动态 Prop

前面已经学过:

传值方式 写法 备注
静态字符串 <book title="三国演义"></book > 直接使用 title属性,默认字符串
变量 <book v-bind:title="book.title"></book > 使用了v-bind:指令
此时值就跟着变量走了
表达式 <book v-bind:title="'《' + book.title + '》'"></book > 同上
对象 <book v-bind:mybook="bookOjb"></book > 同上
数字 <book v-bind:page="500"></book > 这里 500没有引号,是数字
布尔值 <book v-bind:hardback></book > 不赋值,存在就默认为true
赋值时当变量看就好了
数组 <book v-bind:characters="['大哥','二第','三弟]"></book > 支持字面量,也支持变量
对象 <book v-bind:character="{name:'刘备'}"></book > 支持字面量,也支持变量

单向数据流

  1. 所有的 prop 只从父组件 =》子组件。父组件中的值更新,子也更新。
  2. 子组件不应该修改prop(逻辑上它表明你想这样 子组件=》父组件但这是禁止的,你会收到错误提示)
  3. 数组对象是引用传递的,对它们内容的修父子之间是同步的。
  4. 子组件想父级数据,就触发事件,让父级监听来处理吧。详见:sync修饰符

两个想编辑prop 的特殊场景:

  1. 初始值,这个应该在子组件中用一个变量来接收,再使用,不应该直接编辑prop
  2. 父传进来的值需要格式化显示,此时推荐使用计算属性computed

Prop 验证

自己编写的组件给别人用时,需要明确prop的一些验证规则,可以用对象形式定义:

Vue.component('my-component', {
  props: {
    // 基础的类型检查 (`null` 和 `undefined` 会通过任何类型验证)
    propA: Number,
    // 多个可能的类型
    propB: [String, Number],
    // 必填的字符串
    propC: {
      type: String,
      required: true
    },
    // 带有默认值的数字
    propD: {
      type: Number,
      default: 100
    },
    // 带有默认值的对象
    propE: {
      type: Object,
      // 对象或数组默认值必须从一个工厂函数获取
      default: function () {
        return { message: 'hello' }
      }
    },
    // 自定义验证函数
    propF: {
      validator: function (value) {
        // 这个值必须匹配下列字符串中的一个
        return ['success', 'warning', 'danger'].indexOf(value) !== -1
      }
    }
  }
})

注意顺序:验证实例化。 (如 data、computed 等 property ) 在 default 或 validator 函数中是不可用的。

类型检查

type 可以是下列原生构造函数中的一个:
String、 Number、 Boolean、 Array、 Object、 Date、 Function、 Symbol
另外还支持自定义的构造函数,如下验证author是否通过new Person创建的

function Person (firstName, lastName) {
  this.firstName = firstName
  this.lastName = lastName
}
Vue.component('blog-post', {
  props: {
    author: Person
  }
})

非 Prop 的 Attribute

  • 组件可以接受任意的attribute
  • 如果组件显示的定义对应的prop,那就它就有着落了。
  • 如果如果组件没有显示的定义对应prop,那么此attribute就会被添加到组件的根元素上。

替换/合并已有的 Attribute

绝大多数 attribute 会用外部提供给组件的值替换掉组件内部设置好的值。
所以如果传入 type="text" 就会替换掉 type="date" 并把它破坏!
幸好classstyle稍微智能一些,会把两部分值合并起来。

禁用 Attribute 继承

设置 inheritAttrs: false 可以在组件中禁用 Attribute 继承(不会影响 styleclass

Vue.component('my-component', {
  inheritAttrs: false,
  // ...
})

inheritAttrs: false 和 $attrs 配合的例子没看懂

自定义事件

事件名

触发:this.$emit('my-event')
监听:v-on:my-event="clickHandler"
事件名会被自动转换为全小写 (因为 HTML 是大小写不敏感的),所以 v-on:myEvent 将会变成 v-on:myevent
因此,官方推荐始终使用 kebab-case 的事件名,如:my-event

自定义组件的 v-model

一个组件上的 v-model 默认会利用名为 value 的 prop 和名为 input 的事件,但是像单选框、复选框等类型的输入控件可能会将 value attribute 用于不同的目的。model 选项可以用来避免这样的冲突:
2.2.0+ 新增的model

Vue.component('base-checkbox', {
  model: {
    prop: 'checked',
    event: 'change'
  },
  props: {
    checked: Boolean
  },
  template: `
    <input
      type="checkbox"
      v-bind:checked="checked"
      v-on:change="$emit('change', $event.target.checked)"
    >
  `
})
<base-checkbox v-model="lovingVue"></base-checkbox>

我们定义了一个叫checkedprop用来接收v-modellovingVue值。当 <base-checkbox>触发 change事件并附带一个新的值的时候,这个 lovingVue将会更新。

将原生事件绑定到组件

直接在自定义组件上监听事件要在事件后.native,此事子组件中的input元素的focus事件能触发

<div id="app">
	<base-input v-on:focus.native="onFocus"></base-input>
</div>

<script>
	Vue.component('base-input', {
		data: function(){
			return {label : '标签:',value: '值123'}
		},
		template: `<input />`
	})
	new Vue({
		el: "#app",
		methods:{
			onFocus: function($event){console.info("获得焦点");}
		}
	});
</script>

但如果子组件中根元素不是input元素。那么.native也没用了。
为了解决这个问题,Vue 提供了一个 $listeners property,它是一个对象,包含了作用在这个组件上的所有监听器。

<div id="app">
	<base-input v-on:focus="onFocus" v-model="myValue"></base-input> {{myValue}}
</div>

<script>
	Vue.component('base-input', {
	  inheritAttrs: false,
	  props: ['label', 'value'],
	  computed: {
	    inputListeners: function () {
	      var vm = this
	      // `Object.assign` 将所有的对象合并为一个新对象
	      return Object.assign({},
	        // 我们从父级添加所有的监听器
	        this.$listeners,
	        // 然后我们添加自定义监听器,
			// 或者覆写一些监听器的行为
	        {
	          // 这里确保组件配合 `v-model` 的工作
	          input: function (event) {
	            vm.$emit('input', event.target.value)
	          }
	        }
	      )
	    }
	  },
	  template: `
	    <label>
	      {{ label }}
	      <input
	        v-bind="$attrs"
	        v-bind:value="value"
	        v-on="inputListeners"
	      >
	    </label>
	  `
	})
	
	new Vue({
		el: "#app",
		data: {myValue : "123"},
		methods:{
			onFocus: function($event){console.info("获得焦点");}
		}
	});
</script>

现在 <base-input> 组件完全透明了,组件内部所有事件都传出来了。
并且重写了input事件,配合v-model="myValue"使用。

.sync 修饰符 (2.3.0+ 新增)

子组件想父级数据,就触发事件,让父级监听来处理。 .sync 修饰符就是这种操作的缩写形式。
注意:

  1. 带有 .sync 修饰符的v-bind 不能和表达式一起使用 (例如 v-bind:title.sync="doc.title + '!'" 是无效的)。取而代之的是,你只能提供你想要绑定的 property 名,类似 v-model
  2. 用一个对象同时设置多个propv-bind.sync="doc"会把 doc 对象中的每个property (如 title) 都作为一个独立的prop传进去,然后各自添加用于更新的v-on监听器。
  3. v-bind.sync 用在一个字面量的对象上,例如 v-bind.sync="{ title: doc.title }"无法正常工作。

插槽

插槽内容

2.6.0中,我们为具名插槽和作用域插槽引入了一个新的统一的语法 (即 v-slot 指令)。它取代了 slotslot-scope 这两个目前已被废弃但未被移除且仍在文档中的 attribute。新语法的由来可查阅这份 RFC

它允许你像这样合成组件:

<navigation-link url="/profile">
  Your Profile
</navigation-link>

然后你在 的模板中可能会写为:

<a> <slot></slot> </a>
  • 当组件渲染的时候<slot></slot>将会被替换为“Your Profile”
  • 插槽内可以包含任何模板代码,包括 HTML,甚至其它的组件
  • 如果没有包含一个<slot>元素,则该组件两个标签之间的内容会被抛弃。

编译作用域

父级模板里的所有内容都是在父级作用域中编译的;子模板里的所有内容都是在子作用域中编译的。

<navigation-link url="/profile">
  {{ url }}  // 这里其实是读取不取 navigation-link 属性 url的。因为这句会先编译好,再传进去替换插槽。
</navigation-link>

后备内容

<slot>就是默认内容</slot> 如果没有传值进来就会使用它。

具名插槽

2.6.0起有所更新。已废弃的使用 slot attribute 的语法在这里

  1. <template> 上【v-slot】指令对应 <slot> 的【name】。
  2. 可以用一个不带 name<slot>,来入所有没定的部分。(默认隐含名字"default"也可以写出来)
<div id="app">
	<my-component >
		<p>其它内容11111111111</p>
		<template v-slot:header>
			<h1>这里对应头部</h1>
		</template>
		<p>其它内容222222222222</p>	
		<p>正文内容正文内容正文内容正文内容正文内容正文内容</p>
		<p>其它内容333333333333</p>
		<template v-slot:footer>
			<p>这里对应足部</p>
		</template>
		<p>其它内容444444444444</p>
	</my-component>
</div>

<script>
	Vue.component('my-component', {
		data: function(){
			return {label : '标签:',value: '值123'}
		},
		template: `<div>
					<slot name="header"></slot>
					<slot ></slot>
					<slot name="footer"></slot> 
				 </div>`
	})
	new Vue({
		el: "#app",
		methods:{
			onFocus: function($event){console.info("获得焦点");}
		}
	});
</script>
  • 效果:
    在这里插入图片描述
  1. 2.6.0中引入新语法 <template> 使用v-slot 指令
  2. 注意 v-slot 只能添加在 <template> 上 (只有一种例外情况)

注意 v-slot 只能添加在 <template> 上 (只有一种例外情况),这一点和已经废弃的 slot attribute 不同。

作用域插槽

自 2.6.0 起有所更新。已废弃的使用 slot-scope attribute 的语法在这里
<current-user>组件:

<span>
  <slot>{{ user.lastName }}</slot>
</span>

如果想这样换掉备用内容。是无效的

<current-user>
  {{ user.firstName }}
</current-user>

想要实现这个目标,模板使用时都要调整一下

  • 模板调整:
    为了让 user 在父级的插槽内容中可用,我们可以将user 作为<slot>元素的一个 attribute 绑定上去,<current-user>组件如下调整:<slot v-bind:user="user">{{ user.lastName }}</slot>
  • 使用时调整
    绑定在<slot>元素上的 attribute 被称为插槽 prop
    现在在父级作用域中,我们可以使用带值的 v-slot 来定义我们提供的插槽 prop 的名字:(为包含所有default插槽prop的对象取名slotProps 这个名字可以自己喜欢怎么取都行)
<div id="app">
	<current-user>
	  <template v-slot:default="slotProps">
		{{ slotProps.user.lastName }}{{ slotProps.user.firstName }}
	  </template>
	</current-user>
</div>

<script>
	Vue.component('current-user', {
		data: function(){
			return {user : {firstName:"jin", lastName:"jerry" }}
		},
		template: `<div><slot v-bind:user="user">{{ user.lastName }}</slot></div>`
	})
	new Vue({
		el: "#app"
	});
</script>

独占默认插槽的缩写语法

当被提供的内容只有默认插槽时v-slot可以直接用在组件上。

<current-user v-slot:default="slotProps">
	{{ slotProps.user.lastName }}{{ slotProps.user.firstName }}
</current-user>

还可以再简化,省掉:default

<current-user v-slot="slotProps">
	{{ slotProps.user.lastName }}{{ slotProps.user.firstName }}
</current-user>

注意默认插槽的缩写语法不能具名插槽混用,因为它会导致作用域不明确:

<!-- 无效,会导致警告 -->
<current-user v-slot="slotProps">
  {{ slotProps.user.firstName }}
  <template v-slot:other="otherSlotProps">
    slotProps is NOT available here
  </template>
</current-user>

只要出现多个插槽,请始终为所有的插槽使用完整的基于 <template>的语法:

<current-user>
  <template v-slot:default="slotProps">
    {{ slotProps.user.firstName }}
  </template>

  <template v-slot:other="otherSlotProps">
    ...
  </template>
</current-user>

解构插槽 Prop

作用域插槽的内部工作原理是将你的插槽内容包括在一个传入单个参数的函数里:

function (slotProps) {
  // 插槽内容
}

这意味着 v-slot 的值实际上可以是任何能够作为函数定义中的参数的 JavaScript 表达式。所以在支持的环境下 (单文件组件现代浏览器),你也可以使用 ES2015 解构来传入具体的插槽 prop,如下:

<current-user v-slot="{ user }">
  {{ user.firstName }}
</current-user>

这样可以使模板更简洁,尤其是在该插槽提供了多个 prop 的时候。它同样开启了 prop 重命名等其它可能,例如将 user 重命名为person

<current-user v-slot="{ user: person }">
  {{ person.firstName }}
</current-user>

你甚至可以定义后备内容,用于插槽 prop 是 undefined 的情形:

<current-user v-slot="{ user = { firstName: 'Guest' } }">
  {{ user.firstName }}
</current-user>

动态插槽名 2.6.0 新增

动态指令参数也可以用在 v-slot上,来定义动态的插槽名:

<base-layout>
  <template v-slot:[dynamicSlotName]>
    ...
  </template>
</base-layout>

具名插槽的缩写 2.6.0 新增

  • v-slot:替换为字符# 例如: v-slot:header 可以被重写为 #header
  • 缩写只在其有参数的时候才可用。如下省了 default 这样会触发一个警告。
<current-user #="{ user }">
  {{ user.firstName }}
</current-user>
  • 把默认插槽名写上#default="{ user }"就可以了
<current-user #default="{ user }">
  {{ user.firstName }}
</current-user>

其它示例

插槽 prop 允许我们将插槽转换为可复用的模板,这些模板可以基于输入的 prop 渲染出不同的内容。这在设计封装数据逻辑同时允许父级组件自定义部分布局的可复用组件时是最有用的。
例如,我们要实现一个 <todo-list>组件,它是一个列表且包含布局和过滤逻辑:

<ul>
  <li v-for="todo in filteredTodos" v-bind:key="todo.id">
      {{ todo.text }}
  </li>
</ul>

我们可以将每个 todo 作为父级组件的插槽,以此通过父级组件对其进行控制,然后将 todo 作为一个插槽 prop 进行绑定:

<ul>
  <li v-for="todo in filteredTodos" v-bind:key="todo.id" >
    <!-- 我们为每个 todo 准备了一个插槽, 将 `todo` 对象作为一个插槽的 prop 传入。 -->
    <slot name="todo" v-bind:todo="todo">
        {{ todo.text }} <!-- 后备内容 -->
    </slot>
  </li>
</ul>

现在当我们使用 <todo-list> 组件的时候,我们可以选择为 todo 定义一个不一样的 <template> 作为替代方案,并且可以从子组件获取数据:

<todo-list v-bind:todos="todos">
  <template v-slot:todo="{ todo }">
    <span v-if="todo.isComplete"></span>
    {{ todo.text }}
  </template>
</todo-list>

这只是作用域插槽用武之地的冰山一角。想了解更多现实生活中的作用域插槽的用法,我们推荐浏览诸如 Vue Virtual ScrollerVue PromisedPortal Vue 等库。

废弃了的语法

v-slot 指令自 Vue 2.6.0 起被引入,提供更好的支持 slotslot-scope attribute 的 API 替代方案。v-slot 完整的由来参见这份 RFC。在接下来所有的 2.x 版本中 slotslot-scope attribute 仍会被支持,但已经被官方废弃且不会出现在 Vue 3 中。

带有 slot attribute 的具名插槽

2.6.0 起被废弃。新推荐的语法请查阅这里

<base-layout>
  <template slot="header">
    <h1>Here might be a page title</h1>
  </template>

  <p>A paragraph for the main content.</p>

  <template slot="footer">
    <p>Here's some contact info</p>
  </template>
</base-layout>

或者直接把 slot attribute 用在一个普通元素上:

<base-layout>
  <h1 slot="header">Here might be a page title</h1>

  <p>A paragraph for the main content.</p>
  <p>And another one.</p>

  <p slot="footer">Here's some contact info</p>
</base-layout>

这里其实还有一个未命名插槽,也就是默认插槽,捕获所有未被匹配的内容。

带有 slot-scope attribute 的作用域插槽

2.6.0 起被废弃。新推荐的语法请查阅这里
<template> 上使用特殊的 slot-scope attribute,可以接收传递给插槽的 prop (把这里提到过的 <slot-example> 组件作为示例):

<slot-example>
  <template slot="default" slot-scope="slotProps">
    {{ slotProps.msg }}
  </template>
</slot-example>

这里的 slot-scope 声明了被接收的 prop 对象会作为 slotProps 变量存在于 <template> 作用域中。你可以像命名 JavaScript 函数参数一样随意命名 slotProps

  • 这里的 slot="default"可以省略。
<slot-example>
  <template slot-scope="slotProps">
    {{ slotProps.msg }}
  </template>
</slot-example>

slot-scope attribute 也可以直接用于非 <template>元素 (包括组件):

<slot-example>
  <span slot-scope="slotProps">
    {{ slotProps.msg }}
  </span>
</slot-example>

slot-scope 的值可以接收任何有效的可以出现在函数定义的参数位置上的 JavaScript 表达式。这意味着在支持的环境下 (单文件组件现代浏览器),你也可以在表达式中使用 ES2015 解构,如下:

<slot-example>
  <span slot-scope="{ msg }">
    {{ msg }}
  </span>
</slot-example>

使用这里描述过的 <todo-list> 作为示例,与它等价的使用 slot-scope 的代码是:

<todo-list v-bind:todos="todos">
  <template slot="todo" slot-scope="{ todo }">
    <span v-if="todo.isComplete"></span>
    {{ todo.text }}
  </template>
</todo-list>

动态组件 & 异步组件

在动态组件上使用 keep-alive

之前学过用 <component v-bind:is="currentTabComponent"></component> 实现标签页,但切换标签时,组件都会重新渲染。
如果不想这样可以用:keep-alive。 它包裹动态组件时,会缓存不活动的组件实例,而不是销毁它们。。查看API文档了解更多详情

<!-- 失活的组件将会被缓存!-->
<keep-alive>
  <component v-bind:is="currentTabComponent"></component>
</keep-alive>

注意这个<keep-alive> 要求被切换到的组件都有自己的名字,不论是通过组件的name 选项还是局部/全局注册。
你可以在这里查看完整示例代码

异步组件

为了简化分包懒加载。Vue 允许你以一个工厂函数的方式定义你的组件,这个工厂函数会异步解析你的组件定义。Vue 只有在这个组件需要被渲染的时候才会触发该工厂函数,且会把结果缓存起来供未来重渲染。例如:

Vue.component('async-example', function (resolve, reject) {
  setTimeout(function () {
    // 向 `resolve` 回调传递组件定义
    resolve({
      template: '<div>I am async!</div>'
    })
  }, 1000)
})

如你所见,这个工厂函数会收到一个 resolve 回调,这个回调函数会在你从服务器得到组件定义的时候被调用。你也可以调用 reject(reason) 来表示加载失败。这里的 setTimeout 是为了演示用的,如何获取组件取决于你自己。一个推荐的做法是将异步组件和 webpack 的 code-splitting 功能一起配合使用:

Vue.component('async-webpack-example', function (resolve) {
  // 这个特殊的 `require` 语法将会告诉 webpack
  // 自动将你的构建代码切割成多个包,这些包
  // 会通过 Ajax 请求加载
  require(['./my-async-component'], resolve)
})

你也可以在工厂函数中返回一个Promise,所以把 webpack 2 和 ES2015 语法加在一起,我们可以这样使用动态导入:

Vue.component(
  'async-webpack-example',
  // 这个动态导入会返回一个 `Promise` 对象。
  () => import('./my-async-component')
)

当使用局部注册的时候,你也可以直接提供一个返回 Promise 的函数:

处理加载状态 2.3.0+ 新增

这里的异步组件工厂函数也可以返回一个如下格式的对象:

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

注意如果你希望在Vue Router 的路由组件中使用上述语法的话,你必须使用 Vue Router 2.4.0+ 版本。

处理边界情况

这里记录的都是和处理边界情况有关的功能,即一些需要对 Vue 的规则做一些小调整的特殊情况。不过注意这些功能都是有劣势或危险的场景的。我们会在每个案例中注明,所以当你使用每个功能的时候请稍加留意。

直接看官方教程

参考资料

Vue 官方教程基数篇 - 本笔记的学习对象
Vue 官方CLI 官方文档
Vue 官方API 参考
Vue 官方API文档 - 生命周期钩子

vue-devtools 编译安装
我的 Vue CLI 学习笔记
Vue 学习笔记 - 基础(上)
Vue 学习笔记 - 基础(中)
Vue 学习笔记 - 基础(下)组件基础
Vue 学习笔记 - 深入了解组件

MDN 完整有效按键名 Key Values
千锋教育-李卫民 Vue 渐进式 JavaScript 框架

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章