Vue中的插槽与keep-alive

插槽

初次真正接触插槽是在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方法,而是调用activateddeactivated` 这两个生命周期钩子函数将会被对应执行。将其缓存起来。

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
//router.js

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组件管控,导致不正常

Powered by Hexo and Hexo-theme-hiker

Copyright © 2019 - 2024 My Wonderland All Rights Reserved.

UV : | PV :