Vue ref 属性在不同环境下的行为差异?-灵析社区

米小米会努力

因为`:="data"`简写语法的意思是将`data`中的每一个属性都当做`prop`传入,比如`data`是这么一个对象`{name: ref1, age: ref2}`等同于 `:name="ref1" :age="ref2"`,注意`script`中的`ref`和`template`中的`ref`不是同一个概念,模板中是实例引用,编译的时候会将实例绑定到对应的`data`上,然后因为你是用的`:=`对象绑定,而你绑定的对象里并没有`ref`(注意这里的`ref`指的是模版上那个`ref`),所以2、3实际是没有任何数据绑定的,而`ref1`因为你是固定的属性绑定,不是动态的,能对应上,也就能绑上了。 这时候你可能会疑惑,`:={ref: 'ref2'}`以及`refApi = {ref: 'ref3'}`这不是符合我上述说的吗? 因为你这里`ref`虽然对应是模版的`ref`但是你绑定的是字符串,不是某一个`ref变量`这就好比是`ref="'ref2'"`【注意有两引号】 知道了以上的内容那么就可以改代码了:`const ref3 = ref(); const refApi = {ref: ref3}`;这么改`ref3`就有值了 但如果你将模版中的`:={ref: ref2}`你会发现还是没值,为什么呢? `vue`的`const r = ref()`返回的其实是一个对象,当我们在`script`中要访问真正的值的时候是要`r.value`的方式访问的,但是为了方便,在模版里其实我们不需要`.value`,`vue`实际会帮我们去做这件事,所以`:={ref: ref2}`实际上相当于`ref="ref2.value"`,绑定原始值肯定是不行的,所以我们这里需要用到函数的方式来绑定即`:={ref: el => ref2 = el}` 完整修改如下: 区域 位置 ref2 = el }">操作 const ref1 = ref(); const ref2 = ref(); const ref3 = ref(); const refApi = { ref: ref3 }; console.log(ref1, ref2, ref3); 然后我建议你去[VuePlayground](https://link.segmentfault.com/?enc=%2Fqav5NtEfM5l43lErPTxLw%3D%3D.v7a65B%2BMuvjICWMR0EmjGoDBFkS8fD4j9j0GOlD50OdUz9rjhxlBGkNK%2BxeMuMJXpyk0hm99CeKa6vS%2BxnjnWAZlJBI%2B9zB0cQilkWPh5iI%2F1TUjOrbF7E8REZs8xTdaqGlUverNFg3oNa%2F7gzXTqvVEQB6rceEQlihXEZSttlZYZhufKUDprzRJUVY36ZSQZ2kurfVV%2FtL5pzCSPYjAHc7vkcomq3tJ1AXiMbsW6Jjz4YX%2BrOzpHWotfGB2DkJsQGWUoxwwcaVLMqP1bJ%2Bbfa0%2FBDoqVsAL1Gzoy3jvtrFlch7E1TZcCMY1M3So3DzFlNlItixY3fn8qCQbnhtCh%2F5kTZZziQutYf6svAfzp7S2BFSFmqb3cmexfu2tKHu2%2FwfcyjA%2BS8SM4GdEMwIZ%2FY2K5H2yBvEbMRIOGVY3%2F37cMOcJOBDHWwOOAy4m45CJo8fNfKfWV%2Bs8ObanSVngCyjEYjU00BwNeCgiBx6nQJG%2Bghy3HtYLJEqERXqVFkOhInMvcrdNS%2B05cf6zrxgvGxrxWhm8wZpSDh7EiEvCkn%2Bh9%2FD69OjYmRssilyRsU0cxpy91WvuQx20JC6zrY6qCrirb5lI1eMU49ZpIm6dEgA4jByR0IgXPM6SGrMYaCBG8aphfQ9jO%2Bb%2FQg%2Fgj9AGKkSe%2Fhk3zP9gXyfhVenZFy4%3D)看看编译后的代码,有助于你理解我上面所说的 ![截屏2023-12-20 23.22.39.png](https://wmlx-new-image.oss-cn-shanghai.aliyuncs.com/images/20241027/8b112c83cf331652d1659540deff8a2a.png) [https://cn.vuejs.org/guide/essentials/template-syntax.html#at...](https://link.segmentfault.com/?enc=QToOZl4eGoEGA%2F1srYCF3w%3D%3D.ap9%2FRGhmiQWOdf0xVs9bRbHPzymjOsKbk3DggY6NApi0QJ03qxZHGZVvt%2BqHQAxXbfyIrwaxjrrIgDT5WJWHzsTaozRgdPqo9ITnRujwXi8%3D) [https://cn.vuejs.org/guide/essentials/template-refs.html#func...](https://link.segmentfault.com/?enc=IkzdAKDTMJ0khrNu3KcSEg%3D%3D.JMBRJfXV88oy6rWRxK%2Fcg5DmLflqtFLIsw3%2FjOjBKZ0Dd8tZrt0qMVx4YTPcRn5cnmWZJ5UjPgTXuPHwWrEGeORdZaAy%2FX9dN7FHCor7px8%3D) * * * 由于昨晚太晚了,只回答了为什么生产不行的原因,今天补充说明下为什么开发环境是可以的: 首先,`vue`的`script`支持`setup`属性从而简写一些代码,所以就会存在两种编译结果: **这是没有`setup`的`script`:** ![截屏2023-12-21 20.30.28.png](https://wmlx-new-image.oss-cn-shanghai.aliyuncs.com/images/20241027/bedf87edff7f8b9cc93812f07aadec15.png) **这是有`setup`的`script`:** ![截屏2023-12-21 20.31.53.png](https://wmlx-new-image.oss-cn-shanghai.aliyuncs.com/images/20241027/311d154aed500bddfaa79af659316305.png) 关键原因就出在这两种不同结果上,实际上除了昨天我说的那种改法,还有一种改法是改成没有`setup`的`script`形式,也就是上面的图1那样,然后你就会发现,不管开发环境还是生产环境(即`build`之后)都有值了。有没有察觉到什么?没错,在`dev`模式下,`vite`编译的结果就是没有`setup`的结果!! ![截屏2023-12-21 19.27.41.png](https://wmlx-new-image.oss-cn-shanghai.aliyuncs.com/images/20241027/f11a70664ee556ce408d85873de2132b.png) 实际上你的确可以将`ref`定义成字符串,我们知道在`vue`实例上其实有这么个属性——`refs`,它其实就是所有模版中`ref`的集合,在`vue2`时代我们都是`this.$refs.ref1`这么访问的,在`vue3`中虽然不太需要了,但是实例上依然还是有这么个属性,其实你定义的字符串代表的就是这个`refs`的`key` ![截屏2023-12-21 20.57.02.png](https://wmlx-new-image.oss-cn-shanghai.aliyuncs.com/images/20241027/2fdda375c324d199919a4dbda69a8ce1.png) 当你绑定的是一个`ref对象`的时候则会多一步,将这个节点赋值给`ref`,上图中`ref1`也存在于`refs`中;当`ref`是字符串的时候,除了绑定`refs`,`vue`还会检查`data`【vue2叫法,vue3中就是`setup() { return data }`里`return`出来的对象】中是否有同名的`key`,有的话也会给该属性绑定: ![截屏2023-12-21 21.20.01.png](https://wmlx-new-image.oss-cn-shanghai.aliyuncs.com/images/20241027/c9da3f238901eeb2098f95998185f9d3.png) 这也就解释了为什么改成无`setup`的`script`版本就可以了。有的同学可能会疑惑那为什么``的版本不行呢?不也是定义了同样的变量名`const ref2 ref3`吗?这是因为它们只是变量,`build`后是通过闭包访问的,并不是`vue`实例上的`state` ![截屏2023-12-21 21.14.45.png](https://wmlx-new-image.oss-cn-shanghai.aliyuncs.com/images/20241027/98bfbf5acafa1039e7e7091f570052d0.png)

阅读量:1

点赞量:0

问AI