ref 被用来给元素或子组件注册引用信息。引用信息将会注册在父组件的 $refs 对象上。如果在普通的 DOM 元素上使用,引用指向的就是 DOM 元素;如果用在子组件上,引用就指向组件实例:
<!-- vm.$refs.p will be the DOM node -->
<p ref="p">hello</p>
<!-- vm.$refs.child will be the child comp instance -->
<child-comp ref="child"></child-comp>
当 v-for 用于元素或组件的时候,引用信息将是包含 DOM 节点或组件实例的数组。
关于 ref 注册时间的重要说明:因为 ref 本身是作为渲染结果被创建的,在初始渲染的时候你不能访问它们 - 它们还不存在!$refs 也不是响应式的,因此你不应该试图用它在模板中做数据绑定。
参考官网:网页链接
ref 目前使用过的三种方式:
1、在html的元素中使用rel,可在js中直接调用该元素,用this.$refs.(ref值) 获取到的是dom元素
2、在vue的组件上加rel,可在js中直接使用该组件包括该组件的方法,用this.$refs.(ref值).方法名()
3、在v-for的循环列中使用rel
避坑:
v-for中使用rel需要绑定 变量 ,即v-bind:rel='变量名'
ref 需要在dom渲染完成后才会有 ,在使用的时候确保dom已经渲染完成。比如在生命周期 mounted(){} 钩子中调用 ,或者 在 this.$nextTick(()=>{}) 中调用 。
如果rel循环未绑定变量,那就$refs获取获取数组再循环得到使用即可
例子1:在html元素上使用
<div id="app">
<h1 ref="h1ele">这是h1</h1>
<hello ref="ho"></hello>
<button @click="getref">获取h1元素</button>
</div>
获取注册过 ref 的所有组件或元素
methods: {
getref() {
// 表示从 $refs对象 中, 获取 ref 属性值为: h1ele DOM元素
console.log(this.$refs.h1ele.innerText)
this.$refs.h1ele.style.color = 'red'// 修改html样式
console.log(this.$refs.ho.msg)// 获取组件数据
console.log(this.$refs.ho.test)// 获取组件的方法
}
}
例子2:
<html部分
<view class="example-body">
<button class="button" type="primary" @click="togglePopup('top', 'popup')">顶部弹出 popup</button>
<button class="button" type="primary" @click="togglePopup('center', 'popup')">中间弹出 popup</button>
<button class="button" type="primary" @click="togglePopup('bottom', 'popup')">底部弹出 popup</button>
</view>
<uni-popup ref="showpopup" :type="type" @change="change"><text class="popup-content">{{ content }}</text></uni-popup>
<uni-popup ref="showtip" :type="type" :mask-click="false" @change="change">
<view class="uni-tip">
<text class="uni-tip-title">警告</text>
<text class="uni-tip-content">这是一个通过自定义 popup,自由扩展的 警告弹窗。点击遮罩不会关闭弹窗。</text>
<view class="uni-tip-group-button">
<text class="uni-tip-button" @click="cancel('tip')">取消</text>
<text class="uni-tip-button" @click="cancel('tip')">确定</text>
</view>
</view>
</uni-popup>
<js部分
methods: {
togglePopup(type, open) {
switch (type) {
case 'top':
this.content = '顶部弹出 popup'
break
case 'bottom':
this.content = '底部弹出 popup'
break
case 'center':
this.content = '居中弹出 popup'
break
}
this.type = type
this.$nextTick(() =>{
this.$refs['show' + open].open()
})
},
cancel(type) {
this.$refs['show' + type].close()
},
change(e) {
console.log('是否打开:' + e.show)
}
},
一般来讲获取DOM元素,需document.querySelector(".class")获取这个dom节点,然后在获取元素的值。
但是用ref绑定之后,我们就不需要在获取dom节点了,直接在上面的元素上绑定rel,然后$refs里面调用就行。
然后在javascript里面这样调用:this.$refs.元素绑定rel 这样就可以减少获取dom节点的消耗了
一、定义数据角度:
ref定义:基本数据类型
reactive定义:对象(或数组)数据类型
备注:ref也可以用来定义对象和数组,它内部通过reactive转为代理对象
示例:
let p2 = ref({
name: '李四',
age: 18
})
console.log('p2',p2)
let p1 = reactive({
name: '张三',
age: 20
})
console.log('p1',p1)
从打印的结果可以看出来通过ref定义的数组实际生成了一个引用实例对象,在js中如果需要调用对象的属性值通过.value.name调用,而通过reactive定义的对象直接.name调用即可
二、原理角度
ref通过Object.defineProperty()的get()和set()实现响应式(数据的劫持)
reactive通过Proxy实现响应式,并通过Reflect操作源对象内部的数据
三、使用角度
ref:操作数据需要通过.value,在模版中读取不需要通过.value
reactive : 操作与读取数据均不需要通过.value