组件用法
全局注册
- 组件需要注册后才能使用
- 注册有全局注册和局部注册两种方式
<div id="app">
<my-component></my-component>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<script>
Vue.component('my-component',{
template:'<div>这是一个组件的内容</div>'
});
var app = new Vue({
el:'#app',
data:{
selected:''
}
});
</script>
- template的DOM结构必需被一个元素包含
局部注册
- 使用component可以局部注册组件,注册后只能在该实例作用域下有效,使组件可以嵌套
<div id="app">
<my-component></my-component>
<my-components></my-components>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<script>
Vue.component('my-component',{
template:'<div>这是一个组件的内容</div>'
});
var Child = {
template:'<div>这是一个局部注册组件的内容</div>'
};
var app = new Vue({
el:'#app',
data:{
selected:''
},
components:{
'my-components': Child
}
});
</script>
- Vue模板在某种情况下会受到HTML的限制,比如<table>中只能出现<tbody>这些元素,如果直接使用是无效的,这种情况可以使用特殊的属性is来挂载组件;
<div id="app">
<table>
<tbody is="my-component"></tbody>
</table>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<script>
Vue.component('my-component',{
template:'<div>这是一个组件的内容</div>'
});
var Child = {
template:'<div>这是一个局部注册组件的内容</div>'
};
var app = new Vue({
el:'#app',
data:{
selected:''
},
components:{
'my-components': Child
}
});
</script>
- 在组件中除了使用template外也可以使用data,computer,methods等使用data时有区别;
<div id="app">
<table>
<tbody is="my-component"></tbody>
</table>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<script>
Vue.component('my-component',{
template:'<div>{{ message }}</div>',
data: function () {
return{
message:'组件内容'
}
}
});
var Child = {
template:'<div>这是一个局部注册组件的内容</div>'
};
var app = new Vue({
el:'#app',
data:{
selected:''
},
components:{
'my-components': Child
}
});
</script>
- 如果使用data时return出的对象是外部对象,那这个对象就是共享的,修改任何一方都会同步;
<div id="app">
<my-component></my-component>
<my-component></my-component>
<my-component></my-component>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<script>
var data = {
counter:0
}
Vue.component('my-component',{
template:'<button @click="counter++">{{counter}}</button>',
data: function () {
return data;
}
});
var app = new Vue({
el:'#app'
});
</script>
- 我们需要让它独立,而不是同时变动,就需要组件返回一个新的对象
<div id="app">
<my-component></my-component>
<my-component></my-component>
<my-component></my-component>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<script>
Vue.component('my-component',{
template:'<button @click="counter++">{{counter}}</button>',
data: function () {
return {
counter:0
}
}
});
var app = new Vue({
el:'#app'
});
</script>
- 这样点击三个按钮就不会互相影响了
使用props传递数据####
- 概念:组件不仅可以复用,更重要的是组件跟组件之间还可以进行通信,通常父组件的模板中含子组件,父组件正向的向子组件传递数据或参数,子组件接收到后根据参数的不同来渲染不同的内容和执行操作。这个正向传递数据的过程就是通过props[prɑps]来实现的;
- 在组件中,使用props来声明需要从父级接收的数据,props的值可以是两种,一种是字符串组,一种是对象;
<my-component message="来自父组件的数据"></my-component>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<script>
Vue.component('my-component',{
template:'<div>{{ message }}</div>',
props:['message']
});
var app = new Vue({
el:'#app'
});
</script>
由于html特性不区分大小写,当使用DOM模块时,驼峰命名的props名称要转为短横分隔命名:
<div id="app">
<my-component warning-text="来自父组件的数据"></my-component>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<script>
Vue.component('my-component',{
template:'<div>{{ warningText }}</div>',
props:['warningText']
});
var app = new Vue({
el:'#app'
});
</script>
有的时候数据并不是写死的,而是来自父级的动态数据,这时可以使用命令V-bind来动态绑定props的值,当父组件的数据变化时,也会传递给子组件:
<div id="app">
<input type="text" v-model="parentMessage">
<my-component :message="parentMessage"></my-component>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<script>
Vue.component('my-component',{
template:'<div>{{ message }}</div>',
props:['message']
});
var app = new Vue({
el:'#app',
data:{
parentMessage:''
}
});
</script>
如果你要传递数字、布尔值、数组、对象,而且不使用v-bind,传递的是字符串:
<div id="app">
<my-component message="[1,2,3]"></my-component>
<my-component :message="[1,2,3]"></my-component>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<script>
Vue.component('my-component',{
template:'<div>{{ message.length }}</div>',
props:['message']
});
var app = new Vue({
el:'#app',
data:{
parentMessage:''
}
});
</script>
- 单向数据流
VUE2.0通过prop传递数据是单向的,只能父组件传递给子组件,反过来却不行;
组件通信
- 自定义事件
父组件直接在子组件的自定义标签上使用v-on来监听子组件触发的自定义事件,子组件用$emit()来触发事件,注意子组件的监听函数名要小写
<div id="app">
<p>总数:{{ total }}</p>
<my-component v-on:increase = "handlegettotal"
v-on:reduce = "handlegettotal">
</my-component>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<script>
Vue.component('my-component',{
template:'\
<div>\
<button @click = "handleIncrease">+1</button>\
<button @click = "handleReduce">-1</button>\
</div>',
data:function () {
return {
counter:0
}
},
methods:{
handleIncrease:function () {
this.counter++;
this.$emit('increase', this.counter);
console.log(this.counter);
},
handleReduce:function () {
this.counter--;
this.$emit('reduce', this.counter);
console.log(this.counter);
}
}
});
var app = new Vue({
el:'#app',
data:{
total:0
},
methods:{
handlegettotal:function (total) {
console.log(total);
this.total = total;
}
}
});
</script>
slot内容分发
单个slot用法: 也就是说子组件内使用特殊的slot元素,这个子组件就会开启一个slot,如果一个子组件内插入了内容,那么就会替代slot;
<div id="app">
<component-child>
<p>分发的内容</p>
<p>更多的分发的内容</p>
</component-child>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<script>
var bus = new Vue();
Vue.component('component-child',{
template:'\
<div>\
<slot>\
<p>如果父组件没有插入内容,我将默认出现</p>\
</slot>\
</div>\
'
});
var app = new Vue({
el:'#app',
data:{
showChild: true
}
});
</script>
给slot指定name后可以分发更多的内容,具有slot可以与单个slot共存;
<div id="app">
<component-child>
<h2 slot="header">标题</h2>
<p>分发的内容</p>
<p>更多的分发的内容</p>
<div slot="footer">底部信息</div>
</component-child>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<script>
var bus = new Vue();
Vue.component('component-child',{
template:'\
<div class="container">\
<div class="header">\
<slot name="header"></slot>\
</div>\
<div>\
<slot>其实我是出现不了的</slot>\
</div>\
<div class="footer">\
<slot name="footer"></slot>\
</div>\
</div>\
'
});
var app = new Vue({
el:'#app',
data:{
showChild: true
}
});
</script>
组件的高级用法
递归组件
组件在模板内自己调用自己,只要给组件设置name就可以了,**注意的是要给组件设置递归限制条件;内联模板
也就是说在使用组件时,给组件标签使用inline-template特性,组件就会把它的内容当做模板;动态组件
用特殊的元素component用来动态挂载不同的组件,使用is特性来选择需要挂载的组件;nextTickVue观察数据变化时并不是直接跟新DOM,而是开启一个队列,并缓冲在同一事件循环中发生的所有数据变化,而 nextTick就是用来知道什么时候DOM更新完成的;
X-template
X-template是定义模板的另一种方式,可以在script标签中书写HTML代码
<script type='text/x-template' id='my-component'>
<div>这是一个模板内容</div> //模板内容
</script>
end
实例
Vue中html中如果有标点符号的错误,Vue是检测不出来的