ThinkChat2.0新版上线,更智能更精彩,支持会话、画图、阅读、搜索等,送10W Token,即刻开启你的AI之旅 广告
>[success] # ref 1. 接受一个内部值并返回一个响应式且可变的 `ref `对象,`ref()` 返回的是**value reference (包装对象)** 并且这个对象`value`属性指**向包装的值让其具备了响应** * 数据操作的是使用是`xxx.value` * 在模板中引入`ref`的值时,Vue会自动帮助我们进行**解包操作**,所以我们并不需要在模板中通过 `ref.value` 的方式来使用 3. 一般定义基本类型的响应事数据使用`ref `常见的基本类型,如果你绑定的是对象他将会调用`reactive `,此时`.value`返回的是一个`proxy`对象, 4. 为什么具有`value `因为`proxy `不能将基本类型进行劫持和代理,因此将其转换为对象,进行劫持代理,如果包裹是对象类型做了一层`reactive`包裹 >[danger] ##### 案例 ~~~html <template> <div > <button @click="print">触发事件</button> {{str}} <input v-model="str" /> </div> </template> <script> import {ref} from 'vue' export default { name: 'testlison', setup(prop, ctx) { const str = ref('z') const num = ref(1) const boolean = ref(false) const ull = ref(null) const un = ref(undefined) const print = ()=>{ str.value = "q" num.value = 100 boolean.value = true ull.value = {name:'zz'} un.value = 1000 } return { str,print} }, } </script> ~~~ >[danger] ##### 解构 [案例](https://sfc.vuejs.org/#eNp9U21rE0EQ/ivDfmkCyR1VQQ2Xov9jv1wum/Zq7oW9vUQ4DvyQFsRqhJYarRbaChVE4xvFaOuv6Z3xk3/B2d3kkrMiB3uzs888M8/sbELuhqHRixlpEEswL+zagq1RH8Bquz1lgNWKhQh8uON0XedekxJnw/bXGSVr+d4kG44sUwMQTYUKgySxDd/2WJpaZsGjKfGsZThB7AujZ3fjEmRuWeZSKbiNHO6GQkFcLwy4gAQ469Q4sx3h9hik0OGBBysoZEWi2H2FarOOHXcRrfNHTMRhpTrfAjiBHwmwoSnZKpDIkhuU9Pt9SlKolmEthCVoY+XQUAGrVUilZvl1Yh9LwS7p5lSqRRIA04TsYhcjINvZmp5M8tE4G0+mH4/yZ2fZg+fZ1ln2/nDmGY2nx2/nujT89/nO5ddHv14dT09P8sOB63eCMreKx0gsSsdVykoKIXMpCajWNyQV9q4J9gIhferu0E3J6rXrNyhZnJYS5+9eowJdVfb0yc8XA90dqW/3cfZtLzsfolMJV+qkkovt6el2dvAj/3SUv3yYH3zJ9z+UWT+/yQdDTVB06vL7vhR4VYjOKDW0lg/1eMVdreLmrdv/EpEW1vzPcUK4vxgQALu2sFtLtr7mwoFzsESkV+XDxTKL+SU1oge47tmhsRkFPr47lY3ODiJKGvP8lOA8yz0lG0KEUcM0o44jX+tmZAR83UTL4CjV9ZjBIq/e4kE/YhyJKZmVpjhMdPYYr3Pmtxln/H+cf0Gv8M5EpST9A7P1k04=),如果将一个对象赋值给 ref,那么这个对象将通过[reactive()](https://cn.vuejs.org/api/reactivity-core.html#reactive)转为具有深层次响应式的对象 ~~~html <template> <div> <button @click="change">改变</button> <div> {{a.name}}</div> <div> {{b.count.value}}</div> </div> </template> <script> import { ref,reactive } from 'vue' export default { setup() { const a = ref( {name:"www"} ) const b = { count : ref(1) } function change(){ // 当ref 包裹是对象时候其实对象是被reactive包裹,下面解构info // 其实是 reactive({name:"www"}),视图会更新 const { value:info } = a info.name = "1234" // 此时解构后的count 是响应式的ref 对象,但视图没有更新 // 注意响应是对象他是 const { count } = b count.vaule = "789" } return { a, b, change, } } } </script> ~~~ * 官方一个例子,`ref `被传递给函数或是从一般对象上被解构时,不会丢失响应性,解构后他 依旧是一个`ref `的响应式的对象,需要通过`value `赋值 ~~~ const obj = { foo: ref(1), bar: ref(2) } // 该函数接收一个 ref // 需要通过 .value 取值 // 但它会保持响应性 callSomeFunction(obj.foo) // 仍然是响应式的 const { foo, bar } = obj ~~~ >[danger] ##### 是所有情况下ref 在模板渲染时候都不用.value么 1. 只有当`ref`包裹的对象是直接从`setup`返回的可以省略`value`,但是如果是嵌套的**依然需要你在模板中使用value属性** ![](https://img.kancloud.cn/49/e3/49e3e47dedb0159acaf3733e29d4fde2_581x523.png) [案例](https://sfc.vuejs.org/#eNqNU01v00AQ/SvLXpqosc05ciM4cuHA2RfXmYBLbK9216Yo8oEDiEMLBxKpqEUQoopIUCoEhyQS6p/xR34G6107cROCuHh3Zp7fe7OzO8D3CdGjEHAbmxw80rc5dCwfIbPrRnIjtnc0DWXTcfbhZvllkp68TGan+XAa2f0QkKZVKEZsvzMYICcIfY7i2DRkpqwehpwHPrrn9F3n6YGFFWp/38KdB75DwQMRyqRpKGxdPT3/lMwW6h8KvfR6vvwxXn7+mixOsm9jYWk5macXUx8Yh24yuxL4/OJFPrpUJtN3p+limA3n6duz7Oxa+v+YjV7X3BcqWyYVn17z+lBm0C7LG4TZ1SQff09fvc9+jtalHSdSF9OV7/+R3MFGaHD8/FHdOgXb4W4ESA2xRiDnbaiBm0btGoiQOdQlXKq4HgkoR4NiAq0VW4x6NPDQnrhEewUKjiWqCz077Au08seAh6TRrEIkmvBZ2Qo6KBgbd5tVrVoNA+Xnv7I3l8nvG3Hh1NRvE6hDEwwr4qIiSKsw/gupolt1oK7PbV51fNKZQjV2CjRX1GuJakdF29TfMtdax6qBWkIpb9iXi/iIN1XNA7ewGojm2UQ/YoEv3rAUssoCs3C7krawmE8RW/gJ54S1DYP1nOLlHzE9oI8NsdOpsOZ6oAPztEMaPGNABbGFS3eSwxDJCKhGwe8CBfovzg3oFm/ZVIzjP94Ko3Y=) ~~~html <template> <div> <!-- 模板解包不用value --> <span>{{ count }}</span> <button @click="count ++">Increment count</button> <!-- 因为count ref对象被二次包裹在nested中因省略value 响应改变是不生效 --> <!-- <button @click="nested.count ++">Nested Increment count</button> --> <!-- 正确写法 --> <button @click="nested.count.value ++">Nested Increment count</button> <button @click="proxyR.count ++">reactive 解包</button> </div> </template> <script> import { ref,reactive } from 'vue' export default { setup() { const count = ref(0) // 直接使用对象 const nested = { count } // 使用reactive 包裹 const proxyR = reactive({ count }) // return { count, nested, proxyR } } } </script> ~~~ >[danger] ##### 注意点作为对象参数 1. **当一个包装对象被作为另一个响应式对象的(属性)引用的时候也会被自动展开** 但是当从数组或本地集合类型(如Map)访问ref时,不会执行展开操作 ~~~ const books = reactive([ref('Vue 3 Guide')]) // need .value here 这里依旧需要value console.log(books[0].value) const map = reactive(new Map([['count', ref(0)]])) // need .value here 这里依旧需要value console.log(map.get('count').value) // 反复包裹 let obj = ref({ name: 'w' }) console.log(obj.value.name) console.log(reactive(obj).value.name) ~~~ >[danger] ##### 解包的api ~~~ 1.reactive 和 readonly 具有相同解包特性 ~~~ >[info] ## 官网 [## ref()](https://cn.vuejs.org/api/reactivity-core.html#ref) [## 用`ref()`定义响应式变量](https://cn.vuejs.org/guide/essentials/reactivity-fundamentals.html#reactive-variables-with-ref)