>[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)
- 官网给的工具
- 声明vue2 和 vue3
- 指令速览
- Mustache -- 语法
- v-once -- 只渲染一次
- v-text -- 插入文本
- v-html -- 渲染html
- v-pre -- 显示原始的Mustache标签
- v-cloak -- 遮盖
- v-memo(新)-- 缓存指定值
- v-if/v-show -- 条件渲染
- v-for -- 循环
- v-bind -- 知识
- v-bind -- 修饰符
- v-on -- 点击事件
- v-model -- 双向绑定
- 其他基础知识速览
- 快速使用
- 常识知识点
- key -- 作用 (后续要更新)
- computed -- 计算属性
- watch -- 侦听
- 防抖和节流
- vue3 -- 生命周期
- vue-cli 和 vite 项目搭建方法
- vite -- 导入动态图片
- 组件
- 单文件组件 -- SFC
- 组件通信 -- porp
- 组件通信 -- $emit
- 组件通信 -- Provide / Inject
- 组件通信 -- 全局事件总线mitt库
- 插槽 -- slot
- 整体使用案例
- 动态组件 -- is
- keep-alive
- 分包 -- 异步组价
- mixin -- 混入
- v-model-- 组件
- 使用计算属性
- v-model -- 自定义修饰符
- Suspense -- 实验属性
- Teleport -- 指定挂载
- 组件实例 -- $ 属性
- Option API VS Composition API
- Setup -- 组合API 入口
- api -- reactive
- api -- ref
- 使用ref 和 reactive 场景
- api -- toRefs 和 toRef
- api -- readonly
- 判断性 -- API
- 功能性 -- API
- api -- computed
- api -- $ref 使用
- api -- 生命周期
- Provide 和 Inject
- watch
- watchEffect
- watch vs. watchEffect
- 简单使用composition Api
- 响应性语法糖
- css -- 功能
- 修改css -- :deep() 和 var
- Vue3.2 -- 语法
- ts -- vscode 配置
- attrs/emit/props/expose/slots -- 使用
- props -- defineProps
- props -- defineProps Ts
- emit -- defineEmits
- emit -- defineEmits Ts
- $ref -- defineExpose
- slots/attrs -- useSlots() 和 useAttrs()
- 自定义指令
- Vue -- 插件
- Vue2.x 和 Vue3.x 不同点
- $children -- 移除
- v-for 和 ref
- attribute 强制行为
- 按键修饰符
- v-if 和 v-for 优先级
- 组件使用 v-model -- 非兼容
- 组件
- h -- 函数
- jsx -- 编写
- Vue -- Router
- 了解路由和vue搭配
- vueRouter -- 简单实现
- 安装即使用
- 路由懒加载
- router-view
- router-link
- 路由匹配规则
- 404 页面配置
- 路由嵌套
- 路由组件传参
- 路由重定向和别名
- 路由跳转方法
- 命名路由
- 命名视图
- Composition API
- 路由守卫
- 路由元信息
- 路由其他方法 -- 添加/删除/获取
- 服务器配置映射
- 其他
- Vuex -- 状态管理
- Option Api -- VUEX
- composition API -- VUEX
- module -- VUEX
- 刷新后vuex 数据同步
- 小技巧
- Pinia -- 状态管理
- 开始使用
- pinia -- state
- pinia -- getter
- pinia -- action
- pinia -- 插件 ??
- Vue 源码解读
- 开发感悟
- 练手项目