vue3自定义hooks遇到的问题

问题

写了一个输入查询参数和url返回加载中状态、请求方法、接口返回列表的hooks,出现的结果是只有请求方法有效,加载状态无效,接口返回了数据,页面却不显示数据。

代码如下

只展示部分关键代码

vue 复制代码
import { ref, toRefs, toRef, onMounted, onActivated, reactive } from 'vue';
import baseService from '@/service/baseService';
export default (props) => {
  const defaultOptions = {
    getListURL: '',
    dataForm: {},
	loading: false,
	dataList: []
  };
  const state = ref({ ...defaultOptions, ...props });
  const fetchList = () => {
    if (!state.value.getListURL) {
      return;
    }
    state.value.loading = true;
    baseService
      .get(state.value.getListURL, { ...state.value.dataForm })
      .then((res) => {
        if (res.code === 0) {
          state.value.dataList = [...res.data ];
        }
      })
      .finally(() => {
        state.value.loading = false;
      });
  };

  onMounted(() => {
     fetchList();
  });
  return {
    fetchList,
    dataList: state.value.dataList,
    loading: state.value.loading,
  };
};

页面使用

vue 复制代码
<el-row :gutter="20" v-loading="loading">
   <el-col :span="12" v-for="item in dataList" :key="item.id">
      <div class="item">
         {{ item.name }}
      </div>
   </el-col>
</el-row>

const params = ref({
  name: '', // 搜索框名称
});
const { loading, fetchList, dataList } = useDataList({
  dataForm: params.value,
  getListURL: '/page/list',
});

分析

好久没用vue3,写出来的代码让自己一时找不出来问题,唉。。。

第一次尝试

在使用文件下面打印列表查看一下

vue 复制代码
const { loading, fetchList, dataList } = useDataList({
  dataForm: params.value,
  getListURL: '/page/list',
});
console.log(dataList);

是Proxy包裹的空数组,这应该是响应的数据,不像解构赋值出现的响应丢失啊。

为防止真的是这个问题,在hooks导出时使用toRefs包裹一下看看

vue 复制代码
import { ref, toRefs, toRef, onMounted, onActivated, reactive } from 'vue';
import baseService from '@/service/baseService';
export default (props) => {
  const defaultOptions = {
    getListURL: '',
    dataForm: {},
	loading: false,
	dataList: []
  };
  const state = ref({ ...defaultOptions, ...props });
  const fetchList = () => {
    if (!state.value.getListURL) {
      return;
    }
    state.value.loading = true;
    baseService
      .get(state.value.getListURL, { ...state.value.dataForm })
      .then((res) => {
        if (res.code === 0) {
          state.value.dataList = [...res.data ];
        }
      })
      .finally(() => {
        state.value.loading = false;
      });
  };

  onMounted(() => {
     fetchList();
  });
  return {
    fetchList,
	...toRefs({
		dataList: state.value.dataList,
    	loading: state.value.loading,
	})
  };
};

这下真好,打印的是ObjectRefImpl,然而查看里面看到还是空数组。

第二次尝试

接口响应里面有问题吗?那就在接口成功里面打印一下试试看

复制代码
import { ref, toRefs, toRef, onMounted, onActivated, reactive } from 'vue';
import baseService from '@/service/baseService';
export default (props) => {
  const defaultOptions = {
    getListURL: '',
    dataForm: {},
	loading: false,
	dataList: []
  };
  const state = ref({ ...defaultOptions, ...props });
  const fetchList = () => {
    if (!state.value.getListURL) {
      return;
    }
    state.value.loading = true;
    baseService
      .get(state.value.getListURL, { ...state.value.dataForm })
      .then((res) => {
        if (res.code === 0) {
          state.value.dataList = [...res.data ];
          console.log(state.value.dataList);
        }
      })
      .finally(() => {
        state.value.loading = false;
      });
  };

  onMounted(() => {
     fetchList();
  });
  return {
    fetchList,
    dataList: state.value.dataList,
    loading: state.value.loading,
  };
};

发现这里打印是有数据的,那在hooks方法里面返回前打印看看

复制代码
import { ref, toRefs, toRef, onMounted, onActivated, reactive } from 'vue';
import baseService from '@/service/baseService';
export default (props) => {
  const defaultOptions = {
    getListURL: '',
    dataForm: {},
	loading: false,
	dataList: []
  };
  const state = ref({ ...defaultOptions, ...props });
  const fetchList = () => {
    if (!state.value.getListURL) {
      return;
    }
    state.value.loading = true;
    baseService
      .get(state.value.getListURL, { ...state.value.dataForm })
      .then((res) => {
        if (res.code === 0) {
          state.value.dataList = [...res.data ];
        }
      })
      .finally(() => {
        state.value.loading = false;
      });
  };

  onMounted(() => {
     fetchList();
  });
  console.log(state.value.dataList);
  return {
    fetchList,
    dataList: state.value.dataList,
    loading: state.value.loading,
  };
};

啊?这里也是空对象,看来问题还是出现在hooks里面啊。直接打印state看看吧(应该上一次打印,这两个都打印试试的)

复制代码
import { ref, toRefs, toRef, onMounted, onActivated, reactive } from 'vue';
import baseService from '@/service/baseService';
export default (props) => {
  const defaultOptions = {
    getListURL: '',
    dataForm: {},
	loading: false,
	dataList: []
  };
  const state = ref({ ...defaultOptions, ...props });
  const fetchList = () => {
    if (!state.value.getListURL) {
      return;
    }
    state.value.loading = true;
    baseService
      .get(state.value.getListURL, { ...state.value.dataForm })
      .then((res) => {
        if (res.code === 0) {
          state.value.dataList = [...res.data ];
        }
      })
      .finally(() => {
        state.value.loading = false;
      });
  };

  onMounted(() => {
     fetchList();
  });
  console.log(state.value.dataList);
  console.log(state);
  return {
    fetchList,
    dataList: state.value.dataList,
    loading: state.value.loading,
  };
};

此时可以看到state里面是有接口返回的数据的,这样应该就说明不能使用.value获取之后返回使用,这时候的数据是接口响应前的。

那就改造一下直接返回refreactive的数据结构赋值之后是响应丢失的)

复制代码
import { ref, toRefs, toRef, onMounted, onActivated, reactive } from 'vue';
import baseService from '@/service/baseService';
export default (props) => {
  const defaultOptions = {
    getListURL: '',
    dataForm: {},
  };
  const state = ref({ ...defaultOptions, ...props });
  const loading = ref(false);
  const dataList = ref({});
  const fetchList = () => {
    if (!state.value.getListURL) {
      return;
    }
    loading.value = true;
    baseService
      .get(state.value.getListURL, { ...state.value.dataForm })
      .then((res) => {
        if (res.code === 0) {
          dataList.value = [...res.data ];
        }
      })
      .finally(() => {
        loading.value = false;
      });
  };

  onMounted(() => {
     fetchList();
  });
  return {
    fetchList,
    dataList,
    loading,
  };
};

<el-row :gutter="20" v-loading="loading.value">
   <el-col :span="12" v-for="item in dataList.value" :key="item.id">
      <div class="item">
         {{ item.name }}
      </div>
   </el-col>
</el-row>



const params = ref({
  name: '', // 搜索框名称
});
const { loading, fetchList, dataList } = useDataList({
  dataForm: params.value,
  getListURL: '/page/list',
});

但是这是为什么,还是有问题啊?崩溃啊!

第三次尝试

在使用里面打印一下

复制代码
<el-row :gutter="20" v-loading="loading.value">
   <el-col :span="12" v-for="item in dataList.value" :key="item.id">
      <div class="item">
         {{ item.name }}
      </div>
   </el-col>
</el-row>



const params = ref({
  name: '', // 搜索框名称
});
const { loading, fetchList, dataList } = useDataList({
  dataForm: params.value,
  getListURL: '/page/list',
});
console.log(dataList)

发现数据已经更新到接口返回的了,怎么页面没反应呢?额。。。好像页面模版里面可以省略.value,修改一下看看

复制代码
<el-row :gutter="20" v-loading="loading">
   <el-col :span="12" v-for="item in dataList" :key="item.id">
      <div class="item">
         {{ item.name }}
      </div>
   </el-col>
</el-row>



const params = ref({
  name: '', // 搜索框名称
});
const { loading, fetchList, dataList } = useDataList({
  dataForm: params.value,
  getListURL: '/page/list',
});
console.log(dataList)

撒花,终于解决完问题了(刚才不手欠加个.value,就不用耽误一次修改了)

结尾

  1. 自定义hooks,要想返回响应式ref数据,不要使用.value转一层,直接返回ref数据。
  2. 模板里面使用ref数据时候,不要加.value

彩蛋

使用css实现多行超出显示...无效

超出一行没换行

有的换行,但是超出没显示...

css 复制代码
overflow:hidden; 
text-overflow:ellipsis;
display:-webkit-box; 
-webkit-box-orient:vertical;
-webkit-line-clamp:2; 

这可能是英文文字太长导致的,这需要加上强制换行的css就可以

css 复制代码
word-break: break-all;
相关推荐
麦麦大数据2 小时前
F032 材料科学文献知识图谱可视化分析系统(四种知识图谱可视化布局) | vue + flask + echarts + d3.js 实现
vue.js·flask·知识图谱·数据可视化·论文文献·1024程序员节·科研图谱
web打印社区3 小时前
使用React如何静默打印页面:完整的前端打印解决方案
前端·javascript·vue.js·react.js·pdf·1024程序员节
喜欢踢足球的老罗3 小时前
[特殊字符] PM2 入门实战:从 0 到线上托管 React SPA
前端·react.js·前端框架
小光学长3 小时前
基于Vue的课程达成度分析系统t84pzgwk(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。
前端·数据库·vue.js
Baklib梅梅4 小时前
探码科技再获“专精特新”认定:Baklib引领AI内容管理新方向
前端·ruby on rails·前端框架·ruby
南方以南_4 小时前
Chrome开发者工具
前端·chrome
YiHanXii4 小时前
this 输出题
前端·javascript·1024程序员节
楊无好5 小时前
React中ref
前端·react.js
维他命Coco5 小时前
js常见开发学习
javascript
程琬清君5 小时前
vue3 confirm倒计时
前端·1024程序员节