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

梦想缔造狮

区域 位置 操作 const ref1 = ref(); const ref2 = ref(); const ref3 = ref(); const refApi = { ref: 'ref3' }; console.log(ref1, ref2, ref3); 在开发环境下 `ref1, ref2, ref3` 皆符合预期指向 `span` 。 但是打包后的生产环境就只有 `ref1` 正常指向 `span` , `ref2, ref3` 皆为 `undefined`。 为什么表现不一致?

阅读量:25

点赞量:0

问AI
因为":="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)