Skip to content

如果直接在方法中进行更改变量,数据是没有响应式的,也就是说,数据是改了但是不会渲染到主屏幕

ref 实现

javascript
// 导入 
import {ref} from "vue";

export default {
  setup() {
    // 定义的变量使用 ref 进行报错
    let name = ref('123')

    // 在使用或者更改的时候使用以下方式
    name.value = '456'
    
    return {name}
  }
}

在模板语法中可以直接使用,不需要 .value

当 data 是对象的时候,可以采让 ref 包裹住对象的方式

javascript
import {ref} from "vue";
export default {
  setup() {
    // 使用 ref 包裹住对象
    let user = ref({
      name: '张三',
      age: 18
      hobby: ["足球", "篮球", "羽毛球"]
    })
	// 当调用方法是进行响应式更改
    function getName() {
      // 使用以下方式进行更改
      user.value.name = '李四'
      user.value.age = 19
      user.value.hobby[0] = "乒乓球"
    }

    return {user, getName}
  }
}

ref 适合基本数据类型

reactive 实现

reactive 是一个函数,这个实现不能用于基本数据类型,这个函数是专门用于对象类型的

javascript
import {reactive} from "vue";

export default {
  setup() {
    // 使用 reactive 包裹
    let user = reactive({
      name: '张三',
      age: 18,
      hobby: ["足球", "篮球", "羽毛球"]
    })

    function getName() {
      // 在修改的时候不需要使用 value 就可以直接修改
      user.name = '李四'
      user.age = 19
      user.hobby[0] = "乒乓球"
    }

    return {user, getName}
  }
}

使用以上的方式也可以对盒子套盒子的对象进行改变,并且对于 中途添加一个属性、中途删除一个属性(使用 delete 对象.属性)、通过数组下标直接访问 也是可以响应式的

浅层次的响应式(shallow)

shallowReactive:对象第一层支持响应式,第二层就不再支持了

shallowRef:只给基本数据类型添加响应式,如果是对象,则不会给它添加响应式

深只读与浅只读

组合式API:readonly 和 shallowReadonly

场景:如果从其他组件传递过来的数据不希望修改,那么最好加上一个只读

深只读:具有响应式的对象中所有的属性,包括子对象中的子对象中的属性,它的所有值都是只读的不可修改的

使用方法只需要对要被只读的数据用 readonly 进行包裹

浅只读:具有响应式的对象第一层的值是只读的

响应式数据的判断

isRef:检查是否为ref对象

isReactive:检查是否是由 reactive() 或者 shallowReadonly() 创建的代理

isProxy:检查一个值是否是由 reactive()readonly()shallowReactive()shallowReadonly() 创建的代理

isReadonly :检查传入的值是否为只读对象

使用:从 vue 中导入相对应的内容然后直接使用即可

toRef 与 toRefs

在使用插值语法的的时候输入某些值时前面需要写很长的属性(xxx.xxx.xxx.age),如果要省略这些 xxx 那么可以在 return 返回的时候使用键值对的方式返回

javascript
let user = reactive({
  name: "IKun",
  age: 3,
  hobby: {
    h1: "唱",
    h2: "跳",
    h3: "rap",
    h4: "打篮球"
  }
})

return {
  h1: user.hobby.h1,
  h2: user.hobby.h2,
  h3: user.hobby.h3,
}

toRef

按照以上的方式就可以直接使用 h1 进行访问内容了,但是这种方法没有响应式,也就是说,更改 h1 的值 user 中的值不会更改。也可以直接使用 ref 再次进行包裹(h1: ref(user.hobby.h1))这种方式倒是有响应式,但是相当于新建的一个响应式对象,更改的也是这个新的,不会对老的 user 进行更改

在这种情况下就可以使用 toRef 进行包裹住,这样返回的数据不仅仅是老数据的而且也具有响应式

javascript
return {
  h1: toRef(user.hobby, "h1"),
  h2: toRef(user.hobby, "h2"),
  h3: toRef(user.hobby, "h3"),
  h4: toRef(user.hobby, "h4"),
}

toRef 的使用的两个参数,第一个参数是对象,第二个参数是对象中的属性名

toRefs

上面的方式有点过于繁琐,所以又有一个叫 toRefs 的内容

javascript
return {
  ...toRefs(user.hobby)
}

在 toRefs 中填入 user 的话,那么会给 user 的所有内容做代理。使用时,需要从当前层次进行使用,如上所示,在上面的写法中只给 user 内的 hobby 做了代理,使用时只能使用 hobby 内的数据,使用时直接使用属性名即可,如果单纯给 user 做代理,那么想要访问 h1 就得写成 hobby.h1 的形式

由于 toRefs 返回的是对象,所以采用 es6 语法(...xxx)进行添加返回

以上方式对 ref 和 reactive 都有相同的效果

(转换 | 标记)为原始

(转换 | 标记)为原始意思就是把响应式数据(转换 | 标记)成普通对象或者数据

转换(toRaw):将响应式对象转换为普通对象。只适用于reactive 生成的响应式对象

标记(markRaw):标记某个对象,让这个对象永远都不具备响应式

使用:直接对对象进行包裹并接收即可