vue中组件name的作用
起因
export default{
name:'xxxxxxx'
}
自己在写Vue项目的时候,到写name的时候就会很纠结到底写还是不写,有时怕错索性就写上。
那么这个name有什么用?怎么有时写,有时又不写?
官方文档对name的介绍
name的三种用途
项目中有用到keep-alive时
- name可以用作include和exclude的值
新建组件:
在Table.vue组件中定义了组件名name为Table,dom加载完之后执行mounted进行数据更新,这里获取table数据。
//Table.vue
export default {
name:'Table'
},
activated(){
//第二种解决方案
this.getData();
},
methods:{
getData(){
axios.get('/xx/table.json',{
params:{
id:this.$route.query.id
}
}).then(()=>{
.......
})
}
}
//App.vue
<div id="app">
<keep-alive exclude="Table">
<router-view/>
</keep-alive>
</div>
在App.vue中使用keep-alive组件会缓存不活动的组件实例,而不是销毁它们。这样会导致我们滴二次进入页面时不会刷新页面,有两种方式可以解决这样的问题:
- 在keep-alive中加入exclude属性,exclude="Table"这样就不会对Table组件进行缓存,第二次进入该页面时就会得到最新数据。
- 当组件在
<keep-alive>内被切换,它的activated和deactivated这两个生命周期钩子函数将会被对应执行。activated:被 keep-alive 缓存的组件激活时调用。deactivated被 keep-alive 缓存的组件停用时调用。这里把this.getData();放到activated中
keep-alive 扩展
- 执行顺序
页面第一次进入时,钩子的触发顺序是created -> mounted -> activated,退出时触发 deactivated.再次进入时只触发activated。所有,我们把只要执行一次的放在 created 或者 mounted 里,切换到组件需要每次获取最新数据的放在activated中。
<keep-alive>源码
地址:vuejs/vue/edit/dev/src/core/components/keep-alive.js
文章解析:juejin.cn/post/686220…
/* @flow */
import { isRegExp, remove } from 'shared/util'
import { getFirstComponentChild } from 'core/vdom/helpers/index'
type VNodeCache = { [key: string]: ?VNode };
function getComponentName (opts: ?VNodeComponentOptions): ?string {
return opts && (opts.Ctor.options.name || opts.tag)
}
function matches (pattern: string | RegExp | Array<string>, name: string): boolean {
if (Array.isArray(pattern)) {
return pattern.indexOf(name) > -1
} else if (typeof pattern === 'string') {
return pattern.split(',').indexOf(name) > -1
} else if (isRegExp(pattern)) {
return pattern.test(name)
}
/* istanbul ignore next */
return false
}
function pruneCache (keepAliveInstance: any, filter: Function) {
const { cache, keys, _vnode } = keepAliveInstance
for (const key in cache) {
const cachedNode: ?VNode = cache[key]
if (cachedNode) {
const name: ?string = getComponentName(cachedNode.componentOptions)
if (name && !filter(name)) {
pruneCacheEntry(cache, key, keys, _vnode)
}
}
}
}
function pruneCacheEntry (
cache: VNodeCache,
key: string,
keys: Array<string>,
current?: VNode
) {
const cached = cache[key]
if (cached && (!current || cached.tag !== current.tag)) {
cached.componentInstance.$destroy()
}
cache[key] = null
remove(keys, key)
}
const patternTypes: Array<Function> = [String, RegExp, Array]
export default {
name: 'keep-alive',
abstract: true,
props: {
include: patternTypes,
exclude: patternTypes,
max: [String, Number]
},
created () {
this.cache = Object.create(null)
this.keys = []
},
destroyed () {
for (const key in this.cache) {
pruneCacheEntry(this.cache, key, this.keys)
}
},
mounted () {
this.$watch('include', val => {
pruneCache(this, name => matches(val, name))
})
this.$watch('exclude', val => {
pruneCache(this, name => !matches(val, name))
})
},
render () {
const slot = this.$slots.default
const vnode: VNode = getFirstComponentChild(slot)
const componentOptions: ?VNodeComponentOptions = vnode && vnode.componentOptions
if (componentOptions) {
// check pattern
const name: ?string = getComponentName(componentOptions)
const { include, exclude } = this
if (
// not included
(include && (!name || !matches(include, name))) ||
// excluded
(exclude && name && matches(exclude, name))
) {
return vnode
}
const { cache, keys } = this
const key: ?string = vnode.key == null
// same constructor may get registered as different local components
// so cid alone is not enough (#3269)
? componentOptions.Ctor.cid + (componentOptions.tag ? `::${componentOptions.tag}` : '')
: vnode.key
if (cache[key]) {
vnode.componentInstance = cache[key].componentInstance
// make current key freshest
remove(keys, key)
keys.push(key)
} else {
cache[key] = vnode
keys.push(key)
// prune oldest entry
if (this.max && keys.length > parseInt(this.max)) {
pruneCacheEntry(cache, keys[0], keys, this._vnode)
}
}
vnode.data.keepAlive = true
}
return vnode || (slot && slot[0])
}
}
递归组件
递归组件,顾名思义,就是自己的内部实现又调用自己的组件。
其实,除了name选项是必须的之外,还有一点也是在实现递归组件要注意的,就是要防止无限递归,造成调用栈溢出,在不满足条件时跳出递归。
父组件:
<template>
<div>
<tree :model="treeData"></tree>
</div>
</template>
<script>
import tree from '@/components/tree'
export default {
data () {
return {
treeData: {
title: '1',
children: [
{title: '1-1'},
{
title: '1-2',
children: [
{title: '1-2-1'},
{title: '1-2-2'},
{title: '1-2-3'},
]
},
{
title: '1-3',
children: [
{
title: '1-3-1',
children: [
{
title: '1-3-1-1'
},
{
title: '1-3-1-2'
}
]
},
{title: '1-3-2'},
{title: '1-3-3'},
]
},
]
}
}
},
created(){
},
methods:{
},
}
</script>
<style scoped lang="scss"></style>
子组件:
<template>
<div>
<div v-for="(item, index) in model" :key="index">
{{ item.title }}
<div
v-if="item.children && item.children.length"
style="margin-left:20px;"
>
<tree :model="item.children"></tree>
</div>
</div>
</div>
</template>
<script>
export default {
// 这里要写name:tree才可以递归
name: "tree",
props: {
model: Array
},
data() {
return {};
}
};
</script>
<style scoped lang="scss"></style>
效果:
vue-tools 调试时
vue组件中的name决定了vue-tools的显示。