问题分析
Vue3:当我们建立父子通信时,父组件传递给子组件的值,只有在模板上使用,才会具有响应式,我们在代码上使用的时候,就只能拿到刚开始传入的prop的“死值”,即使父组件值发生改变,它依旧保持不变,但是模板上,它还是具有响应式的,问题就是我们业务需求就是想拿到这个prop值,进行代码逻辑计算之后,在进行渲染到模板上
情景导入+解决方法
方法一:比较官方
解决父子组件页码同步的问题:
有一组数据,从父组件传入,但是我们是把数据渲染到表格上,肯定会涉及到分页,那么我们点击分页按钮时,数据应该进行筛选,重新渲染。首先要解决的就是点击某个页码,切换这个页码对应的数据。我们一般会把组件的交互权限交给父组件,那么我们子组件被点击的时候,就需要通过event up发生自定义事件给父组件,由父组件自行解决数据,子组件只负责交互和展示;这里也是组件封装的思想之一;子组件就干 展示+交互,至于交互做什么处理,以及数据怎么处理,我子组件一概不管,交给你父组件
//分页器,用的是Element组件,里面的页码通过v-model双向数据绑定
//这里可以通过Watch数据侦听,侦听currentPage数据的变化
<template>
<div class="my-pagination">
<el-pagination background layout="prev, pager, next" :page-size="pageSize" :total="tableData.length" v-model:current-page="currentPage" />
</div>
</template>
//侦听currentPage数据逻辑,当数据一变化,就把当前页码emit()发送自定义事件并携带当前页码数,给父组件
<script setup>
const currentPage = ref(1);
watch(
/* 监听页码项 */
() => currentPage,
/* 发生变化时,传递给父组件更新 */
(nv, ov) => {
console.log("currentPage changed", nv, ov);
emit("pageChange", nv)
}
)
</script>
解决分页数据问题:
//父组件
<EpTable @pageChange="onPageChange" :tableData="computedData"></EpTable>
const currentPage = ref(1);
const onPageChange = (page)=>{
currentPage.value = page
}
//计算分页数据具体逻辑(一页十条)
const computedData = computed(() => tableData.value.slice((currentPage.value - 1) * 10, currentPage.value * 10));
//最终把这个计算出来的分页数据注入给子组件
方法二:来点简单粗暴的
父组件传入全部数据,由子组件自己进行数据的选择,当用户选择页码,(分页器当中的页码一变化)就导致重新刷新这个模板,再重新调用这个模板上的方法,获得最新数据
父组件就当甩手掌柜,一开始就把数据丢给你子组件,你爱怎么处理就怎么处理,可能和上头组件封装思想有点出入,但是实际问题实际分析,你就看看这方法二好还是方法一好
//父组件
<EpTable :tableData="tableData"></EpTable>
<script setup>
const tableData = ref([])
//这是具体业务逻辑,联网获取所有数据
onMounted(async () => {
const films = await getComings()
console.log("films", films);
tableData.value = films;
})
</script>
//子组件
<el-table :data="getNewData(tableData)"></el-table>
//由于prop传入的值,在代码中不具有响应式,在模板上才有,将计就计,把数据放入一个函数,传递到代码当中,进行计算之后,我再把返回值丢给模板自行渲染
//当我们选择页码,(分页器当中的页码一变化)就导致重新刷新这个模板,就会重新调用这个模板上的方法,获得最新数据,重绘页面
<script setup>
const getNewData = (arr) => {
return arr.slice((currentPage.value - 1) * pageSize, (currentPage.value) * pageSize)
}
</script>
最后,你们觉得哪种更好呢?
下课!