全局组件
<my-button></my-button>
Vue.component('my-button',{
template:'<button>点我啊</button>'
})
let vm = new Vue({
el:'#app'
})
局部组件
<my-button></my-button>
let vm = new Vue({
el:'#app',
components:{
'MyButton':{
template:'<button>按钮</button>'
}
}
});
HTML不支持自闭合的自定义元素,在DOM模板里永远不要使用自闭和组件,在HTML中也不支持MyButton的写法,所以组件调用全部使用短横线连接的方式!
https://www.w3.org/TR/html/syntax.html#void-elements
在组件中的数据必须是函数的形式
'MyButton':{
data(){
return {content:'按钮'}
},
template:'<button>{{content}}</button>'
}
<my-button button-content="按钮"></my-button>
components:{
'MyButton':{
props:['buttonContent'],
template:'<button>{{buttonContent}}</button>'
}
}
属性在组件标签上需要使用短横线命名法,在组件中声明需要采用驼峰命名法
<my-button button-content="按钮" :number="'1'"></my-button>
components:{
'MyButton':{
props:{
buttonContent:String,
arr:{
type:Array,
default:()=>([])
},
number:{
type:Number,
validator:(value)=>{
return typeof value == 'number'
}
},
},
template:'<button>{{buttonContent}} {{arr}} {{number}}</button>'
}
}
<my-button v-bind="info"></my-button>
let vm = new Vue({
el:'#app',
data:{
info:{name:'姜文',age:18}
},
components:{
'MyButton':{
props:['name','age'],
inheritAttrs:false,
mounted(){
console.log(this.$attrs)
},
template:'<button>{{name}} {{age}} </button>'
}
}
});
<!-- 给组件绑定方法,在内部触发绑定的方法 -->
<my-button @click="change" msg="按钮"></my-button>
let vm = new Vue({
el:'#app',
methods:{
change(){ alert('hello'); }
},
components:{
'MyButton':{
props:['msg'],
template:`<div>
<button @click="this.$listeners.click">{{msg}}</button>
<button v-on="this.$listeners">{{msg}}</button>
<button @click="$emit('click')"></button>
</div>`
}
}
});
在组件的根元素上直接监听一个原生事件
<my-button @click.native="change"></my-button>
实现收缩面板功能
<collapse>
<collapse-item title="react">内容1</collapse-item>
<collapse-item title="vue">内容2</collapse-item>
<collapse-item title="node">内容3</collapse-item>
</collapse>
Vue.component('Collapse',{
methods:{
open(id){
this.$children.forEach(child => {
if(child._uid != id){
child.show = false;
}
});
}
},
template:`<div class="wrap">
<slot></slot>
</div>`
});
Vue.component('CollapseItem',{
props:['title'],
data(){
return {show:true}
},
methods:{
change(){
this.$parent.open(this._uid);
this.show =!this.show;
}
},
template:`<div class="collapse-item" @click="change">
<div class="title">{{title}}</div>
<div v-show="show">
<slot></slot>
</div>
</div>`
});
v-slot:可以简写成#
<List>
<template v-slot:banana>🍌</template>
<template v-slot:apple>🍎</template>
🍊
</List>
list:{
template:`
<ul>
<li><slot></slot></li>
<li><slot name="banner"></slot></li>
<li><slot name="apple"></slot></li>
</ul>
`
}
作用域插槽
<List #default="{val}">
{{val}}
</List>
list:{
data(){
return {arr:[1,2,3]}
},
template:`
<ul>
<li v-for="a in arr" :key="a">
<slot :val="a">{{a}}</slot>
</li>
</ul>
`
}
跨组件数据传递,主要为高阶插件/组件库提供用例
provide:{ name:'zf' },
components:{
list:{
inject:['name'],
template:`<div>{{name}}</div>`
}
}
.sync 和 v-model的使用
<div id="app">
{{msg}}
<tab :msg="msg" @update:msg="change"></tab>
<tab :msg.sync="msg"></tab>
<tab v-model="msg"></tab>
</div>
let vm = new Vue({
el:'#app',
data:{
msg:'hello'
},
methods:{
change(value){
this.msg = value
}
},
components:{
tab:{
props:['msg'],
methods:{
change(){
this.$emit('update:msg','world')
this.$emit('input','world');
}
},
template:`<div>
{{msg}} <button @click="change">切换</button>
</div>`
}
}
})
// 在组件中可以获取组件实例
<tab :msg="msg" @update:msg="change" ref="ele"></tab>
this.$refs.ele.change()
// 放在dom上表示获取当前dom元素
<div ref="ele"></div>
this.$refs.ele.style.border="1px solid red"
// 在v-for中获取的是集合
<template v-for="a in 3">
<tab :msg="msg" @update:msg="change" ref="ele" :key="a"></tab>
</template>
console.log(this.$refs.ele.length)
Vue.component('async', function (resolve, reject) {
setTimeout(function () {
resolve({
template: '<div>异步组件</div>'
})
}, 1000);
});
在后期我们一般配合webpack的import语法使用