Vue的其他重要知识点汇总学习
插槽slot
插槽
<div id="root">
<child> <!-- 组件标签 -->
<h1>hello</h1>
</child>
</div>
<script type="text/javascript">
Vue.component('child', { // 子组件
template: '<div><slot></slot></div>'
})
var vm = new Vue({
el: '#root'
})
</script>
上面代码中,组件标签内的h1
是要插入子组件内部的元素,子组件内使用slot
标签接收父组件插入的h1
标签。
默认值
Vue.component('child', {
template: '<div><slot>默认值</slot></div>'
})
子组件slot
标签内可以添加默认值,它只会在父组件没有传入内容的时候被渲染。
具名插槽
::: warning
自 2.6.0 起有所更新。使用 slot
attribute 的语法已废弃。
:::
<div id="root">
<child>
<div slot="header">header</div> <!--旧语法 使用template标签或其他标签都可以-->
<div slot="footer">footer</div>
</child>
</div>
<script type="text/javascript">
Vue.component('child', {
template: `<div>
<slot name="header"></slot>
<div>content</div>
<slot name="footer"></slot>
</div>`
})
var vm = new Vue({
el: '#root'
})
</script>
上面代码中,组件标签内有两个元素,分别添加了slot
属性赋予不同的值,子组件内分别有两个slot
插槽,添加了对应的name
属性,用于分别接收父组件传入的内容。
::: tip
自 2.6.0 起,使用v-slot
指令代替slot
attribute 的语法。
:::
<div id="root">
<child>
<template v-slot:header> <!--新语法 只能使用template标签-->
<h1>标题</h1>
</template>
<p>内容</p>
<template v-slot:footer>
<p>页脚</p>
</template>
</child>
</div>
<script type="text/javascript">
Vue.component('child', {
template: `<div>
<header>
<slot name="header"></slot>
</header>
<main>
<slot></slot>
</main>
<footer>
<slot name="footer"></slot>
</footer>
</div>`
})
var vm = new Vue({
el: '#root'
})
</script>
自2.6.0版本起,具名插槽由原来的slot
标签属性改为v-slot
指令,例v-slot:header
。子组件内仍然是在slot
插槽标签添加name
属性用于分别接收内容。未具名的插槽接收未使用v-slot
指定的内容。
另外,具名插槽同样可以使用默认值。
注意 v-slot
只能添加在 <template
上 (只有一种例外情况),这一点和已经废弃的 slot
attribute不同。
作用域插槽
::: warning
自 2.6.0 起有所更新。使用 slot-scope
attribute 的语法已废弃。
:::
<div id="root">
<child>
<template slot-scope="dataObj"> <!--可使用其他标签,但注意其他标签将会被带到插槽里面-->
<li>{{dataObj.dataItem}}</li>
</template>
</child>
</div>
<script type="text/javascript">
Vue.component('child', {
data(){
return {
list: [1, 2, 3, 4]
}
},
template: `<div>
<ul>
<slot
v-for="item of list"
:dataItem=item
>
</slot>
</ul>
</div>`
})
var vm = new Vue({
el: '#root'
})
</script>
上面代码中,组件标签内需要使用template
标签并且设置slot-scope
属性 用于接收子组件内传递的值,template
标签内的li
标签是传入插槽的元素,dataObj.dataItem
数据由子组件内提供。子组件内通过v-for
循环插入父组件提供的li
标签,并且通过:dataItem=item
把每个item
数据传递出去。
子组件提供数据,父组件中接收数据,可以对数据处理并插入到元素,然后把元素放入子组件插槽。
作用:
数据由子组件提供,但渲染什么元素由父组件决定,并且可以对数据做二次处理。
:::tip
自 2.6.0 起。使用v-slot
代替 slot-scope
attribute 的语法。
:::
为了让 user
在父级的插槽内容中可用,我们可以将 user
作为 <slot>
元素的一个 attribute 绑定上去:
<span>
<slot v-bind:user="user">
{{ user.lastName }}
</slot>
</span>
绑定在 <slot>
元素上的 attribute 被称为插槽 prop。现在在父级作用域中,我们可以使用带值的 v-slot
来定义我们提供的插槽 prop 的名字:
<current-user>
<template v-slot:default="slotProps">
{{ slotProps.user.firstName }}
</template>
</current-user>
在这个例子中,我们选择将包含所有插槽 prop 的对象命名为 slotProps
,但你也可以使用任意你喜欢的名字。
<div id="root">
<child>
<template v-slot:default="dataObj"> <!--default是默认具名,可省略。但有多个插槽时不能省略。-->
<li>{{dataObj.dataItem}}</li>
</template>
</child>
</div>
<script type="text/javascript">
Vue.component('child', {
data(){
return {
list: [1, 2, 3, 4]
}
},
template: `<div>
<ul>
<slot
v-for="item of list"
:dataItem=item
>
</slot>
</ul>
</div>`
})
var vm = new Vue({
el: '#root'
})
</script>
具名插槽的缩写
跟 v-on
和 v-bind
一样,v-slot
也有缩写,即把参数之前的所有内容 (v-slot:
) 替换为字符 #
。例如 v-slot:header
可以被重写为 #header
:
<base-layout>
<template #header>
<h1>Here might be a page title</h1>
</template>
<p>A paragraph for the main content.</p>
<p>And another one.</p>
<template #footer>
<p>Here's some contact info</p>
</template>
</base-layout>
然而,和其它指令一样,该缩写只在其有参数的时候才可用。这意味着以下语法是无效的:
<!-- 这样会触发一个警告 -->
<current-user #="{ user }">
{{ user.firstName }}
</current-user>
如果你希望使用缩写的话,你必须始终以明确插槽名取而代之:
<current-user #default="{ user }">
{{ user.firstName }}
</current-user>
Demo
<p class="codepen" data-height="400" data-theme-id="light" data-default-tab="js,result" data-user="xugaoyi" data-slug-hash="XWbdpBp" style="height: 400px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;" data-pen-title="插槽slot">
<span>See the Pen <a href="https://codepen.io/xugaoyi/pen/XWbdpBp">
插槽slot</a> by xugaoyi (<a href="https://codepen.io/xugaoyi">@xugaoyi</a>)
on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>
动态组件与 v-once 指令
动态组件
<div id="root">
<component :is="type"></component> <!--其效果如同下面两行被注释的代码-->
<!-- <child-one v-if="type === 'child-one'"></child-one>
<child-two v-if="type === 'child-two'"></child-two> -->
<button @click="handleClick">change</button>
</div>
<script type="text/javascript">
Vue.component('child-one', {
template: '<div>child-one</div>'
})
Vue.component('child-two', {
template: '<div>child-two</div>'
})
var vm = new Vue({
el: '#root',
data: {
type: 'child-one'
},
methods: {
handleClick() {
this.type = this.type === 'child-one' ? 'child-two' : 'child-one'
}
}
})
</script>
上面代码中,点击按钮在两个组件间切换,可使用<component>
标签并绑定:is
为动态组件名。
动态组件 demo
See the Pen 动态组件 by xugaoyi (@xugaoyi) on CodePen.
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>v-once 指令
-
不需要表达式
-
详细:
只渲染元素和组件一次。随后的重新渲染,元素/组件及其所有的子节点将被视为静态内容并跳过。这可以用于优化更新性能。
<!-- 单个元素 --> <span v-once>This will never change: {{msg}}</span> <!-- 有子元素 --> <div v-once> <h1>comment</h1> <p>{{msg}}</p> </div> <!-- 组件 --> <my-component v-once :comment="msg"></my-component> <!-- `v-for` 指令--> <ul> <li v-for="i in list" v-once>{{i}}</li> </ul>
-
参考:
通过 v-once
创建低开销的静态组件
渲染普通的 HTML 元素在 Vue 中是非常快速的,但有的时候你可能有一个组件,这个组件包含了大量静态内容。在这种情况下,你可以在根元素上添加 v-once
attribute 以确保这些内容只计算一次然后缓存起来,就像这样:
Vue.component('terms-of-service', {
template: `
<div v-once>
<h1>Terms of Service</h1>
... a lot of static content ...
</div>
`
})
danger
再说一次,试着不要过度使用这个模式。当你需要渲染大量静态内容时,极少数的情况下它会给你带来便利,除非你非常留意渲染变慢了,不然它完全是没有必要的——再加上它在后期会带来很多困惑。例如,设想另一个开发者并不熟悉 v-once
或漏看了它在模板中,他们可能会花很多个小时去找出模板为什么无法正确更新。
vue父子组件的生命周期顺序
加载渲染过程
父beforeCreate -> 父created-> 父beforeMount-> 子beforeCreate -> 子created -> 子beforeMount -> 子mounted -> 父mounted
父组件会先执行到beforeMount,接着会执行子组件钩子到挂载结束,再挂载父组件。
子组件更新过程
父beforeUpdate -> 子beforeUpdate -> 子updated -> 父updated
父组件更新过程
父beforeUpdate -> 父updated
销毁过程
父beforeDestroy -> 子beforeDestroy -> 子destroyed -> 父destroyed
- 点赞
- 收藏
- 关注作者
评论(0)