Vue.component('my-component-name', { /* ... */ })这里的
my-component-name
就是组件名,组件名的取法能够参考指南
kebab-case写法(-链接单词) 推荐的写法
定义:javascript
Vue.component('my-component-name', { /* ... */ })
用法:html
<my-component-name></my-component-name>
PascalCase写法(单词首字母大写)vue
Vue.component('MyComponentName', { /* ... */ })
Vue.component('my-component-name', { /* ... */ })
var ComponentA = { /* ... */ } var ComponentB = { /* ... */ }而后在
components
选项中定义你想要使用的组件: new Vue({ el: '#app', components: { 'component-a': ComponentA, 'component-b': ComponentB } })对于 components 对象中的每一个属性来讲,其属性名就是自定义元素的名字,其属性值就是这个组件的选项对象。
var ComponentA = { /* ... */ } var ComponentB = { components: { 'component-a': ComponentA }, // ... }或者若是你经过 Babel 和 webpack 使用 ES2015 模块,那么代码看起来更像:
import ComponentA from './ComponentA.vue' export default { components: { ComponentA }, // ... }
import/require
使用一个模块系统
import ComponentA from './ComponentA' import ComponentC from './ComponentC' export default { components: { ComponentA, ComponentC }, // ... }
prop大小写(camelCase vs kebab-case)
HTML 中的特性(属性)名是大小写不敏感的,因此浏览器会把全部大写字符解释为小写字符,camelCase (驼峰命名法) 的 prop 名须要使用其等价的 kebab-case (短横线分隔命名) 命名:java
Vue.component('blog-post', { // 在 JavaScript 中是 camelCase 的 props: ['postTitle'], template: '<h3>{{ postTitle }}</h3>' })
<!-- 在 HTML 中是 kebab-case 的 --> <blog-post post-title="hello!"></blog-post>
所以,强烈建议
用kebab-case
写法。webpack
prop 类型
一般,以字符串数组形式列出 prop:git
props: ['title', 'likes', 'isPublished', 'commentIds', 'author']
可是,一般你但愿每一个 prop 都有指定的值类型。这时,你能够以对象形式列出 prop,这些属性的名称和值分别是 prop 各自的名称和类型:github
props: { title: String, likes: Number, isPublished: Boolean, commentIds: Array, author: Object, callback: Function, contactsPromise: Promise // or any other constructor }
传递静态或动态prop
传递静态值:web
<blog-post title="My journey with Vue"></blog-post>
传递动态值数组
<!-- 动态赋予一个变量的值 --> <blog-post v-bind:title="post.title"></blog-post> <!-- 动态赋予一个复杂表达式的值 --> <blog-post v-bind:title="post.title + ' by ' + post.author.name" ></blog-post>
实际上,能传递的值包括:字符串、数字、布尔值、数组、对象、对象全部属性。浏览器
单向数据流
全部的 prop 都使得其父子 prop 之间造成了一个单向下行绑定:父级 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 } } } })
上面的type
能够是原生构造函数的一个:String
,Number
,Boolean
,Array
,Object
,Date
,Function
,Symbol
。
非 Prop 的特性
一个非 prop 特性是指传向一个组件,可是该组件并无相应 prop 定义的特性。
class
和 style
特性会稍微智能一些,即两边的值会被合并起来。inheritAttrs: false
,适合配合实例的 $attrs 属性使用: Vue.component('base-input', { inheritAttrs: false, props: ['label', 'value'], template: ` <label> {{ label }} <input v-bind="$attrs" v-bind:value="value" v-on:input="$emit('input', $event.target.value)" > </label> ` })
事件名
不一样于组件和 prop,事件名不存在任何自动化的大小写转换。而是触发的事件名须要彻底匹配
监听这个事件所用的名称:
this.$emit('myEvent')
则监听这个名字的 kebab-case 版本是不会有任何效果的:
<!-- 没有效果 --> <my-component v-on:my-event="doSomething"></my-component>
推荐始终使用 kebab-case 的事件名
自定义组件的 v-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>
将原生事件绑定到组件
使用 v-on 的 .native 修饰符:
<base-input v-on:focus.native="onFocus"></base-input>
Vue 提供了一个 $listeners 属性,它是一个对象,里面包含了做用在这个组件上的全部监听器。能够配合 v-on="$listeners" 将全部的事件监听器指向这个组件的某个特定的子元素。
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> ` })
.sync 修饰符
以 update:myPropName
的模式触发事件
this.$emit('update:title', newTitle)
<text-document v-bind:title="doc.title" v-on:update:title="doc.title = $event" ></text-document>
缩写:
<text-document v-bind:title.sync="doc.title"></text-document>
同时设置多个 prop :
<text-document v-bind.sync="doc"></text-document>
插槽内容
<navigation-link url="/profile"> Your Profile </navigation-link>
<navigation-link>
的模板中:
<a v-bind:href="url" class="nav-link"> <slot></slot> </a>
则Your Profile
会替换<slot></slot>
部分。Your Profile
能够是HTML代码或者其余插件。
编译做用域
父级模板里的全部内容都是在父级做用域中编译的;子模板里的全部内容都是在子做用域中编译的。
<navigation-link url="/profile"> Clicking here will send you to: {{ url }} <!-- 这里的 `url` 会是 undefined,由于 "/profile" 是 _传递给_ <navigation-link> 的而不是 在 <navigation-link> 组件内部定义的。 --> </navigation-link>
后备内容(默认值)
<button type="submit"> <slot>Submit</slot> </button>
这里的Submit
就是默认值。
具名插槽
<slot>
元素有一个特殊的特性:name
。这个特性能够用来定义额外的插槽:
<div class="container"> <header> <slot name="header"></slot> </header> <main> <slot></slot> </main> <footer> <slot name="footer"></slot> </footer> </div>
一个不带 name
的 <slot>
出口会带有隐含的名字“default”。
在一个 <template>
元素上使用 v-slot
指令,并以 v-slot 的参数的形式提供其名称:
<base-layout> <template v-slot:header> <h1>Here might be a page title</h1> </template> <p>A paragraph for the main content.</p> <p>And another one.</p> <template v-slot:footer> <p>Here's some contact info</p> </template> </base-layout>
做用域插槽
绑定在 <slot>
元素上的特性被称为插槽 prop
。如今在父级做用域中,咱们能够给 v-slot 带一个值来定义咱们提供的插槽 prop
的名字:
<current-user> <template v-slot:default="slotProps"> {{ slotProps.user.firstName }} </template> </current-user>
独占默认插槽的缩写语法
<current-user v-slot:default="slotProps"> {{ slotProps.user.firstName }} </current-user>
解构插槽 Prop
<current-user v-slot="{ user }"> {{ user.firstName }} </current-user>
动态插槽名
<base-layout> <template v-slot:[dynamicSlotName]> ... </template> </base-layout>
具名插槽的缩写
(v-slot:
) 替换为字符 #
:
其它示例(略)
在动态组件上使用 keep-alive
曾经在一个多标签的界面中使用 is
特性来切换不一样的组件:
<component v-bind:is="currentTabComponent"></component>
能够用一个 <keep-alive>
元素将其动态组件包裹起来,避免切换的时候从新渲染:
<!-- 失活的组件将会被缓存!--> <keep-alive> <component v-bind:is="currentTabComponent"></component> </keep-alive>
异步组件(略)
这些特殊场景和危险状况须要留心~
访问元素 & 组件
$root
属性$parent
属性ref
特性provide
和 inject
。程序化的事件侦听器
$on(eventName, eventHandler)
侦听一个事件$once(eventName, eventHandler)
一次性侦听一个事件$off(eventName, eventHandler)
中止侦听一个事件循环引用
模板定义的替代品
控制更新
$forceUpdate
v-once
建立低开销的静态组件