Vue组件
大约 2 分钟
Vue组件
vue父子组件的生命周期顺序
加载渲染过程
父beforeCreate -> 父created-> 父beforeMount-> 子beforeCreate -> 子created -> 子beforeMount -> 子mounted -> 父mounted
父组件会先执行到beforeMount,接着会执行子组件钩子到挂载结束,再挂载父组件。
子组件更新过程
父beforeUpdate -> 子beforeUpdate -> 子updated -> 父updated
父组件更新过程
父beforeUpdate -> 父updated
销毁过程
父beforeDestroy -> 子beforeDestroy -> 子destroyed -> 父destroyed
解析 DOM 模板时的注意事项
<div id="root">
<table>
<tbody>
<row></row>
<row></row>
<row></row>
</tbody>
</table>
</div>
<script type="text/javascript">
Vue.component('row', {
template: '<tr><td>this is a row</td></tr>'
})
var vm = new Vue({
el: '#root'
})
</script>
上面代码中,row
组件在渲染页面时,并不会把tr
节点渲染到tbody
里面,而是被提升到了和table
同一个级别的地方。原因是在html编码规范中,tbody
里面只能放tr
,正确的做法是使用tr
标签添加is
属性等于组件名称row
:
<tbody>
<tr is="row"></tr>
<tr is="row"></tr>
<tr is="row"></tr>
</tbody>
同样,ul>li
、ol>li
、select > option
标签也要注意这样的问题。
需要注意的是如果我们从以下来源使用模板的话,这条限制是不存在的:
- 字符串 (例如:
template: '...'
) - 单文件组件 (
.vue
) <script type="text/x-template">
子组件内的data要使用函数返回
Vue.component('row', {
data() {
return {
content: 'this is content'
}
},
template: '<tr><td>{{content}}</td></tr>'
})
之所以这样设计是因为子组件有可能会被调用多次,而每次调用时的data数据都应该是独立的。因此需要通过一个函数来实现,每个实例可以维护一份被返回对象的独立的拷贝。
这样才不会出现每个子组件数据相互影响的情况。
通过 ref 引用操作DOM
虽然并不推荐我们在使用vue的时候操作DOM,但是某些情况下我们必须要操作DOM来实现一些功能,因此可以通过ref引用的形式来获取到DOM节点。
<!-- `vm.$refs.p` 指向DOM元素节点 -->
<p ref="p">hello</p>
<!-- `vm.$refs.child` 指向组件实例 -->
<child-component ref="child"></child-component>
ref
被用来给元素或子组件注册引用信息。引用信息将会注册在父组件的 $refs
对象上。如果在普通的 DOM 元素上使用,引用指向的就是 DOM 元素;如果用在子组件上,引用就指向组件实例。