组件注册
全局注册
- 注册组件,传入一个扩展过的构造器
Vue.component('my-component', Vue.extend({/*...*/}))
- 注册组件,传入一个选项对象(自动调用Vue.extend)
Vue.component('my-component', {/*...*/})
- 获取注册的组件(始终返回构造器)
let MyComponent = Vue.component('my-component')
局部注册
- 通过普通的javascript对象来定义组件
var MyComponent = {/*...*/}
- 在component选项中定义要使用的组件
new Vue({ el:'#app', component:{ 'my-component': MyComponent } })
自动化全局注册组件
- 主要使用
require.context
const contexts = require.context( './MyComponent', // 其组件目录的相对路径 false, // 是否查询其子目录 /\.vue$/ // 匹配基础组件文件名的正则表达式 ) contexts.keys().forEach(component =>{ // 如果这个组件选项是通过`export.default` 导出的 // 那么就会优先使用default const componentConfig = contexts(component).default // 全局注册组件 Vue.component(componentConfig.name, componentConfig) })
组件核心
属性prop
单向数据流
- 传递初始值,并作为本地数据来调用
{ props:['count'], data(){ return { counter: this.count } } }
- 传入初始值,使用计算属性来进行装换
{ props:['str'], computed: { normalizedStr(){ return this.str.trim().toLowerCase() } } }
双向绑定```// 子组件派发事件,更新名为title的propthis.$emit('update:title',newTitle)// 父组件监听事件并更新本地数据属性<text-document:title='doc.title'@update:title='doc.title = $event'></text-document>
// 上面可以简写成如下
<text-document
:title.sync='doc.title'
>
</text-document>
// 如果用一个对象同时设置多个prop时可以采用如下写法
<text-document
v-bind.sync = 'doc'
>
</text-document>
```
特性继承
- 默认情况下父作用域的不被认作 props 的特性绑定将会“回退”且作为普通的 HTML 特性应用在子组件的根元素上。
- 通过inheritAttrs设置为false可将其禁用
- 反之,$attrs可以让这些特性生效,并提供访问,它包含了父级所有不被prop识别的特性绑定。
- 使用v-bind=“$attrs”可以将这些特性传入内部组件
- 注意:class和style例外,vue会对其进行特别处理。
见下代码
Vue.component('base-input', {
inheritAttrs: false,
props: ['label', 'value'],
template: `
<label>
{{label}}
<input
v-bind="$attrs"
:value="value"
@input="$emit('input',$event.target.value)"
>
</label>
`
})
事件
自定义事件
- 通过v-model语法糖实现数据双向绑定
Vue.component('base-checkbox', {
model: {
prop: 'checkbox',
event: 'change'
},
props: {
checked:Boolean
},
template: `
<input
type="checkbox"
:checked="checked"
@change="$emit('change',$event.target.checked)"
>
`
})
绑定原生事件
// 监听组件根元素的原生事件
<base-input
v-on:focus.native="onFocus"
>
</base-input>
// 如果根元素不具备该原生事件,事件监听将静默失败
<label>
{{label}}
<input
v-bind='$attrs'
:value="value"
@input="$emit('input',$event.target.value)"
>
</label>
事件传递
- $listeners包含了父作用域中的(不含.native修饰符)的v-on事件监听器。
- 可以通过v-on=“$listeners”传入内部组件。
- 同时结合v-bind=“$attrs”传入父作用域中所有不被prop识别的属性,完成属性和事件的传递。
下面看一个例子
Vue.component('base-input', {
inheritAttrs:false,
props: ['lable', 'value'],
computed:{
inputListeners(){
return Object.assgin({},
this.$listeners,
{
input(event){
this.$emit('input',event.target.value)
}
}
)
}
},
template: `
<label>
{{label}}
<input
v-bind='$attrs'
:value="value"
v-on="inputListeners"
>
</label>
`
})
插槽
编译作用域
- 父级模板里的所有内容都是在父级作用域中编译的;子模板里的所有内容都是在子作用域中编译的。