无论是通过 Vue.component
的方式,还是在写 .vue
文件的方式,官方都会推荐你写一个 name
属性。但是好像这个 name 在渲染时又几乎用不到,那么它实际能干嘛呢?
方便调试
Vue 有一款官方强力推荐的浏览器上的调试插件: vue-devtools。通过打开调试工具,我们可以很轻松的看到已经渲染到页面上的各个组件,以及对应的组件的内部状态。
例如以下组件:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| <script> export default { name: 'Kawaii', props: ['val'], render (h) { return ( <div> { this.val } </div> ) } } </script>
|
如果在 App.vue 里引用的话:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| <template> <Demo val="foo" /> </template>
<script> import Demo from './components/Demo'
export default { name: 'app', components: { Demo } } </script>
|
那么可以在 chrome 的调试界面可以看到:
其中 Kawaii
就是刚才起了名字的组件,如果将其改名为 看不见看不见
1 2 3 4 5 6 7
| <script> export default { name: '看不见看不见', } </script>
|
那么在 chrome 界面则可以直接看到其显示名字就变为 看不见看不见
了。
但如果不设置名字,那么 Vue.js 默认会用 tag 名称,也就是这个组件在 template
或者 jsx
里的名字。比如:
1 2 3 4 5 6 7 8
| <script> export default { } </script>
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| <template> <D val="foo" /> </template>
<script> import Demo from './components/Demo'
export default { name: 'app', components: { 'D': Demo } } </script>
|
那么此时就会显示为 D
:
Note: functional 组件不会显示在 devtools 中,因为 vue 并不会为 functional component 创建实例
递归应用
在有些时候,我们可以会递归使用自身组件,比如:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| <template> <div> {{ val }} <Recursive v-if="val" :val="val - 1" /> </div> </template>
<script> export default { name: 'Recursive', props: { val: { required: true, type: Number, default: 5 } } } </script>
|
在这种情况下,如果不设置 name,那么 console 就会报错,提示在 Recursive.vue 中找不到名为 Recursive
的组件。因此,如果想要递归应用自身组件的话,就必须设置 name 属性。
keep-alive
keep-alive 是 Vue 内置的组件,可以将 keep-alive 的子组件运行缓存,用于保存切换 (例如 v-if 的切换) 过程前的状态。
而 keep-alive 有两个 props 是 include
以及 exclude
。前者指明需要缓存的组件的名字。而后者则指明不需要缓存的组件的名字。
下述例子中,Foo, Bar 两个组件的名字分别为 vue-foo
, vue-bar
, 且组件均包含一个 input。因为通过 input 可以很轻松的观察到切换前后的状态是否有保存:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| <template> <div> {{ val }} <input type="text" v-model="m" /> </div> </template>
<script>
export default { name: 'vue-foo', data () { return { val: 'vue-foo', m: 'vue-foo' } } } </script>
|
Bar.vue 跟 Foo.vue 内容几乎一样,除了名字,因此这里就不贴 Bar.vue 的代码了。
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
| <template> <div> <keep-alive include="vue-foo"> <Foo v-if="visible" /> <Bar v-else /> </keep-alive> <Button @click="visible = !visible"> Visible {{ visible }} </Button> </div>
</template>
<script> import Foo from './components/Foo' import Bar from './components/Bar'
export default { name: 'app', data () { return { visible: true } }, components: { Foo, Bar } } </script>
|
通过点击 button 来切换。因为设置了 include
指令,那么只有 Foo
的状态才会被保存:
通过这张效果图可以看到,在切换过程中,Foo
的状态被保存了,而 Bar
则没有,而是重新生成。
如果使用 exclude
指令:
1 2 3 4 5 6 7 8 9 10 11 12
| <template> <div> <keep-alive exclude="vue-foo"> <Foo v-if="visible" /> <Bar v-else /> </keep-alive> <Button @click="visible = !visible"> Visible {{ visible }} </Button> </div>
</template>
|
那么就会得到一个完全相反的结果: 即 Bar
的状态被保存了,而 Foo
则没有,而是重新生成。
References
- api/#keep-alive
- api/#name
- vue-devtools/issues/280