customRef---创建一个自定义ref

返回一个ref对象,可以显式地控制依赖追踪和触发响应

<template>
  <div>
    <div>{
    
    {
    
     state }}</div>
    <button @click="handelClick">按钮</button>
  </div>
</template>

<script>
import {
    
     ref, customRef } from "vue";
// value:接收一个参数
function myRef(value) {
    
    
  // 返回一个回调函数,接收两个参数,分别是追中变化与触发更新
  return customRef((track, trigger) => {
    
    
    return {
    
    
      get() {
    
    
        track(); //告诉Vue这个数据是需要追踪变化的
        console.log("get", value);
        return value;
      },
      // 更新时会接收一个新值
      set(newValue) {
    
    
        value = newValue; //更新值
        console.log("set", newValue);
        trigger(); //告诉Vue触发界面更新
      },
    };
  });
}
export default {
    
    
  setup() {
    
    
    let state = myRef(1);
    function handelClick() {
    
    
      state.value = 2;
    }
    return {
    
     state,handelClick };
  },
};
</script>

效果
在这里插入图片描述

为什么要自定义ref?

在开发中获取的数据有可能是本地的,也有可能是远程服务器上的,如果是远程服务器上的需要发送网络请求再获取数据,而网络请求是一个异步操作,异步操作则需要在异步函数里面操作,如果业务复杂的话就会出现大量回调函数嵌套的情况.
过去我们可以通过async和await解决,但在setup只能接受同步操作,但是customRef就可以解决这一问题

//index.vue
<template>
  <div>
    <ul>
      <li v-for="(item, index) in state" :key="index">{
    
    {
    
     item.name }}</li>
    </ul>
  </div>
</template>

<script>
import {
    
     ref, customRef } from "vue";
// value:接收一个参数
function myRef(value) {
    
    
  // 返回一个回调函数,接收两个参数,分别是追中变化与触发更新
  return customRef((track, trigger) => {
    
    
    // 传入路径,返回promise
    fetch(value)
      .then((res) => {
    
    
        return res.json(); //为了方便处理转换成json
      })
      .then((data) => {
    
    
        // 拿到服务器返回的数据
        console.log(data);
        value = data;
        trigger(); //告诉Vue触发界面更新
      })
      .catch((err) => {
    
    
        // 失败的时候打印
        console.log(err);
      });
    return {
    
    
      get() {
    
    
        track(); //告诉Vue这个数据是需要追踪变化的
        console.log("get", value);
        //注意:不能再get发送网络请求,会死循环
        //渲染页面>调用get>发送网络请求
        //保存数据>更新界面>调用get
        return value;
      },
      // 更新时会接收一个新值
      set(newValue) {
    
    
        value = newValue; //更新值
        console.log("set", newValue);
        trigger(); //告诉Vue触发界面更新
      },
    };
  });
}
export default {
    
    
  setup() {
    
    
    // 解决异步
    let state = myRef("./data.json");
    // let state=ref([])
    // // 传入路径,返回promise
    // fetch('./data.json')
    // .then((res)=>{
    
    
    //   return res.json()//为了方便处理转换成json
    // })
    // .then((data)=>{
    
    
    //   // 拿到服务器返回的数据
    //   console.log(data);
    //   state.value=data
    // })
    // .catch((err)=>{
    
    
    //   // 失败的时候打印
    //   console.log(err);
    // })
    return {
    
     state };
  },
};
</script>

//data.json,需要把这注释删除
[
    {
    
    "id":1,"name":"黄忠"},
    {
    
    "id":2,"name":"周瑜"},
    {
    
    "id":3,"name":"安其拉"}
]

效果

在这里插入图片描述

异步写法

<template>
  <div>
    <ul>
      <li v-for="(item, index) in state" :key="index">{
    
    {
    
     item.name }}</li>
    </ul>
  </div>
</template>

<script>
import {
    
     ref, customRef } from "vue";
// value:接收一个参数
function myRef(value) {
    
    
  // 返回一个回调函数,接收两个参数,分别是追中变化与触发更新
  return customRef((track, trigger) => {
    
    
    // 传入路径,返回promise
    fetch(value)
      .then((res) => {
    
    
        return res.json(); //为了方便处理转换成json
      })
      .then((data) => {
    
    
        // 拿到服务器返回的数据
        console.log(data);
        value = data;
        trigger(); //告诉Vue触发界面更新
      })
      .catch((err) => {
    
    
        // 失败的时候打印
        console.log(err);
      });
    return {
    
    
      get() {
    
    
        track(); //告诉Vue这个数据是需要追踪变化的
        console.log("get", value);
        //注意:不能再get发送网络请求,会死循环
        //渲染页面>调用get>发送网络请求
        //保存数据>更新界面>调用get
        return value;
      },
      // 更新时会接收一个新值
      set(newValue) {
    
    
        value = newValue; //更新值
        console.log("set", newValue);
        trigger(); //告诉Vue触发界面更新
      },
    };
  });
}
export default {
    
    
  setup() {
    
    
    // 解决异步
    let state = myRef("./data.json");
    // let state=ref([])
    // // 传入路径,返回promise
    // fetch('./data.json')
    // .then((res)=>{
    
    
    //   return res.json()//为了方便处理转换成json
    // })
    // .then((data)=>{
    
    
    //   // 拿到服务器返回的数据
    //   console.log(data);
    //   state.value=data
    // })
    // .catch((err)=>{
    
    
    //   // 失败的时候打印
    //   console.log(err);
    // })
    return {
    
     state };
  },
};
</script>

Guess you like

Origin blog.csdn.net/weixin_47886687/article/details/112966339
Recommended