您好,登錄后才能下訂單哦!
這篇文章主要介紹“Vue怎么實現父子組件頁面刷新”的相關知識,小編通過實際案例向大家展示操作過程,操作方法簡單快捷,實用性強,希望這篇“Vue怎么實現父子組件頁面刷新”文章能幫助大家解決問題。
很多時候我們在操作過頁面時候,特別是增刪改操作之后,數據會有所改變,這個時候我們希望返回的界面中的數據要和數據庫中的數據進行同步,就需要刷新當前頁面,如果是使用ajax可以使用異步請求實現頁面的局部刷新,Vue常用的幾種刷新頁面方法如下:
this.$router.go(0) //根據路由重新定向到當前頁 或者 location.reload() //重新加載當前頁
上述兩種方法可以數據同步,但是其實都是重新加載當前頁面,在刷新的時候會出現屏幕閃動,如果當前頁面初始化加載的數據或者請求很多的時候,此種方法嚴重影響效率和體驗感。
新建一個空白頁面組件empty.vue,點擊確定的時候先跳轉到這個空白頁,然后再立刻跳轉回當前頁面。
在需要刷新的頁面先引入空白頁面組件,再添加路由跳轉:
//引入空白頁面組件 import empty from '@/views/organization/empty.vue' //添加路由跳轉 this.$router.replace({ path:'/empty' });
此種方法基本和上述兩種方法,不會出現一瞬間的空白頁(如果網絡不好或者數據量大也可能會出現),只是地址欄有個快速的切換的過程,如果數據量不大也可以采用。
詳情參考官網指導文檔。
通常,當我們需要從父組件向子組件傳遞數據時,我們使用 props。想象一下這樣的結構:有一些深度嵌套的組件,而深層的子組件只需要父組件的部分內容。在這種情況下,如果仍然將 prop 沿著組件鏈逐級傳遞下去,可能會很麻煩。
對于這種情況,我們可以使用一對
provide
和inject
。無論組件層次結構有多深,父組件都可以作為其所有子組件的依賴提供者。這個特性有兩個部分:父組件有一個 provide 選項來提供數據,子組件有一個 inject 選項來開始使用這些數據。
此種方法最基本的Vue腳手架工程很容易實現:
在App.vue跟組件中定義變量和方法如下:
<template> <div id="app"> <router-view v-if="isShow"/> </div> </template> <script> export default { name: 'App', provide(){ //父組件中通過provide來提供變量,在子組件中通過inject來注入變量。 return{ reload:this.reload } }, data(){ return{ isShow:true //控制視圖是否顯示的變量 } }, methods:{ reload(){ this.isShow=false; //先關閉 this.$nextTick(()=>{ this.isShow=true //再打開 }) } } } </script>
在子組件中使用inject注入根組件的reload方法:
<template> <div> <div class="header"> <button @click="update()">刷新頁面</button> </div> </div> </template> <script> export default { data(){ return{ } }, inject:['reload'],//inject注入根組件的reload方法 methods:{ update(){ this.reload(); console.log('刷新頁面') } } } </script>
但是我使用的vue項目是基于webpack構建的,整體項目結構有點不同,搞了半天也沒搞出來:
<template> <div id="app"> <router-view v-if="isRouterAlive"/> </div> </template> <script lang="ts"> import { Component, Vue } from 'vue-property-decorator' @Component({ name: 'App', provide() { //父組件中通過provide來提供變量,在子組件中通過inject來注入變量。 reload: this.reload }, data() { return { isRouterAlive: true //控制視圖是否顯示的變量 } }, method: { reload() { this.isRouterAlive = false //先關閉 this.$nextTick(() => { this.isRouterAlive = true //再打開 }) } } }) export default class extends Vue {} </script>
子組件中注入reload:
<script lang="ts"> import { updateStore,//更新門店信息 getStoresData,//獲取門店列表信息 searchStore//根據門店id和商戶id獲取門店信息 } from '@/api/organization.ts' import App from '@/App.vue' @Component({ components: { updateStore, getStoresData, searchStore } }) /** * 此處的默認輸出是集成Vue類(和java中定義實體類跟相似) */ export default class createTasks extends Vue { //此處注入relod inject:['reload']; private async ensureDialog() { let res = await updateStore(this.form) this.syncDialogVisible = false; if (res) { this.$message.success('修改成功'); } //到達此處說明請求響應成功 this.reload();//此處調用根組件的reload方法 } }
上述做法不生效,如果有大神知道哪個不對,還望不吝賜教。
我們知道Vue有一個特點,只要vue實例中的數據屬性值發生改變,頁面中使用v-model
或者:data
渲染綁定的數據也會隨之改變,通常情況下展示數據的界面為父組件,需要對父組件中的某一條數據進行增刪改查操作時,都會響應彈出一個組件框懸浮在父組件之上單獨展示某一條數據的內容,而這個懸浮組件就可以看做是子組件。
所以我們只要在父組件中監聽到子組件的行為事件,就可以在進行當前頁面的局部數據刷新(非重新加載)。
父組件:index.vue
<template> <div class="data-container"> <h4>門店管理</h4> <el-table :data="list" fit highlight-current-row :header-cell- > </el-table> <addStore :dialogVisible.sync="dialogVisible" v-on:post="getList" @refreshList="getList"></addStore> <setCode :dialogVisible.sync="dialogVisible1" @refreshList="getList" :code="codes"></setCode> <updateStore :dialogVisible.sync="dialogVisible2" v-on:put="getList" @refreshList="getList" :storeIds="storeId"></updateStore> <setUse :dialogVisible.sync="dialogVisible3" @refreshList="getList" @getAppId="getAppIds"></setUse> <pagination v-show="total>0" :total="total" :page.sync="pageNo" :limit.sync="pageSize" @pagination="getList" /> </div> </template> <script lang="ts"> import addStore from '@/views/organization/addStore.vue' import Pagination from "@/components/Pagination/index.vue"; import setCode from '@/views/organization/setCode.vue' import updateStore from '@/views/organization/updateStore.vue' import setUse from '@/views/organization/setUse.vue' @Component({ components: { addStore, Pagination, setCode, updateStore, setUse } }) export default class extends Vue { private list: any[] = []; private pageNo: number = 1; private pageSize: number = 10; private total: number = 0; private dialogVisible: boolean = false; private dialogVisible1: boolean = false; private dialogVisible2: boolean = false; private dialogVisible3: boolean = false; private appId: string = ''; private codes: string = ''; private storeId: string = ''; private storeForm = { storeName: '', storeNumber: '' } private form = { totalAmount: '', body: '' } created() { this.getList() } private async getList() { let data = await getStoresData(this.pageNo, this.pageSize, this.storeForm) this.list = data.items; //查詢到的門店列表 this.total = this.list.length; //查詢到的總記錄數 } } </script>
可以看到上述父組件中包含了以下子組件:
//新增門店子組件 <addStore :dialogVisible.sync="dialogVisible" v-on:post="getList" @refreshList="getList"></addStore> //更新門店子組件 <updateStore :dialogVisible.sync="dialogVisible2" v-on:put="getList" @refreshList="getList" :storeIds="storeId"></updateStore>
getList方法的作用就是更新當前父組件要展示的數據:
private async getList() { let data = await getStoresData(this.pageNo, this.pageSize, this.storeForm) this.list = data.items; //查詢到的門店列表 }
getStoresData方法:
//分頁條件查詢商戶下門店 export const getStoresData = (pageNo:number,pageSize:number,data:any) => request({ url: `/merchant/my/stores/merchants/page?pageNo=${pageNo}&pageSize=${pageSize}&tenantId=${UserModule.tenantId}`, method: 'post', data })
渲染數據:
this.list = data.items; //查詢到的門店列表 <el-table :data="list" fit highlight-current-row :header-cell- > </el-table>
更新數據子組件updaStore.vue:
<template> <el-dialog title="修改門店信息" :visible.sync="syncDialogVisible" @open="opend"> <el-form :inline="false"> <el-form-item label="門店名稱:" :label-width="formLabelWidth" :rules="[{required:true}]"> <el-input v-model="form.storeName"></el-input> </el-form-item > <el-form-item label="門店地址:" :label-width="formLabelWidth"> <el-input v-model="form.storeAddress"></el-input> </el-form-item> <el-form-item label="門店編號:" :label-width="formLabelWidth"> <el-input v-model="form.storeNumber"></el-input> </el-form-item> </el-form> <div slot="footer" class="dialog-footer"> <el-button @click="syncDialogVisible = false">取 消</el-button> <el-button type="primary" @click="ensureDialog">確 定</el-button> </div> </el-dialog> </template> <script lang="ts"> @Component({ components: { updateStore, getStoresData, searchStore } }) export default class createTasks extends Vue { @PropSync('dialogVisible', { type: Boolean, default: false }) syncDialogVisible!: boolean @PropSync('storeIds', { type: String }) storeId!: string private form = { id: 0, storeAddress: '', storeName: '', storeNumber: 0, parentId: 0, storeStatus: '', merchantId: 0 } private storeForm = { storeNumber: '', storeName: '' } list: any[] = []; pageNo: number = 1; pageSize: number = 10; total: number = 0; private filterData: any[] = []; private opend() { this.getList(); } private async getList() { let res = await searchStore(this.storeId); this.form = res.result; } private async ensureDialog() { let res = await updateStore(this.form) this.syncDialogVisible = false; if (res) { this.$message.success('修改成功'); } } } </script>
實際應用場景:
在子組件updateStore.vue中,點擊確定修改,修改成功之后在當前組件中進行查詢門店列表getStoresData:
private async ensureDialog() { let res = await updateStore(this.form) this.syncDialogVisible = false; if (res) { this.$message.success('修改成功'); } //此處查詢列表信息 let ret = await getStoresData(this.pageNo, this.pageSize, this.storeForm); this.list = ret.items; this.total = this.list.length; }
按理論是查詢到了修改之后的門店列表list,但是當前是在子組件中,list和父組件index.vue中的list作用域不同,所以父組件中的內容也不會發生改變同步更新,那怎么辦呢?
上述我們說了,我們需要父組件監聽子組件的事件,當子組件完成相應的操作請求之后可以觸發父組件所監聽的回調函數,讓其父組件index.vue實現list的更新,刷新頁面中的數據。
在父組件index.vue中:
//更新門店子組件 <updateStore :dialogVisible.sync="dialogVisible2" v-on:put="getList" @refreshList="getList" :storeIds="storeId"></updateStore>
v-on:put="getList"
其中的put就是監聽子組件的一個可觸發事件,所以我們可以在子組件中完成put更新請求之后,觸發該事件,讓父組件來完成同步更新渲染數據。
此處完成同步更新有兩種方式:
子組件直接觸發父組件的監聽事件,父組件查詢列表信息
子組件將查詢好的列表信息,在觸發監聽事件同時傳遞給父組件
第一種方式:直接觸發監聽事件
private async ensureDialog() { let res = await updateStore(this.form) this.syncDialogVisible = false; if (res) { this.$message.success('修改成功'); } //觸發父組件監聽事件put this.$emit('put'); }
//父組件監聽到事件put v-on:put="getList" //調用getList方法重新查詢列表信息(此處的this.list就是渲染界面的綁定屬性),這樣完成數據刷新,而不用重新加載整個頁面 private async getList() { let data = await getStoresData(this.pageNo, this.pageSize, this.storeForm) this.list = data.items; //查詢到的門店列表 this.total = this.list.length; //查詢到的總記錄數 }
第二種方式:觸發監聽事件的同時傳遞數據
private async ensureDialog() { let res = await updateStore(this.form) this.syncDialogVisible = false; if (res) { this.$message.success('修改成功'); } //此處查詢列表信息 let ret = await getStoresData(this.pageNo, this.pageSize, this.storeForm); let = ret.items; = this.list.length; //觸發父組件監聽事件put,同時傳遞數據(后面的皆為參數數據) this.$emit('put',ret.items,ret.items.length); }
//父組件監聽到事件put v-on:put="getList" //根據子組件傳遞過來的數據進行同步更新渲染(此方法的參數列表個數要與所監聽的事件傳遞的參數個數保持一致) private async getList(param1,param2) { this.list = param1; //子組件傳遞過來的列表數據 this.total = param2; //子組件傳遞過來的列表記錄數 }
addStore.vue子組件同樣可以用此方法完成同步更新渲染。
關于“Vue怎么實現父子組件頁面刷新”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識,可以關注億速云行業資訊頻道,小編每天都會為大家更新不同的知識點。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。