Vue.js实战读书笔记(3)
Rehoni / 2019-03-08
slot分发内容
props 传递数据、 events 触发事件和 slot 内 容分发就构成了 Vue 组件的 3 个 API 来源,再复杂的组件也是由这 3 部分构成的。
-
作用域:slot分发的内容作用域是在父组件上的。
-
slot用法:
- 单个slot:父组件中进入子组件child-component,在child-component的模板内定义一个<slot>元素,并且用一个<p>作为默认的内容,在父组件没有使用 slot 时,会渲染这段默认的文本;如果写入了 slot, 那就会替换整个<slot>。 子组件
<slot>
内的备用内容,它的作用域是子组件本身。 - 具名slot:给<slot>元素指定一个 name 后可以分发多个内容,具名 Slot 可以与单个 Slot 共存。其中在<div class=”main与内的<slot> 没有使用 name 特性,它将作为默认 slot 出现,父组件没有使用 slot 特性的元素与内容都将出现在这里。如果没有指定默认的匿名 slot,父组件内多余的内容片段都将被抛弃。
- 作用域插槽:在<slot>元素上有一个类似 props 传递数据给组件的写法 msg=”xxx”,将数据传到了插槽。父组件中使用了<template>元素,而且拥有一个 scope=”props”的特性,这里的 props只是一个临时变量,就像 v-for=”item in items,里面的 item 一样。 template 内可以通过临时变量 props访问来自子组件插槽的数据 msg 。如果下例还在其他组件内使用,<Ii>的内容渲染权是由使用者掌握的,而数据却可以通过临时变量(比如 props )从子组件内获取。
- 通过$slots 可以访问某个具名 slot, this .$slots.default 包括了所有没有被包含在具名 slot 中的节点。$slots 在业务中几乎用不到 , 在用 render 函数(进阶篇中将介绍)创建组件时会比较有用,但主要还是用于独立组件开发中。
<div id="app"> <my-list :books="books"><!--这里用v-bind语法糖,绑定父组件data中的book传入--> <!--作用域插槽也可以是具名slot--> <template slot=”book” scope=”props ”> <li> {{props.bookName}}</li> </template> </my-list> </div> <script> Vue.component('my-list',{ props:{ books:{ type:Array, default:function(){ return []; } } }, template:'\ <ul>\ <slot name="book"\ v-for="book in books"\ <!--这里的:book-name对应props.bookName,是由驼峰命名法转化位kebab-case命名的-->\ :book-name="book.name">\ <!--这里也可以写默认 slot 内容-->\ </slot>\ </ul>' }); var app = new Vue({ el:'#app', data:{ books:[ {name:'book1'}, {name:'book2'}, {name:'book3'} ] } }) </script>
- 单个slot:父组件中进入子组件child-component,在child-component的模板内定义一个<slot>元素,并且用一个<p>作为默认的内容,在父组件没有使用 slot 时,会渲染这段默认的文本;如果写入了 slot, 那就会替换整个<slot>。 子组件
组件高级用法
- 组件递归 组件在它的模板内可以递归地调用自己 , 只要给组件设置 name 的选项就可以了。设置 name 后,在组件模板内就可以递归使用了,不过需要注意的是,必须给一个条件来限制递归数量,否则会抛出错误 : max stack size exceeded 。组件递归使用可以用来开发一些具有未知层级关系的独立组件,比如级联选择器和树形控件等
<!--父组件中-->
<child-component : count= "1" ></child- component>
<!--子组件中-->
<child-component :count="count + 1" v-if="count < 3" ></child- component>
-
内联模板 组件的模板一般都是在 template 选项内定义的, Vue 提供了一个内联模板的功能,在使用组件时,给组件标签使用 inline- mplate 特性,组件就会把它的内容当作模板,而不是把它当内容分发,这让模板更灵活。 在父组件中声明的数据 message 和子组件中声明的数据 msg , 两个都可以渲染(如果同名,优先使用子组件的数据)。这反而是内联模板的缺点,就是作用域比较难理解,如果不是非常特殊的场景 , 建议不要轻易使用内联模板。
-
动态组件
<component :is="currentView"></component>
动态改变currentView的值就可以动态挂载组件了,也可以直接绑定在组件对象上。 -
异步组件 工厂函数接收一个 resolve 回调,在收到从服务器下载的组件定义时调用。也可以调用reject(reason)指示加载失败。这里 setTimeout 只是为了演示异步,具体的下载逻辑可以自己决定,比如把组件配置写成一个对象配置,通过 Ajax 来请求,然后调用 resolve 传入配置选项。
<div id="app">
<child-component></child-component>
</div>
<script>
Vue.component('child-component',
function (resolve, reject) {
window.setTimeout(function () {
resolve({
template: '<div>我是异步渲染的</div>'
});
}, 2000)
});
var app = new Vue({
el: '#app'
})
</script>