Vue3.0 reactive与ref :VCA模式

简介

Vue3 最大的一个变动应该就是推出了 CompositionAPI,可以说它受ReactHook 启发而来;它我们编写逻辑更灵活,便于提取公共逻辑,代码的复用率得到了提高,也不用再使用 mixin 担心命名冲突的问题。

ref 与 reactive 是 Vue3 新推出的主要 API 之一,它们主要用于响应式数据的创建。

reactive 能做的,ref 都能胜任,并且 ref 底层还是使用 reactive 来做的!!!

ref 函数可以接收原始数据类型引用数据类型

reactive 函数只能接收引用数据类型

当你明确知道需要包裹的是一个对象,那么推荐使用 reactive,其他情况使用 ref 即可

reactive包装函数

<template>
  <div>
    <!-- 案列1 -->
    <button @click="myClick">点我</button>
    <div>{{ obj.name }}--{{ obj.age }}</div>
    <div>{{ obj2.email }}</div>
    <!-- <div>{{ obj3 }}</div> -->
    <hr>

    <!-- 列表案列 -->
    <ul>
      <li v-for="item in obj.datalist" :key="item">{{ item }}</li>
    </ul>

    <!-- 模糊查询案列 -->
    <input type="text" v-model="obj.mytitle">
    <ul>
      <li v-for="item in GetSelectItems()" :key="item">{{ item }}</li>
    </ul>

  </div>
</template>
<script>
import { reactive } from 'vue';
export default {
  setup() {

    //用reactive是一个包装函数,包装后就得到了一个响应式对象obj (setup中可以存在多个reactive,只是正常情况下一个就够用了,比如下面的obj 和obj2)

    //注意const是申明常量的,常量不是不可变的吗?为什么还可以通过obj.name = "李四"来改变它呢? 
    //其实obj只是reactive({name: "张三",age: 29})这个对象的一个引用(指针),obj不能再进行修改,只是说obj不能再指向其他的对象了,例如:obj="aaa"就会报错,因为obj所指向对象的引用已经变化了。
    //但是obj指向的这个对象它本身的属性是可以修改的,所以 obj.name = "李四"不会报错
    const obj = reactive({
      name: "张三",
      age: 29,
      datalist: ["aaa", "bbb", "ccc"],
      mytitle: ""
    })

    const obj2 = reactive({ email: "abc@qq.com" })

    //const obj3=reactive("张三"); //reactive不支持这种简单类型的包装,它只支持复杂类型的包装,如对象,数组等。
    //const obj3=reactive("");     //reactive不支持这种简单类型的包装
    //const obj3=reactive(1);      //reactive不支持这种简单类型的包装

    const myClick = () => {
      obj.name = "李四"
    }

    const GetSelectItems = () => {
      //includes() 方法用于判断字符串是否包含指定的子字符串
      //filter方法是过滤方法, item表示当前遍历datalist数组的项,如果当前项包含了input中输入的值,则找出来,然后统一返回一个数组
      var selectIitemArr = obj.datalist.filter(item => item.includes(obj.mytitle))
      return selectIitemArr;
    }

    //所有的函数与对象都需要在return中进行返回
    //obj,myClick是定义在setup中的,它只能在setup中使用,为了在setup外面使用(例如DOM中)我们就必须要把他们暴露出去,就需要放到return中进行返回
    return {
      obj, //等同于obj:obj
      obj2,
      obj3,
      myClick, //返回myClick
      GetSelectItems,
    }
  }
}

</script>

ref包装函数

<template>
  <div>
    <!-- 案列1 -->
    <button @click="myClick">点我</button>
    <div>{{ obj.name }}--{{ obj.age }}</div>
    <div>{{ obj2.email }}</div>
    <div>{{ obj3 }}</div>
    <div>{{ obj4 }}</div>
    <div>{{ obj5 }}</div>
    <div>{{ obj6?"中国":"美国" }}</div>
    <hr>

    <!-- 列表案列 -->
    <ul>
      <li v-for="item in obj.datalist" :key="item">{{ item }}</li>
    </ul>

    <!-- 模糊查询案列 -->
    <input type="text" v-model="obj.mytitle">
    <ul>
      <li v-for="item in GetSelectItems()" :key="item">{{ item }}</li>
    </ul>

  </div>
</template>
<script>
import { reactive, ref } from 'vue';
export default {
  setup() {

    //用reactive是一个包装函数,包装后就得到了一个响应式对象obj (setup中可以存在多个reactive,只是正常情况下一个就够用了,比如下面的obj 和obj2)

    //注意const是申明常量的,常量不是不可变的吗?为什么还可以通过obj.name = "李四"来改变它呢? 
    //其实obj只是ref({name: "张三",age: 29})这个对象的一个引用(指针),obj不能再进行修改,只是说obj不能再指向其他的对象了,例如:obj="aaa"就会报错,因为obj所指向对象的引用已经变化了。
    //但是obj指向的这个对象它本身的属性是可以修改的,所以 obj.value.name = "李四"不会报错
    const obj = ref({
      name: "张三",
      age: 29,
      datalist: ["aaa", "bbb", "ccc"],
      mytitle: ""
    })

    const obj2 = ref({ email: "abc@qq.com" })

    const obj3=ref("王五"); //ref支持这种简单类型的包装  原理就是new Proxy({value:"王五"}) 注意:在DOM模板中使用{{obj3}}  在<script>中使用需要在后面加.value 如:obj3.value
    const obj4=ref("");     //ref支持这种简单类型的包装  原理就是new Proxy({value:""})
    const obj5=ref(1);      //ref支持这种简单类型的包装  原理就是new Proxy({value:1})
    const obj6=ref(true);

    const myClick = () => {
      obj.value.name = "李四"
    }

    const GetSelectItems = () => {

      //特别注意:经过ref包装函数包装的对象,在<script>中必须要在对象名称后面.value ,在DOM模板中则不需要.value
      // 比如:
      // obj.value.name; 获取obj对象中的name值
      // obj.value.age;  获取obj对象中的age值
      // obj.value.datalist; 获取obj对象中的datalist值
      // obj.value.mytitle;  获取obj对象中的mytitle值

      //includes() 方法用于判断字符串是否包含指定的子字符串
      //filter方法是过滤方法, item表示当前遍历datalist数组的项,如果当前项包含了input中输入的值,则找出来,然后统一返回一个数组
      var selectIitemArr = obj.value.datalist.filter(item => item.includes(obj.value.mytitle))
      return selectIitemArr;
    }

    //所有的函数与对象都需要在return中进行返回
    //obj,myClick是定义在setup中的,它只能在setup中使用,为了在setup外面使用(例如DOM中)我们就必须要把他们暴露出去,就需要放到return中进行返回
    return {
      obj, //等同于obj:obj
      obj2,
      obj3,
      obj4,
      obj5,
      obj6,
      myClick, //返回myClick
      GetSelectItems,
    }
  }
}

</script>

reactive与ref共存

<template>
  <div>
    <!-- 案列1 -->
    <button @click="myClick">点我</button>
    <div>{{ obj.name }}--{{ obj.age }}</div>
    <div>{{ obj2.email }}</div><hr>


    <!-- 可以直接用mydata -->
    <ul>
      <li v-for="item in mydata" :key="item">{{ item }}</li>
    </ul>
   
    <!-- 也可以将mydata放到reactive包装函数中然后通过obj对象来用 -->
    <ul>
      <li v-for="item in obj.mydata" :key="item">{{ item }}</li>
    </ul>

    <ul>
      <li v-for="item in mylist.mydata" :key="item">{{ item }}</li>
    </ul>
    <div>{{mylist.obj.name}}</div>

  </div>
</template>
<script>
import { reactive, ref } from 'vue';
export default {
  setup() {

    //有一种情况就是通过import导入的组件(JS)中存在用ref包装的,而我们当前组件组件用的是reactive包装的,为了保持风格统一(当然不统一也行)我们也可以将ref中的包装对象直接放到reactive包装函数中:
    //举列:
    const mydata = ref([1, 2, 3]);//我们可以直接用mydata,也可以将mydata放到reactive包装函数中

    const obj = reactive({
      name: "张三",
      age: 29,
      datalist: ["aaa", "bbb", "ccc"],
      mytitle: "",
      mydata //也可以将ref包装函数包装的对象mydata放到reactive包装函数中
    })

    const mylist=ref({
      mydata, 
      obj //也可以将reactive包装函数包装的对象obj放到ref包装函数中
    })

    const obj2 = reactive({ email: "abc@qq.com" })

    return {
      obj, //等同于obj:obj
      obj2,
      mydata,
      mylist
    }
  }
}
</script>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值