使用场景: 在 vue 中, 我们需要直接操作 DOM 的时候, 可以使用 ref 及 $ref 来实现
也就是说我们在原生 js 中获取 dom 元素, 需要使用 document.getElementById("name")
现在可以直接使用this.$refs.name
$refs 相对于 document.getElementById,减少了获取 dom 节点的消耗
项目需求:使用 v-for 循环数个 div 区块, 需要实现使用鼠标滚轮监听对每个区块进行自由缩放
需求分析: 我的思路是, 利用 vue 的 ref 属性, 获取对应 dom 节点的 zoom 属性(这个 zoom 属性是用来展示区块缩放倍数的), 最后根据区块的原宽高来计算缩放后的宽高
初步解决方法:
<div
class="block"
v-for="(item,index) in charts.blockdata"
:key="index"
@mousewheel="rollImg(item.id,index)"
:ref="`list${index}`"
>
这里使用 ES6 的模板字符串, 用占位符的方式来拼接字符串
给每一个 div 添加不同的 ref 属性
如果对模板字符串的使用方法不清楚的, 可以查看文档
http://es6.ruanyifeng.com/#docs/string# 模板字符串
@mousewheel 监听鼠标滚轮时间, 触发 rollImg 方法
rollImg(id, index) {
/* 获取当前页面的缩放比
若未设置 zoom 缩放比,则为默认 100%,即 1,原图大小 */
var zoom = parseInt(this.$refs[`list${index}`][0].style.zoom) || 100;
/* event.wheelDelta 获取滚轮滚动值并将滚动值叠加给缩放比 zoom
wheelDelta 统一为±120,其中正数表示为向上滚动,负数表示向下滚动 */
zoom += event.wheelDelta / 12;
console.log(zoom);
/* 最小范围 和 最大范围 的图片缩放尺度 */
this.$refs[`list${index}`][0].style.zoom = zoom + "%";
this.onResizstop(id, index, 1, parseFloat(zoom / 100));
return false;
}
其中获取 dom 节点的核心代码是这一句this.$refs[
list${index}][0].style.zoom
我们仍然是使用模板字符串的方法来获取 dom 节点, 从而得到 zoom 的更新值
这么看我们已经实现这个需求了, 但我在官方文档中看到这样一句话
当 v-for 用于元素或组件时, 引用信息将是包含 DOM 节点或组件实例的数组
所以我们或许可以用更简单的方法来实现这个功能
直接给每一个 div 组件设置相同名称的 ref, 根据此 ref 获取到的是一个包含 DOM 节点或组件实例的数组列表,然后根据 index 即可定位该元素
<div
class="block"
v-for="(item,index) in charts.blockdata"
:key="index"
@mousewheel="rollImg(item.id,index)"
:ref="blocklist"
>
rollImg(id, index) {
......
this.$refs.blocklist[index].style.zoom = zoom + "%";
......
}
最后需要注意的是:
因为 ref 本身是作为渲染结果被创建的,在初始渲染的时候你不能访问它们 – 它们还不存在!$refs 也不是响应式的,因此你不应该试图用它在模板中做数据绑定。