今天突然想去了解一下 ref 概念,歪打正着的想明白了之前遇到的问题,使用element-ui中的 tree 组件,在初始化回显勾选为什么不成功的问题。
不知道有没有人和我一样,在vue初始化渲染需要进行一些操作时,特别喜欢在 created 中去操作,这就造成了一些可以避免的错误和不必要的代码。初始化中操作dom,我们首先要了解在 created这个阶段和在mounted阶段进行初始化有什么区别:
created,这个阶段模板已经创建完成,可以请求data和method,但是dom树没有渲染成,因此无法进行dom操作;
mounted,这个阶段模板已经渲染完成,可以进行一些dom操作,所以通常需要进行一些dom操作时,就在这个阶段进行请求。
在了解这个区别之后,我们需要ref是什么?
ref是被用来给元素或子组件注册引用信息的。如果是普通的DOM元素上,引用的信息指向就是DOM元素;如果是子元素,引用信息将会注册在父组件的$refs的对象上,引用就指向组件实例。(下面代码是普通DOM元素)
<template>
<div>
//记录一下我碰到过的特殊写法的ref
<el-table
:ref="'multipleTable' + id"
:data="data"
@select="allCheck()"
>
</el-table>
//一般情况的写法
<div ref="boxDom" @click="getDom"></div>
</div>
</template>
data () {
return {
id: 1 ,
data: [
{
id: 1,
value: '张三'
}
]
}
},
methods: {
allCheck() {
console.log(this.$refs[`multipleTable${id}`][0])
},
getDom(){
//一般的
console.log(this.$refs.boxDom)
}
}
前面两个概念都知道了之后,我们还需要再了解一个$nextTick的作用。
简单点来理解就是修改数据后想立刻获取这个dom的数据,如果是调用$nextTick回调函数的话,获取到的数据会是更新后的数据;如果不是,那获取到的就会是旧数据。mounted中发送请求就是放在nexttick中。
在这一系列的了解下就知道我犯了什么错,我在created阶段就想操作dom树,所以勾选就一直不成功,加了一个$nextTick回调函数后,才成功。这种方法虽然可行,但如果在初始化就需要操作Dom,还是放在mounted中更好,更保险。如果又遇到类似操作dom不出来的情况,不妨看看是不是放错地方了,或者把操作dom的代码放入nextTick函数中。下面是将dom操作放入created的代码:
<el-tree
ref="rightsTree"
:data="option"
:props="{
label: 'name',
value: 'id',
children: 'child',
}"
show-checkbox
node-key="id"
:default-expanded-keys="defaultCheckedKeys"
:default-checked-keys="defaultCheckedKeys"
@check="currentChecked"
/>
async created() {
// 需要对DOM树进行操作
this.getCheckedMenu()
},
methods: {
getCheckedMenu() {
// 将需要对DOM树进行的操作放到$nextTick回调中
this.$nextTick(function() {
// this.defaultCheckedKeys是需要勾选的节点数组,例如this.defaultCheckedKeys=[1,3,5]
this.$refs.rightsTree.setCheckedKeys(this.defaultCheckedKeys)
console.log(this.$refs.rightsTree)
})
}
}