Vue3 — Composition API(其它部分二)

# toRef

  • 为源响应式对象上的某个属性创建一个 ref对象, 二者内部操作的是同一个数据值, 更新时二者是同步的

  • 区别ref: 拷贝了一份新的数据值单独操作, 更新时相互不影响

  • 应用: 当要将 某个prop 的 ref 传递给复合函数时,toRef 很有用

    <template>
      <h3>state:{{ state }}</h3>
      <h3>age:{{ age }}</h3>
      <h3>money:{{ money }}</h3>
      <hr />
      <button @click="update">更新数据</button>
    </template>
    
    <script lang="ts">
    import { defineComponent, reactive, ref, toRef } from "vue";
    
    export default defineComponent({
      name: "App",
    
      setup() {
        const state = reactive({
          age: 5,
          money: 100,
        });
        const age = toRef(state, "age");
        const money = ref(state.money);
        const update = () => {
          age.value += 10;
          money.value += 10;
        };
    
        console.log(age);
        console.log(money);
    
        return {
          state,
          age,
          money,
          update
        };
      },
    });
    </script>
    

    在这里插入图片描述

  • 案例:

    <template>
      <h2>子组件</h2>
      <h3>age:{{age}}</h3>
      <h3>length:{{length}}</h3>
    </template>
    
    <script lang="ts">
    import { computed, defineComponent, Ref, toRef } from "vue";
    function useGetLength(age: Ref) {
        return computed(() => {
            // 将age属性转化成ref,与原属性是共通的
            return age.value.toString().length
        })
    }
    export default defineComponent({
      name: "Child",
      props:["age"],
      setup(props) {
          console.log(props.age);
          
          const length = useGetLength(toRef(props,"age"))  
          console.log(length);
          
          return {
              length
          }
      }
    });
    </script>
    
    <template>
      <h3>state:{{state}}</h3>
      <h3>age:{{age}}</h3>
      <h3>money:{{money}}</h3>
      <hr>
      <button @click="update">更新数据</button>
      <hr>
      <Child :age = "age"/>
    </template>
    
    <script lang="ts">
    import { defineComponent, reactive, ref, toRef } from "vue";
    import Child from "./components/Child.vue"
    
    export default defineComponent({
      name: "App",
      components: {
        Child
      },
      setup() {
        const state = reactive({
          age: 5,
          money: 100
        })
        const age = toRef(state, "age")
        const money = ref(state.money)
        const update = () => {
          age.value+=10
          
        }
        return {
          state,
          age,
          money,
          update
        };
      },
    });
    </script>
    

    在这里插入图片描述


# customRef

  • 创建一个自定义的 ref,并对其依赖项跟踪和更新触发进行显式控制

  • 需求: 使用 customRef 实现防抖的示例

    <template>
      <h2>customRef</h2>
      <input type="text" v-model="keyword">
      <p>{{keyword}}</p>
    </template>
    
    <script lang="ts">
    import { customRef, defineComponent } from "vue";
    // 自定义hook防抖
    function useAntiShake<T>(value: T, delay = 200) {
      let timeOutId: number
      return customRef((track, trigger) => {
        return {
          get() {
            // 告诉vue去追踪数据的变化
            track()
            return value
          },
          set(newValue: T) {
            clearTimeout(timeOutId)
            timeOutId = setTimeout(() => {
              value = newValue
              // 告诉vue更新界面
              trigger()
            }, delay)
          }
        }
      })
    }
    export default defineComponent({
      name: "App",
    
      setup() {
        const keyword = useAntiShake("abc", 3000)
        return {
          keyword
        };
      },
    });
    </script>
    

# provide 与 inject

  • provideinject提供依赖注入,功能类似 2.x 的provide/inject

  • 实现跨层级组件(祖孙)间通信

  • 案例:

    <template>
      <h2>provide 与 inject</h2>
      <p>当前的颜色:{{color}}</p>
      <button @click="color = 'red'">红色</button>
      <button @click="color = 'yellow'">黄色</button>
      <button @click="color = 'blue'">蓝色</button>
      <hr>
      <Son />
    </template>
    
    <script lang="ts">
    import { defineComponent, provide, ref } from "vue";
    import Son from "./compontent/Son.vue"
    export default defineComponent({
      name: "App",
      components: {
        Son
      },
      setup() {
        const color = ref("red")
        // 提供数据
        provide("color", color)
        return {
          color
        };
      },
    });
    </script>
    
    <template>
      <h2>子组件Son</h2>
      <hr>
      <GrandSon />
    </template>
       
    <script lang="ts">
    import { defineComponent } from "vue";
    import GrandSon from "./GrandSon.vue"
    export default defineComponent({
      name: "Son",
      components: {
          GrandSon
      },
      setup() {
       
        return {
          
        };
      },
    });
    </script>
    
    <template>
      <h3 :style="{color}">孙子组件: {{color}}</h3>
      
    </template>
    
    <script lang="ts">
    import { inject } from 'vue'
    export default {
      setup() {
        const color = inject('color')
    
        return {
          color
        }
      }
    }
    </script>
    

    在这里插入图片描述


# 响应式数据的判断

  • isRef: 检查一个值是否为一个 ref 对象

  • isReactive: 检查一个对象是否是由 reactive 创建的响应式代理

  • isReadonly: 检查一个对象是否是由 readonly 创建的只读代理

  • isProxy: 检查一个对象是否是由 reactive 或者 readonly 方法创建的代理

    <template>
     <h1></h1>
    </template>
    
    <script lang="ts">
    import { defineComponent, isProxy, isReactive, isReadonly, isRef, reactive, readonly, ref } from "vue";
    
    export default defineComponent({
      name: "App",
    
      setup() {
        console.log(isRef(ref({})));
        console.log(isReactive(reactive({})));
        console.log(isReadonly(readonly({})));
        console.log(isProxy(reactive({})));
      },
    });
    </script>
    

    在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值