当我在 Vue JS 中按下父组件上的按钮时如何刷新子组件?
Posted
技术标签:
【中文标题】当我在 Vue JS 中按下父组件上的按钮时如何刷新子组件?【英文标题】:How to refresh Child component when i pressed a button on Parent Component in Vue JS? 【发布时间】:2018-03-06 04:46:13 【问题描述】:我有一个设置选项,它将从父组件更新。我将这些设置数据保存在 localStorage 中,这三个子组件正在使用设置数据。
<P>
<c1> </c1>
<c2> </c2>
<c3> </c3>
</P>
我想要一种方式,当我更新我的设置数据时,三个组件将刷新或更新以获得新值。 就像,我将按下父组件上的一个按钮,三个子组件将被更新。
------------ 已更新 ---------- --------
模板部分:
<template>
<div class="main-content">
<div class="main">
<!-- COMPONENT -->
<div class="row">
<div class="padpad">
<div class="col-md-6">
<app-colma></app-colma>
</div>
<div class="col-md-3">
<app-colmb></app-colmb>
</div>
</div>
</div>
<!-- SAVE BUTTON -->
<button type="submit" class="btn btn-success" data-dismiss="modal" aria-label="Close" v-on:click="onSubmit()"><span>Save</span></button>
<!-- DATA FORM ( SELECT, OPTION) -->
<div class="container modal-body">
<div class="col-xs-12 col-md-3">
<h4>Sortierung</h4>
<div class="radio">
<label><input value="theropeut" type="radio" name="filterop">Theropeut</label>
</div>
<div class="radio">
<label><input value="ausl_perf" type="radio" name="filterop">Ausl Perf</label>
</div>
<div class="radio">
<label><input value="ausl_bud" type="radio" name="filterop">Ausl Bud</label>
</div>
<div class="radio">
<label><input value="umsatz" type="radio" name="filterop">Umsatz</label>
</div>
<div class="order-select">
<select id="orderid" class="form-control">
<option value="ascending">Ascending</option>
<option value="descending">Descending</option>
</select>
</div>
</div>
</div>
</div>
</template>
脚本代码:
<script>
import ColmA from './ColmA.vue';
import ColmB from './ColmB.vue';
import ColmTotal from './ColmTotal.vue';
export default
components:
'app-colma': ColmA,
'app-colmb': ColmB,
'app-colmtotal': ColmTotal
,
name: 'main-content',
data()
return
users: [],
filtr:'',
order:''
,
methods:
onSubmit: function()
// console.log("onsubmit");
//filter
var filterop = document.getElementsByName('filterop');
for (var i = 0, length = filterop.length; i < length; i++)
if (filterop[i].checked)
// do whatever you want with the checked radio
// alert(filterop[i].value);
this.filtr = filterop[i].value;
// only one radio can be logically checked, don't check the rest
break;
//order
var e = document.getElementById("orderid");
this.order = e.options[e.selectedIndex].value;
var homesetting =
filter: this.filtr,
order:this.order,
;
if (localStorage.getItem('homesetting') === null)
var homesettings = [];
// homesettings.push(homesetting);
localStorage.setItem('homesetting', JSON.stringify(homesetting));
else
localStorage.removeItem('homesetting');
localStorage.setItem('homesetting', JSON.stringify(homesetting));
;
,
created: function ()
this.fetchData();
</script>
组件代码:
<script>
export default
name: 'colma',
data ()
return
title: 'A Area',
colmAdata:[]
,
methods:
fetchData: function ()
var self = this;
var homeObject = JSON.parse(localStorage.getItem('homesetting'));
// console.log('retrievedObject: ', retrievedObject.filter);
var filter= homeObject.filter;
var order= homeObject.order;
// HERE I NEED MY TWO UPDATED VARIABLES
var a = 'http://localhost:3000/'+'_'+filter+'_'+order;
console.log('A',a);
$.get(apiURL, function (data)
self.colmAdata = data;
// self.$store.state.storeGdata = ' store data from content';
// console.log(data.people[0].name);
);
,
created: function ()
this.fetchData();
</script>
【问题讨论】:
你试过什么?你在哪里研究过? 【参考方案1】:解决此问题的一种方法是从子组件发出自定义事件(如果更改源自子组件),然后在调用方法的父组件中捕获/侦听此事件。然后可以使用此方法调用将更新值的子方法。
真正的问题是,为什么需要这样做?假设父组件是事实的来源(即将数据作为 props 传递给子组件),那么您只需要观察这些 props 的变化,或者使用计算的 props 来获取更新的值。根本不需要使用事件来调用方法。
基本上,你的作案手法可以是:
将父值(存储在父数据中)作为道具传递给子组件。子组件将响应式更新其继承的属性。
家长的设置也可以同时存储到localStorage
。这可以通过简单地使用watch
监视父数据的变化来完成。在这种情况下,您可以在重新挂载父级时(例如重新加载页面时)再次从localStorage
中读取—使用mounted
lifecycle hook。根据第 1 点,这些更改将再次传播到子组件。
一个概念验证示例(要使 localStorage 功能正常工作,please check this fiddle,因为代码 sn-ps 是沙盒化的):
Vue.component('child-component-a',
template: '<div><h2>Child component A</h2><p>I multiply inherited parent value by 2: <strong> computedNumber </strong></p></div>',
props:
number:
type: Number
,
computed:
computedNumber()
return this.number * 2;
);
Vue.component('child-component-b',
template: '<div><h2>Child component B</h2><p>I divide inherited parent value by 16: <strong> computedNumber </strong></p></div>',
props:
number:
type: Number
,
computed:
computedNumber()
return this.number / 16;
);
var app = new Vue(
el: '#app',
data:
parentNumber: 1024
,
watch:
parentNumber()
// Store parent number in localStorage when updated
// *NOTE: Disabled in this code snippet since it is sandboxed
// localStorage.setItem('parentNumber', this.parentNumber);
,
mounted()
// Overwrite parent data if localStorage is found
// *NOTE: Disabled in this code snippet since it is sandboxed
// if (localStorage.getItem('parentNumber') !== null)
// this.parentNumber = localStorage.getItem('parentNumber');
//
);
html
font-family: Arial, sans-serif;
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.4.4/vue.min.js"></script>
<div id="app">
<div>
<h1>Parent component</h1>
<p>I have a value of <strong> parentNumber </strong>.</p>
<p>But wait, you can change my number!</p>
<input v-model="parentNumber" type="number" />
</div>
<child-component-a v-bind:number="parentNumber"></child-component-a>
<child-component-b v-bind:number="parentNumber"></child-component-b>
</div>
【讨论】:
我同意。存储在本地存储和从本地存储读取不是传播更改的方式。 我需要将这些设置数据保存在本地存储中。所以我认为这个程序行不通。 @Terry 知道了,让我试试这个。 @Sharat 我添加了一个概念验证代码 sn-p。请注意,localStorage 功能将无法使用,因为它已被沙盒化。 @Terry,我无法将您的代码 sn-p 用于我的项目。你能检查我更新的问题吗?现在根据我的项目结构给我一些建议。 :)【参考方案2】:如果你使用 Vue.JS,你应该真的只使用 Vue.JS - 父级应该有一个模型,其中包含你的设置作为反应数据。然后你把这个属性作为 properties 传递给你的组件,组件只在属性上定义一个 watcher。
var localStore = reason: 'Fake, because no localStorage in Sandbox' ;
Vue.component('rows',
props: ["order"],
data: function() return values: [] ,
template: `<ul><li v-for="v in values">v</li></ul>`,
created: function() this.fetchValues() ,
watch: order: function() this.fetchValues() ,
methods: fetchValues: function()
/* Placeholder for an ajax-call with order as a parameter */
this.values = ( this.order == 'ascending' ) ? [1,2,3] : [3,2,1]
)
new Vue(
el: '#main',
data: order: 'ascending' ,
created: function()
if ( localStore.order )
this.order = localStore.order;
,
watch: order: function()
/* Save any change on order in the local storage */
localStore.order = this.order;
)
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.4.4/vue.js"></script>
<div id="main">
<select v-model="order">
<option value="ascending">Sort Ascending</option>
<option value="descending">Sort Descending</option>
</select>
<rows :order="order"></rows>
</div>
【讨论】:
以上是关于当我在 Vue JS 中按下父组件上的按钮时如何刷新子组件?的主要内容,如果未能解决你的问题,请参考以下文章
当我在模拟器中按下 Apple TV 游戏手柄按钮时,它们不会触发
当我在颤动中按下按钮时,如何将 Card 小部件替换为 TextField? [关闭]