Vue实现父子组件页面刷新的几种常用方法

目录
  • 1、原地页面重新加载(不推荐)
  • 2、空白页面作为过渡
  • 3、使用Provide / Inject组合控制显示
  • 4、v-on:param父组件监听子组件事件
  • 参考文档:

很多时候我们在操作过页面时候,特别是增删改操作之后,数据会有所改变,这个时候我们希望返回的界面中的数据要和数据库中的数据进行同步,就需要刷新当前页面,如果是使用ajax可以使用异步请求实现页面的局部刷新,Vue常用的几种刷新页面方法如下:

1、原地页面重新加载(不推荐)

this.$router.go(0) //根据路由重新定向到当前页
或者
location.reload() //重新加载当前页

上述两种方法可以数据同步,但是其实都是重新加载当前页面,在刷新的时候会出现屏幕闪动,如果当前页面初始化加载的数据或者请求很多的时候,此种方法严重影响效率和体验感。

2、空白页面作为过渡

新建一个空白页面组件empty.vue,点击确定的时候先跳转到这个空白页,然后再立刻跳转回当前页面。

在需要刷新的页面先引入空白页面组件,再添加路由跳转:

//引入空白页面组件
import empty from '@/views/organization/empty.vue'

//添加路由跳转
this.$router.replace({ path:'/empty' });

此种方法基本和上述两种方法,不会出现一瞬间的空白页(如果网络不好或者数据量大也可能会出现),只是地址栏有个快速的切换的过程,如果数据量不大也可以采用。

3、使用Provide / Inject组合控制显示

详情参考官网指导文档。

通常,当我们需要从父组件向子组件传递数据时,我们使用 props。想象一下这样的结构:有一些深度嵌套的组件,而深层的子组件只需要父组件的部分内容。在这种情况下,如果仍然将 prop 沿着组件链逐级传递下去,可能会很麻烦。

对于这种情况,我们可以使用一对 provideinject。无论组件层次结构有多深,父组件都可以作为其所有子组件的依赖提供者。这个特性有两个部分:父组件有一个 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方法
        }
	}

上述做法不生效,如果有大神知道哪个不对,还望不吝赐教。

4、v-on:param父组件监听子组件事件

我们知道Vue有一个特点,只要vue实例中的数据属性值发生改变,页面中使用v-model或者:data渲染绑定的数据也会随之改变,通常情况下展示数据的界面为父组件,需要对父组件中的某一条数据进行增删改查操作时,都会响应弹出一个组件框悬浮在父组件之上单独展示某一条数据的内容,而这个悬浮组件就可以看做是子组件。

所以我们只要在父组件中监听到子组件的行为事件,就可以在进行当前页面的局部数据刷新(非重新加载)。

父组件: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; //查询到的总记录数
        }
    }
</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-style="{color:'#5373e0',background:'#f3f6fb'}"
      style="width: 100%">
    </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子组件同样可以用此方法完成同步更新渲染。

参考文档:

$emits选项

Vue组件基础(监听子组件事件)

到此这篇关于Vue实现父子组件页面刷新的几种常用方法的文章就介绍到这了,更多相关Vue 父子组件页面刷新内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • Vue监听页面刷新和关闭功能

    我在做项目的时候,有一个需求,在离开(跳转或者关闭)购物车页面或者刷新购物车页面的时候向服务器提交一次购物车商品数量的变化. 将提交的一步操作放到 beforeDestroy 钩子函数中. beforeDestroy() { console.log('销毁组件') this.finalCart()}, 但是发现  beforeDestroy 只能监听到页面间的跳转,无法监听到页面刷新和关闭标签页. 所以还是要借助 onbeforeunload 事件. 顺便复习了一下 JavaScript 中的一

  • 解决vue 路由变化页面数据不刷新的问题

    每天记录一点点,把我遇到的问题记录下来, 希望可以帮助到更多和我遇到同样问题的人. 问题描述:通过调接口,动态显示帮助页面的问题列表, 问题列表有多级,当点击的这个问题没有下一级问题的时候跳入内容页. 问题出在,我在电脑上做移动端页面的时候,相继跳到详情页,我想返回,点击 按钮,直接跳转到了如上第一张图的样子,no,no,no,这不是我想要的结果,此刻,想到了通过改变url来改变页面的层级问题. 一级的parent为0,默认不显示或显示. 二级的parent为1,点击一级路由变为如图: 点击进入

  • vue主动刷新页面及列表数据删除后的刷新实例

    1.场景 在处理列表时,常常有删除一条数据或者新增数据之后需要重新刷新当前页面的需求. 2.遇到的问题 1. 用vue-router重新路由到当前页面,页面是不进行刷新的 2.采用window.reload(),或者router.go(0)刷新时,整个浏览器进行了重新加载,闪烁,体验不好 3.解决方法 provide / inject 组合 作用:允许一个祖先组件向其所有子孙后代注入一个依赖,不论组件层次有多深,并在起上下游关系成立的时间里始终生效. App.vue: 声明reload方法,控制

  • vue项目刷新当前页面的三种方法

    想必大家在刨坑vue的时候也遇到过下面情形:比如在删除或者增加一条记录的时候希望当前页面可以重新刷新或者如下面这种: 如果希望点击确定的时候,Dialog 对话框关闭的时候,当前http://localhost:9530/#/supplier/supplierAll页面可以重新刷新下 那么表格的数据可以重新加载,Dialog 对话框设置的数据可以在确定后刷新出现在页面上 这时候我们最直接的思维就是想到下面这种: 但是,试过的会发现用vue-router重新路由到当前页面,页面是不进行刷新的,根本

  • vue.js实现刷新当前页面的方法教程

    前言 Vue.js(是一套构建用户界面的渐进式框架.与其他重量级框架不同的是,Vue 采用自底向上增量开发的设计.Vue 的核心库只关注视图层,是一种数据驱动的前端框架 我们在开发vue的页面的时候,有时候会遇到需要刷新当前页面功能,但是vue框架自带的router是不支持刷新当前页面功能的,它只支持在路由路径变化时刷新页面.基于这个原理,为了实现刷新页面,可以先跳转到一个空页面,然后马上跳回来,从而实现这个功能. 开发工具环境 vue.js webstorm 方法如下 一.原理 如上图所示,我

  • 解决vue单页使用keep-alive页面返回不刷新的问题

    使用vue单页开发项目时遇到一个很恶心的问题:在列表页点击一条数据进入详情页,按返回键返回列表页时页面刷新了,用户体验非常差啊!!!查阅了一下相关问题,使用<keep-alive>解决这个问题,下面是我的使用心得. <keep-alive>是Vue的内置组件,能在组件切换过程中将状态保留在内存中,防止重复渲染DOM. 首先在App.vue页面上有下面一段代码,我们都知道这是页面渲染的地方 <router-view></router-view> 把这段代码改成

  • vue router嵌套路由在history模式下刷新无法渲染页面问题的解决方法

    解决vue-router嵌套路由(子路由)在history模式下刷新无法渲染页面的问题,具体内容如下 一. 异常描述 本来使用的是vue-router的hash模式,但是hash模式下url需要带"#"符号,不仅看起来不舒服,而且有些场景下是会破坏路由中的"#"(微信分享页面就会把"#"后边的内容处理掉),所以就需要使用history模式,然后就让后端改下nginx配置: location / { try_files $uri $uri/ /in

  • vue项目如何刷新当前页面的方法

    1.场景 在处理列表时,常常有删除一条数据或者新增数据之后需要重新刷新当前页面的需求. 2.遇到的问题 1. 用vue-router重新路由到当前页面,页面是不进行刷新的 2.采用window.reload(),或者router.go(0)刷新时,整个浏览器进行了重新加载,闪烁,体验不好 3.解决方法 provide / inject组合 作用:允许一个祖先组件向其所有子孙后代注入一个依赖,不论组件层次有多深,并在起上下游关系成立的时间里始终生效. App.vue: 声明reload方法,控制r

  • Vue实现父子组件页面刷新的几种常用方法

    目录 1.原地页面重新加载(不推荐) 2.空白页面作为过渡 3.使用Provide / Inject组合控制显示 4.v-on:param父组件监听子组件事件 参考文档: 很多时候我们在操作过页面时候,特别是增删改操作之后,数据会有所改变,这个时候我们希望返回的界面中的数据要和数据库中的数据进行同步,就需要刷新当前页面,如果是使用ajax可以使用异步请求实现页面的局部刷新,Vue常用的几种刷新页面方法如下: 1.原地页面重新加载(不推荐) this.$router.go(0) //根据路由重新定

  • 详解Vue之父子组件传值

    一.简要介绍 父子组件之间的传值主要有三种:传递数值.传递方法.传递对象,主要是靠子组件的 props 属性来接收传值,下面分别介绍: (一)传递数值 1.子组件:Header.vue <template> <div> <!-- data对象里并没有 msg 属性,这里调用的是父类传递过来的 msg 属性 --> <h2>{{msg}}</h2> </div> </template> <script> expo

  • vue.js父子组件通信动态绑定的实例

    如下所示: <!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8"> <title></title> </head> <body> <div id='app'> <!--这里的作用是将父组件渲染到页面上--> <father></father> </d

  • vue缓存的keepalive页面刷新数据的方法

    用到这个的业务场景是这样的: a页面点击新建列表按钮进入到新建的页面b,填写b页面并点击b页面确认添加按钮,把这些数据带到a页面,填充到列表(数组),可以添加多条, 点击这条的时候进入到编辑页面,确认修改之后,回退到a页面,a页面需要更新这条数据 实现这个功能的时候,由于是路由页面之间的跳转,首先想到的方案有几个:1. 用sessionStorage本地存储:2. 用路由参数带过去:3. 用兄弟组件传值 由于是添加完之后如果按回退是需要退出整个页面,如果用路由跳转,会出现回退到编辑页面了,所以这

  • Vue.js 父子组件通信的十种方式

    面试官:Vue 中父子组件通信有哪些方式? 自己先想一分钟. 无可否认,现在无论大厂还是小厂都已经用上了Vue.js 框架,简单易上手不说,教程详尽,社区活跃,第三方套件还多.真的是前端开发人员必备技能.而且在面试当中也往往会问到关于 Vue 方面的各种问题,其中大部分面试官会问到如上这种问题. 最近一直在做 Vue项目代码层面上的优化,说实话,优化别人的代码真是件痛苦的事情,功能实现尚且不说,就说代码规范我就能再写出一篇文章来.真的是无规范不成方圆,规范这个东西太重要了!有点扯了,回到主题,咳

  • vue同步父子组件和异步父子组件的生命周期顺序问题

    关于vue组件的引入方式有两种 一. 同步引入 例子: import Page from '@/components/page' 二.异步引入 例子:const Page = () => import('@/components/page') 或者: const Page = resolve => require(['@/components/page'], page) 两种引入方式的不同之处在于: 同步引入时生命周期顺序为:父组件的beforeMount.created.beforeMoun

  • vue实现父子组件之间的通信以及兄弟组件的通信功能示例

    本文实例讲述了vue实现父子组件之间的通信以及兄弟组件的通信功能.分享给大家供大家参考,具体如下: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>www.jb51.net vue父子组件通信.兄弟组件通信</title> <style> *{ margin: 0; padding: 0; l

  • Vue 父子组件数据传递的四种方式( inheritAttrs + $attrs + $listeners)

    当我们在书写 vue 组件的时候,也许可能会用到数据传递:将父组件的数据传递给子组件,有时候也需要通过子组件去事件去触发父组件的事件: 每当我们遇到这样的需求的时候,我们总是会想到有三种解决办法: 通过 props 的方式向子组件传递(父子组件) vuex 进行状态管理(父子组件和非父子组件) vuex 非父子组件的通信传递 Vue Event Bus ,使用Vue的实例,实现事件的监听和发布,实现组件之间的传递. 后来再逛社区的时候我又发现了还有第四种传递方式, inheritAttrs +

  • vue非父子组件通信问题及解决方法

    问题描述: 最近在做登录部分时遇到一个场景,当点击 "用户"按钮时,首先渲染login组件,在用户登录后直接跳转到用户信息界面(user组件).这里遇到了需要将login组件通过异步请求获得的用户信息传向 user组件,但是login和login组件不是父子组件,就暂称为兄弟组件吧. 简而言之,我要解决的就是兄弟组件之间的信息传递问题. //位于login.vue 中 export default { methods:{ login(){ this.$axios({ method: '

  • 解决vue this.$forceUpdate() 处理页面刷新问题(v-for循环值刷新等)

    问题描述: 在使用Vue框架开发时,在函数中改变了页面中的某个值,在函数中查看是修改成功了,但在页面中没有及时刷新改变后的值: 解决: 运用 this.$forceUpdate()强制刷新 代码案例 <Select v-model="carSafeLine.insuranceName" placeholder="请选择" class="mulisel option-h" filterable clearable :disabled=&quo

随机推荐

其他