Vue学习笔记(组件篇)
1、组件用法
全局注册:全局注册后,任何vue实例都能使用(template的dom结构必须被元素包含,否则无法渲染)
<div id="app">
<my-component></my-component>
</div>
Vue.component("my-component",{
template:"<div>这里是组件的内容</div>"
})
new Vue({
el:'#app'
})
渲染结果:
<div id="app">
<div>这里是组件的内容</div>
</div>
局部注册:
<div id="app">
<my-component></my-component>
</div>
new Vue({
el:'#app',
components:{
"my-component":{
template:"<div>这里是组件的内容</div>"
}
}
})
table中使用组件可以用is来挂载(ul、ol、select)
<table>
<tbody is="my-component"></tbody>
</table>
Vue.component("my-component",{
template:"<div>这里是组件的内容</div>"
})
new Vue({
el:"#app"
})
组件还可以使用data、computed、methods等,不过data是函数,需要return这个值
组件动态获取父级数据
<my-component :warning-text="parentMessage"></my-component>
Vue.component("my-components",{
props:['warningText'],
template:'<div>{{warningText}}</div>'
})
new Vue({
el:"#app",
data:{
parentMessage:"xxx"
}
})
2、单项数据流
<my-component :init-count="1"></my-component>
Vue.component("my-component",{
props:['initCount'],
template:<div>{{count}}</div>,
data:function(){
return {
count:this.initCount
}
}
})
new Vue({
el:'#app'
})
<my-component :width="100"></my-component>
Vue.component("my-component",{
props:['width'],
template:'<div :style="style"></div>',
computed:{
style:function(){
return {
width:this.width+'px'
}
}
}
});
new Vue({
el:"#app"
})
3、数据验证
Vue.component("my-component",{
props:{
propA:Number,
propB:[String,Mumber], //字符串或者number
propC:{
type:Boolean, boolean类型,默认为true
default:true
},
propD:{
type:Number,
required:true //Number类型,必传
},
propE:{
type:Array, //数组或对象,默认值必须函数来返回
default:function(){
return []
}
},
propF:{
validator:function(value){
return value>10 自定义验证函数
}
}
}
})
4、组件通信
1、自定义事件
父组件可以在子组件自定义标签上通过v-on来监听自定义事件
<div id="app">
<p>{{total}}</p>
<my-component :increase="handleGetTotal" :reduce="handleGetTotal"></my-component>
</div>
Vue.component("my-component",{
template:'<button @click="handleIncrease">+1</button><button @click="handleReduce">-1</button>',
data:function(){
return {
counter:0
}
},
methods:{
handleIncrease:function(){
this.counter++;
this.$emit("increase",this.counter);
},
handleReduce:function(){
this.counter--;
this.$emit("reduce",this.counter);
}
}
})
new Vue({
el:'#app',
data:{
total:0
},
methods:{
handleGetTotal:function(total){
this.total=total;
}
}
})
v-model
<div id="app">
<div>总数{{total}}<div>
<my-component v-model="total"></my-component>
</div>
Vue.component("my-component",{
template:'<button @click="handleClick">+1</button>',
data:function(){
return {
counter:0
}
},
methods:{
handleClick:function(){
this.counter++;
this.$emit("input",this.counter);
}
}
})
new Vue({
el:'#app',
data:{
total:0
}
})
相当于使用@input="handle"
v-model创建自定义表单输入组件进行双向绑定(接收一个value属性,value有变化时触发input事件)
<div id="app">
<p>总数:{{total}}</p>
<my-component v-model="total"></my-component>
<button @click="handleReduce">-1</button>
</div>
Vue.component("my-component",{
props:"value",
template:'<input :value="value" @input="updateValue">',
methods:{
updateValue:function(event){
this.$emit("input",event.target.value);
}
}
})
new Vue({
el:'#app',
data:{
total:0
},
methods:{
handleReduce:function(){
this.total--;
}
}
})
2、非父子组件通信
中央事件总线bus
<div id="app">
{{message}}
<component-a></component-a>
</div>
var bus=new Vue();
Vue.component("component-a",{
template:'<button @click="handleClick">传递事件</button>',
methods:{
handleClick:function(){
bus.$emit("on-message","来自a的类容");
}
}
});
new Vue({
el:'#app',
data:{
message:''
},
mounted:function(){
var _this=this;
bus.$on("on-message",function(msg){
_this.message=msg;
})
}
})
父链
this.$parent可以访问该实例的父实例或组件,this.$children访问所有的子组件
<div id="app">
{{message}}
<component-a></component-a>
</div>
Vue.component("component-a",{
template:'<button @click="handleClick">button</button>',
methods:{
handleClick:function(){
this.$parent.message="来自。。的消息";
}
}
})
new Vue({
el:'#app',
data:{
message:''
}
})
子组件索引(通过ref为为字组件指定一个索引)
<div id="app">
<button @click="handleref">获取子组件实例</button>
<component-a ref="comA"></component-a>
</div>
Vue.component("component-a",{
template:'<div>子组件</div>',
data:function(){
return:{
message:'子组件内容'
}
}
})
new Vue({
el:"#app",
methods:{
handleref:function(){
var msg=this.$refs.comA.message;
console.log(msg);
}
}
})
3、slot分发
<div id="app">
<child>
<p>分发的内容</p>
</child>
</div>
vue.component("child",{
template:'\
<div>\
<slot>\
<p>这是默认内容</p>\
</slot>\
</div>'
})
new Vue({
el:'#app'
})
子组件<slot>元素里面定义了一个默认内容,如果父组件没有使用slot,则渲染默认的内容,如果使用了,则替换整个<slot>,分发的内容作用域在父组件上,子组件模板上的内容,
作用域在子组件上。
<div id="app">
<child-component>
<h2 slot="header">标题</h2>
<p>正文</p>
<div slot="footer">底部信息</div>
</child-component>
</div>
vue.component("child-component",{
template:'<div>\
<div class="header">\
<slot name="header"></slot>\
</div>\
<div class="main">\
<slot></slot>\
</div>\
<div class="footer">\
<slot name="footer"></slot>\
</div>\
</div>'
})
new Vue({
el:"#app"
})
指定了name特性的,相应的slot会被替换,没有使用特性的会替换默认slot,没有默认slot则父组件多余的不会显示
4、作用域插槽
<div id="app">
<child-component>
<template scope="props">
<p>父组件的内容</p>
<p>{{props.msg}}</p>
</template>
</child-component>
</div>
vue.component("child-component",{
template:'\
<div class="container">\
<slot msg="来自子组件的内容"></slot>\
</div>'
})
new Vue({
el:'#app'
})
props是一个临时变量,可通过这个变量访问子组件插槽的数据,如msg
渲染结果:
<div id="app">
<div class="container">
<p>父组件内容</p>
<p>来自子组件的内容</p>
</div>
</div>
列表组件
<div id="app">
<my-list :books="books">
<template scope="props" slot="book">
<li>{{props.bookName}}</li>
</template>
</my-list>
</div>
Vue.component("my-list",{
props:{
books:{
type:Array,
default:function(){
return []
}
}
},
template:'\
<ul>\
<slot name="book" v-for="book in books" :book-name="book.name"></slot>\
</ul>'
})
new Vue({
el:'#app',
data:{
books:[
{name:"js"},
{name:"java"}
]
}
})
作用域插槽使用场景:既可以复用子组件的slot,又可以使slot内容不同
5、访问slot
<div id="app">
<child-component>
<h2 slot="header"></h2>
<p>xxxx</p>
<div slot="footer"></div>
</child-component>
</div>
Vue.component("child-component",{
template:'\
<div class="header">\
<slot name="header"></slot>\
</div>\
<div class="main">\
<slot></slot>\
</div>\
',
mounted:function(){
var header=this.$slots.header;
var main=this.$slots.default;
console.log(header);
console.log(header[0].elm.innerHTML)
}
})
new Vue({
el:'#app'
})
5、组件高级用法
1、递归组件(设置name属性,必须有数量限制,不能无限递归)
<div id="app">
<child-component :count="1"></child-component>
</div>
Vue.component("child-component",{
name:"child-component",
props:{
count:{
type:Number,
default:1
}
},
template:'\
<div class="child">\
<child-component :count="count+1" v-if="count<3"></child-component>
</div>'
})
new Vue({
el:'#app'
})
2、内联模板
在使用组件时,在组件标签上使用inline-template特性,组件会把他的内容当模板,不会对内容进行分发。
3、动态组件
通过<component>元素动态挂载不同的组件
<div id="app">
<component :id="currentView"></component>
<button @click="handleClick('A')">挂载A</button>
<button @click="handleClick('B')">挂载B</button>
</div>
new Vue({
el:'#app',
data:{
currentView:'comA'
},
components:{
comA:{
template:'<div>组件A</div>'
},
comB:{
template:'<div>组件B</div>'
},
},
methods:{
handleClick:function(component){
this.currentView="com"+component;
}
}
})
4、异步组件
<div id="app">
<child-component></child-component>
</div>
Vue.component("child-component",function(resolve,reject){
setTimeout(function(){
resolve({
template:"异步渲染"
})
},2000)
})