插槽
初次真正接触插槽是在Elementui中的表格中在自定义列的内容时
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| <el-table-column label="姓名" width="180"> <template slot-scope="scope"> <el-popover trigger="hover" placement="top"> <p>姓名: {{ scope.row.name }}</p> <p>住址: {{ scope.row.address }}</p> <div slot="reference" class="name-wrapper"> <el-tag size="medium">{{ scope.row.name }}</el-tag> </div> </el-popover> </template> </el-table-column>
|
在列中插入一个template用来放置我们自定义的内容,并且可以通过slot-scope="scope"
中的scope来获取这一列的row信息。
仔细看了官方文档才明白,插槽slot
是用来接收父组件在调用子组件时,在子组件标签内添加添加的内容,这个内容可以时文字,标签,或是其他组件。并且可以在slot上通过v-bind绑定值传递到父组件(说起来也算是子组件向父组件传值哦~)。可以预见,在el-table-column
组件中,肯定存在一个slot来接受父组件的template:
1 2 3
| <el-table-column> <slot v-bind:rowRata="rowData"></slot> </el-table-column>
|
值得注意的是:scope-slot
,slot
这两个语法在2.6.0之后都被官方废除,但是并未移除。在3.0中会被移除,取而代之的是新的v-slot
指令。具体用法如下:
插槽的作用域
值得重视的是,插槽总是在父组件中渲染的,引用官方的一句话:
父级模板里的所有内容都是在父级作用域中编译的;子模板里的所有内容都是在子作用域中编译的。
这句话中的“在”字,即我们能看到的。即使是插槽这样传递到子组件中元素。
所以,插槽总是能访问父组件的数据,而不能访问子组件的数组。但是有时我们又必须访问子组件的数据怎么办呢?这就用到了v-slot(slot-scope)属性。
作用域插槽
对于默认插槽(即default),可以通过开始的代码形式,来获取子组件的值,前提是在子组件中使用 v-bind将其绑定到slot上。
1 2 3 4 5 6
| //父组件 <child> <template v-slot="defaultPorps"> {{defaultPorps.user.name}} </template> <child>
|
1 2 3
| //子组件 <slot v-bind:user = {"name":"tom"}> </slot>
|
还有一点值得注意的是,Vue将整个slot的所有bind值封装为一个对象,所以我们使用v-bind绑定的值仅仅是该对象的一个属性(但是我们可以通过ES6的解构方法来直接拿到属性值)
具名插槽
这个就很简单的了,一个子组件可能具有多个插槽,我们可以必须为止加上名字来区分,(如果不加,比如上面的例子中,v-slot = “xxx”全称应该是 v-slot:default=”xxx”,默认名字就是default),使用方法如下:
1 2 3 4 5 6
| //父组件中 <child> <template v-slot="slot1">对应插槽1</template> <template v-slot="slot1">对应插槽2</template> <template v-slot="slot1">对应插槽3</template> </child>
|
1 2 3 4 5 6
| //子组件中 <template> <slot name="slot1"></slot> <slot name="slot1"></slot> <slot name="slot1"></slot> </template>
|
另外v-slot也可以缩写为#,就像v-on缩写为@,v-bind缩写为:
keep-alive
这个属性之前没有尝试过,但是最近遇到有个组件想要在来回切换时保持状态,既保持用户观看的内容,开始是想手动记录用户的状态,后来发现Vue官方提供了这个抽象组件,正好解决了问题,
keep-alive
基本用法是缓存某些组件的状态,我们从Vue的生命周期函数中可以发现,在组件失活时,都会触发beforeDestroy
生命周期函数,但是如果我们将其包裹在keep-alive
标签下,那么这些组件在失活时,并不会调用beforeDestroy
方法,而是调用activated和
deactivated` 这两个生命周期钩子函数将会被对应执行。将其缓存起来。
keep-alive组件有3个porp.
include
- 字符串或正则表达式。只有名称匹配的组件会被缓存。
exclude
- 字符串或正则表达式。任何名称匹配的组件都不会被缓存。
max
- 数字。最多可以缓存多少组件实例。
基本用法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| //缓存所有的组件 <keep-alive> <component1></component1> <component2></component1> <component3></component1> </keep-alive>
//缓存特定组件 <keep-alive inlude="component1"> <component1></component1> <component2></component1> <component3></component1> </keep-alive>
//不缓存特定组件 <keep-alive exclude="component2"> <component1></component1> <component2></component1> <component3></component1> </keep-alive>
//规定最多缓存2个组件 <keep-alive max="2"> <component1></component1> <component2></component1> <component3></component1> </keep-alive>
|
当然,也可以配合Vue-router。来进行使用:
配合路由
在使用Vue-router进行组件选择性渲染的时候,我们同样也可以使用keep-alive
,因为<router-view></router-view>
组件是一个抽象路由,并不会真正创建一个组件结构在整个文档结构中,所以keep-alive
对其仍然有效。代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
|
import Vue from 'vue' import Router from 'vue-router' import Home from './views/Home.vue' import Login from './views/Login.vue' import Register from "./views/regisetr.vue"
Vue.use(Router)
export default new Router({ routes: [ { path: '/', name: 'home', component: Home }, { path: '/about', name: 'about', componet: About }, { path: '/login', name: 'login', component: Login }, { path: '/register', name: 'register', component: Register } ] })
|
1 2 3 4 5 6 7 8 9 10
| <transition :duration="500" mode="out-in" enter-active-class="animated bounceIn" leave-active-class="animated bounceOutDown" > <keep-alive exclude="Login,Register" max=2> <router-view></router-view> </keep-alive> </transition>
|
上面的代码即表示,不缓存Login
,Register
组件,并且最多缓存2和组件。
值得注意的是,当同时使用transiton
组件与keep-alive
组件时,transiton
组件必须位于外层,很容易想明白,keep-alive
组件对其内部的组件进行管控,如果将transiton
组件放置到其内部,即使它是抽象组件,也会被被keep-alive
组件管控,导致不正常