上次学到作用域
首先需要明确slot分发的内容是在父组件上的
所谓内容在父组件和子组件的内容之分,就是看在哪里编译
在子组件上绑定的话写在组件注册内容内部,父组件绑定是写在注册vue实例内容中
slot的用法
slot的意思是插槽,用于内容分发,就是混合父组件的内容和子组件的模板
单个slot
在子组件内使用特殊的<slot>
元素就可以为这个子组件开启一个slot(插槽)
在父组件模板里面插入在子组件标签内的所有内容将代替子组件的<slot>
标签及它的内容
<body>
<div id="app">
<child-component>
<p>分发的内容</p>
<p>更多</p>
</child-component>
</div>
<script>
Vue.component('child-component',{
template:'\
<div>\
<slot>\
<p>如果没有内容,这句话将默认出现</p>\
</slot>\
</div>'
});
var app = new Vue({
el:'#app'
})
</script>
</body>
来看看一个案例,就是一个普通的注册组件,然后使用的过程,之前一般的组件注册内容,在写了template属性后,里面的内容会完全替代使用组件标签时里面的内容,但是这里的template内容添加了slot的属性后,就变得不一样了,他不会直接完全替代原本组件标签中的内容,只会在组件标签原本无内容时替换
子组件child-component的模板内定义了一个slot元素,并且使用一个p作为默认内容,在父组件没有使用slot的
具名slot
给slot元素指定一个name后可以分发多个内容,具名slot可以与单个slotslot共存
额,我理解错了,slot的作用不是为了禁止template里面的内容代替组件标签内容,而是slot相当于一个槽孔,插槽,让组件标签内的内容加入到slot里面,然后再把template的内容替换组件标签内容,而槽孔原来的内容会被替代,除非组件标签原来没内容,芜湖!!!
<body>
<div id="app">
<child-component>
<h2 slot="header">标题</h2>
<p>正文内容</p>
<p>更多正文内容</p>
<div slot="footer">底部消息</div>
</child-component>
</div>
<script>
Vue.component('child-component',{
template:'\
<div class="xx">\
<div class="x">\
<slot name="footer"></slot>\
</div>\
<div>\
<slot></slot>\
</div>\
<div>\
<slot name="header"></slot>\
</div>\
</div>'
}); //main那个是默认slot
var app = new Vue({
el:'#app'
})
</script>
</body>
这里经过渲染后的结果就是:
<div class="xx">
<div class="x">
<div>底部消息</div>
</div>
<div>
<p>正文内容</p>
<p>更多正文内容</p>
</div>
<div>
<h2>标题</h2>
</div>
</div>
作用域插槽
作用域插槽是一种特殊的slot,使用一个可以复用的模板替换已渲染元素
<body>
<div id="app">
<child-component>
<template scope="props">
<p>来自父组件的内容</p>
<p>{{props.msg}}</p>
</template>
</child-component>
</div>
<script>
Vue.component('child-component',{
template:'\
<div class="container">\
<slot msg="来自子组件的内容"></slot>\
</div>'
});
var app = new Vue({
el:'#app'
})
</script>
</body>
分析:
渲染后的结果是:
<div id="app">
<div class="container">
<p>来自父组件的内容</p>
<p>来自子组件的内容</p>
</div>
</div>
在slot元素上有一个类似props传递数据给组件的写法msg=“xxx”,将数据传到了插槽中。父组件使用了template元素,而且拥有一个scope=“props”的特性,这里的props可以是任意变量,并不代表什么绑定。template内通过变量props访问来自子组件插槽的数据msg
作用域插槽更具有代表性的用例是列表组件,允许组件自定义应该如何渲染列表的每一项
<body>
<div id="app">
<my-qian :books="books">
<template slot="book" scope="props">
<li> {{props.bookName}} </li>
</template>
</my-qian>
</div>
<script>
Vue.component('my-qian',{
props:{
books:{
type:Array,
default:function(){
return [];
}
}
},
template:'\
<ul>\
<slot name="book" v-for="book in books" :book-name="book.name">\
</slot>\
</ul>'
});
var app = new Vue({
el:'#app',
data:{
books:[
{ name: 'xxxxx'},
{ name: 'yyyyy'},
{ name: 'zzzzz'}
]
}
})
</script>
</body>
子组件my-qian接受一个来自父级的prop数组books,并且将它在叫做book的插槽中使用v-for循环,并使用点出bookName的值3次,这个for循环是子组件的插槽中进行的
访问slot
未来就是现在!
使用$slot可以访问被slot分发的内容
<body>
<div id="app">
<my-qian>
<h2 slot="header">标题</h2>
<p>正文</p>
<p>more</p>
<div slot="footer">底部信息</div>
</my-qian>
</div>
<script>
Vue.component('my-qian',{
template:'\
<div class="container">\
<div class="header"></slot>\
<slot name="header"></slot>\
</div>\
<div class="main">\
<slot></slot>\
</div>\
<div class="footer">\
<slot name="footer"></slot>\
</div>\
</div>',
mounted:function(){
var header = this.$slots.header;
var main = this.$slots.default;
var footer = this.$slots.footer;
// console.log(footer);
console.log(footer[0].elm.innerHTML);
}
});
var app = new Vue({
el:'#app'
})
</script>
</body>
这里面通过mounted里面的内容访问了几个具名slot还有匿名,匿名的通过this.$slots.defaut来访问,其他的都是this.$slot.+名字来访问,然后如果是具体的名字,需要语句console.log(footer[0].elm.innerHTML);
如果是获取所有信息在控制板上,就是通过console.log(footer);
$nextTick
一个div,默认用v-if隐藏之,点击按钮,改变v-if值使之显现,同时也就获取到了这个div的内容,但是如果值为负的时候,是无法获取的,之前说和v-show的区别的时候也讲过了,这个是不曾渲染的在为假时
<body>
<div id="app">
<div id="div" v-if="showDiv">这是一段问了</div>
<button @click="getText">获取内容</button>
</div>
<script>
var app = new Vue({
el:'#app',
data:{
showDiv:false
},
methods:{
getText:function(){
this.showDiv = true;
var text = document.getElementById('div').innerHTML;
console.log(text);
}
}
})
</script>
</body>
像上面这样直接获取div的内容的话,是会报错的,因为根本没有渲染
vue在观察到数据变化的时候并不是直接更新DOM,而是开启一个队列,并缓冲在同一时间循环中发生的所有数据改变。在缓冲的时候会去除重复数据,从而避免不需要的计算和DOM操作。然后在下一个事件循环tick中,vue刷新队列并执行工作
所以如果是一个for循环来动态改变数据100次,他只会应用最后一次改变
$nextTick可以用来知道DOM是什么时候更新完成的
<body>
<div id="app">
<div id="div" v-if="showDiv">这是一段文本</div>
<button @click="getText">获取内容</button>
</div>
<script>
var app = new Vue({
el:'#app',
data:{
showDiv:false
},
methods:{
getText:function(){
this.showDiv = true;
this.$nextTick(function(){
var text = document.getElementById('div').innerHTML;
console.log(text);
});
}
}
})
</script>
</body>
这样把获取div的语句放进$nextTick里面就可以了,不会继续报错
手动挂载实例
一般来说都是new Vue()来创建实例。如果需要动态地创建一些Vue实例的话,就需要用到Vue.extend和$mount两个方法来手动挂载一个实例
Vue.extend是基础Vue构造器,创建一个“子类”,参数是一个包含组件选项的对象。
如果Vue实例在实例化的时候没有收到el选项,他就处于一个未挂载的状态,没有关联的DOM元素。可以使用$mount()手动地挂载一个未挂载的实例
<body>
<div id="mount-div">
</div>
<script>
var MyComonent = Vue.extend({
template:'<div>Hello:{{name}}</div',
data:function(){
return {
name : 'Ak'
}
}
});
new MyComonent().$mount('#mount-div');
</script>
</body>
具体,明天再分析