Vue實現(xiàn)父子組件頁面刷新的幾種常用方法
很多時候我們在操作過頁面時候,特別是增刪改操作之后,數(shù)據(jù)會有所改變,這個時候我們希望返回的界面中的數(shù)據(jù)要和數(shù)據(jù)庫中的數(shù)據(jù)進(jìn)行同步,就需要刷新當(dāng)前頁面,如果是使用ajax可以使用異步請求實現(xiàn)頁面的局部刷新,Vue常用的幾種刷新頁面方法如下:
1、原地頁面重新加載(不推薦)
this.$router.go(0) //根據(jù)路由重新定向到當(dāng)前頁 或者 location.reload() //重新加載當(dāng)前頁
上述兩種方法可以數(shù)據(jù)同步,但是其實都是重新加載當(dāng)前頁面,在刷新的時候會出現(xiàn)屏幕閃動,如果當(dāng)前頁面初始化加載的數(shù)據(jù)或者請求很多的時候,此種方法嚴(yán)重影響效率和體驗感。
2、空白頁面作為過渡
新建一個空白頁面組件empty.vue,點擊確定的時候先跳轉(zhuǎn)到這個空白頁,然后再立刻跳轉(zhuǎn)回當(dāng)前頁面。
在需要刷新的頁面先引入空白頁面組件,再添加路由跳轉(zhuǎn):
//引入空白頁面組件 import empty from '@/views/organization/empty.vue' //添加路由跳轉(zhuǎn) this.$router.replace({ path:'/empty' });
此種方法基本和上述兩種方法,不會出現(xiàn)一瞬間的空白頁(如果網(wǎng)絡(luò)不好或者數(shù)據(jù)量大也可能會出現(xiàn)),只是地址欄有個快速的切換的過程,如果數(shù)據(jù)量不大也可以采用。
3、使用Provide / Inject組合控制顯示
通常,當(dāng)我們需要從父組件向子組件傳遞數(shù)據(jù)時,我們使用 props。想象一下這樣的結(jié)構(gòu):有一些深度嵌套的組件,而深層的子組件只需要父組件的部分內(nèi)容。在這種情況下,如果仍然將 prop 沿著組件鏈逐級傳遞下去,可能會很麻煩。
對于這種情況,我們可以使用一對
provide
和inject
。無論組件層次結(jié)構(gòu)有多深,父組件都可以作為其所有子組件的依賴提供者。這個特性有兩個部分:父組件有一個 provide 選項來提供數(shù)據(jù),子組件有一個 inject 選項來開始使用這些數(shù)據(jù)。
此種方法最基本的Vue腳手架工程很容易實現(xiàn):
在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; //先關(guān)閉 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構(gòu)建的,整體項目結(jié)構(gòu)有點不同,搞了半天也沒搞出來:
<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 //先關(guān)閉 this.$nextTick(() => { this.isRouterAlive = true //再打開 }) } } }) export default class extends Vue {} </script>
子組件中注入reload:
<script lang="ts"> import { updateStore,//更新門店信息 getStoresData,//獲取門店列表信息 searchStore//根據(jù)門店id和商戶id獲取門店信息 } from '@/api/organization.ts' import App from '@/App.vue' @Component({ components: { updateStore, getStoresData, searchStore } }) /** * 此處的默認(rèn)輸出是集成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('修改成功'); } //到達(dá)此處說明請求響應(yīng)成功 this.reload();//此處調(diào)用根組件的reload方法 } }
上述做法不生效,如果有大神知道哪個不對,還望不吝賜教。
4、v-on:param父組件監(jiān)聽子組件事件
我們知道Vue有一個特點,只要vue實例中的數(shù)據(jù)屬性值發(fā)生改變,頁面中使用v-model
或者:data
渲染綁定的數(shù)據(jù)也會隨之改變,通常情況下展示數(shù)據(jù)的界面為父組件,需要對父組件中的某一條數(shù)據(jù)進(jìn)行增刪改查操作時,都會響應(yīng)彈出一個組件框懸浮在父組件之上單獨展示某一條數(shù)據(jù)的內(nèi)容,而這個懸浮組件就可以看做是子組件。
所以我們只要在父組件中監(jiān)聽到子組件的行為事件,就可以在進(jìn)行當(dāng)前頁面的局部數(shù)據(jù)刷新(非重新加載)。
父組件:index.vue
<template> <div class="data-container"> <h3>門店管理</h3> <el-table :data="list" fit highlight-current-row :header-cell-style="{color:'#5373e0',background:'#f3f6fb'}" style="width: 100%"> </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; //查詢到的總記錄數(shù) } } </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方法的作用就是更新當(dāng)前父組件要展示的數(shù)據(jù):
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 })
渲染數(shù)據(jù):
this.list = data.items; //查詢到的門店列表 <el-table :data="list" fit highlight-current-row :header-cell-style="{color:'#5373e0',background:'#f3f6fb'}" style="width: 100%"> </el-table>
更新數(shù)據(jù)子組件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>
實際應(yīng)用場景:
在子組件updateStore.vue中,點擊確定修改,修改成功之后在當(dāng)前組件中進(jìn)行查詢門店列表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,但是當(dāng)前是在子組件中,list和父組件index.vue中的list作用域不同,所以父組件中的內(nèi)容也不會發(fā)生改變同步更新,那怎么辦呢?
上述我們說了,我們需要父組件監(jiān)聽子組件的事件,當(dāng)子組件完成相應(yīng)的操作請求之后可以觸發(fā)父組件所監(jiān)聽的回調(diào)函數(shù),讓其父組件index.vue實現(xiàn)list的更新,刷新頁面中的數(shù)據(jù)。
在父組件index.vue中:
//更新門店子組件 <updateStore :dialogVisible.sync="dialogVisible2" v-on:put="getList" @refreshList="getList" :storeIds="storeId"></updateStore>
v-on:put="getList"
其中的put就是監(jiān)聽子組件的一個可觸發(fā)事件,所以我們可以在子組件中完成put更新請求之后,觸發(fā)該事件,讓父組件來完成同步更新渲染數(shù)據(jù)。
此處完成同步更新有兩種方式:
- 子組件直接觸發(fā)父組件的監(jiān)聽事件,父組件查詢列表信息
- 子組件將查詢好的列表信息,在觸發(fā)監(jiān)聽事件同時傳遞給父組件
第一種方式:直接觸發(fā)監(jiān)聽事件
private async ensureDialog() { let res = await updateStore(this.form) this.syncDialogVisible = false; if (res) { this.$message.success('修改成功'); } //觸發(fā)父組件監(jiān)聽事件put this.$emit('put'); }
//父組件監(jiān)聽到事件put v-on:put="getList" //調(diào)用getList方法重新查詢列表信息(此處的this.list就是渲染界面的綁定屬性),這樣完成數(shù)據(jù)刷新,而不用重新加載整個頁面 private async getList() { let data = await getStoresData(this.pageNo, this.pageSize, this.storeForm) this.list = data.items; //查詢到的門店列表 this.total = this.list.length; //查詢到的總記錄數(shù) }
第二種方式:觸發(fā)監(jiān)聽事件的同時傳遞數(shù)據(jù)
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; //觸發(fā)父組件監(jiān)聽事件put,同時傳遞數(shù)據(jù)(后面的皆為參數(shù)數(shù)據(jù)) this.$emit('put',ret.items,ret.items.length); }
//父組件監(jiān)聽到事件put v-on:put="getList" //根據(jù)子組件傳遞過來的數(shù)據(jù)進(jìn)行同步更新渲染(此方法的參數(shù)列表個數(shù)要與所監(jiān)聽的事件傳遞的參數(shù)個數(shù)保持一致) private async getList(param1,param2) { this.list = param1; //子組件傳遞過來的列表數(shù)據(jù) this.total = param2; //子組件傳遞過來的列表記錄數(shù) }
addStore.vue子組件同樣可以用此方法完成同步更新渲染。
參考文檔:
到此這篇關(guān)于Vue實現(xiàn)父子組件頁面刷新的幾種常用方法的文章就介紹到這了,更多相關(guān)Vue 父子組件頁面刷新內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- vue組件強(qiáng)制刷新的4種方案
- Vue3中進(jìn)行頁面局部刷新組件刷新的操作方法
- Vue?Router解決多路由復(fù)用同一組件頁面不刷新問題(場景分析)
- vue組件值變化但不刷新強(qiáng)制組件刷新的問題
- vue打開子組件彈窗都刷新功能的實現(xiàn)
- vue相同路由跳轉(zhuǎn)強(qiáng)制刷新該路由組件操作
- 解決vue更新路由router-view復(fù)用組件內(nèi)容不刷新的問題
- vue強(qiáng)制刷新組件的方法示例
- Vue 實現(xiàn)手動刷新組件的方法
- 使用Vue開發(fā)動態(tài)刷新Echarts組件的教程詳解
- vue強(qiáng)制刷新組件的三種方法
相關(guān)文章
babel7.x和webpack4.x配置vue項目的方法步驟
這篇文章主要介紹了babel7.x和webpack4.x配置vue項目的方法步驟,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2019-05-05vue+elementUI多表單同時提交及表單校驗最新解決方案
假設(shè)有一個頁面,需要分三步填寫三個表單,且每個表單位于獨立的組件中,然后最后保存同時提交,如何進(jìn)行表單必填項校驗,下面小編給大家介紹vue+elementUI多表單同時提交及表單校驗最新解決方案,感興趣的朋友一起看看吧2024-03-03vuejs router history 配置到iis的方法
今天小編就為大家分享一篇vuejs router history 配置到iis的方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-09-09Vue——解決報錯 Computed property "****" was assigned to but it ha
這篇文章主要介紹了Vue——解決報錯 Computed property "****" was assigned to but it has no setter.的方法,幫助大家更好的理解和使用vue框架,感興趣的朋友可以了解下2020-12-12vue如何使用window.open打開頁面并拼接參數(shù)
這篇文章主要介紹了vue如何使用window.open打開頁面并拼接參數(shù),具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-09-09Vue服務(wù)端渲染實踐之Web應(yīng)用首屏耗時最優(yōu)化方案
這篇文章主要介紹了Vue服務(wù)端渲染實踐之Web應(yīng)用首屏耗時最優(yōu)化方案,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-03-03