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,點(diǎn)擊確定的時候先跳轉(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)有點(diǎn)不同,搞了半天也沒搞出來:
<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有一個特點(diǎn),只要vue實例中的數(shù)據(jù)屬性值發(fā)生改變,頁面中使用v-model或者:data渲染綁定的數(shù)據(jù)也會隨之改變,通常情況下展示數(shù)據(jù)的界面為父組件,需要對父組件中的某一條數(shù)據(jù)進(jìn)行增刪改查操作時,都會響應(yīng)彈出一個組件框懸浮在父組件之上單獨(dú)展示某一條數(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中,點(diǎn)擊確定修改,修改成功之后在當(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-05
vue+elementUI多表單同時提交及表單校驗最新解決方案
假設(shè)有一個頁面,需要分三步填寫三個表單,且每個表單位于獨(dú)立的組件中,然后最后保存同時提交,如何進(jìn)行表單必填項校驗,下面小編給大家介紹vue+elementUI多表單同時提交及表單校驗最新解決方案,感興趣的朋友一起看看吧2024-03-03
vuejs router history 配置到iis的方法
今天小編就為大家分享一篇vuejs router history 配置到iis的方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-09-09
Vue——解決報錯 Computed property "****" was assigned to but it ha
這篇文章主要介紹了Vue——解決報錯 Computed property "****" was assigned to but it has no setter.的方法,幫助大家更好的理解和使用vue框架,感興趣的朋友可以了解下2020-12-12
vue如何使用window.open打開頁面并拼接參數(shù)
這篇文章主要介紹了vue如何使用window.open打開頁面并拼接參數(shù),具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-09-09
Vue服務(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

