返回一个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>