使用场景:在 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 也不是响应式的,因此你不应该试图用它在模板中做数据绑定。

无锡肖奈
186 声望7 粉丝

十八线野生程序猿 前端开发