道具更改时子组件不会更新

Posted

技术标签:

【中文标题】道具更改时子组件不会更新【英文标题】:Child component doesn't get updated when props changes 【发布时间】:2018-08-09 01:18:42 【问题描述】:

我无法理解 vue js 的反应性如何工作。我正在尝试为各种 ajax 调用制作一个组件,问题是当我更改要传递给组件的道具时,它不会得到数据的更改。

https://jsfiddle.net/8t4vx44r/34/

Vue.component('api-call-template', 
	template: '#api-call-templates',
	props: 
      apiCallParams: Object
    ,
  data () 
    return 
      result: [],
      loading: false
    
  ,
  created() 
  	console.log("entered?")
    console.log(this.apiCallParams);
      var vm = this;
      vm.loading = true;
      axios(
         method: this.apiCallParams.method,
         url: this.apiCallParams.url,
         data: this.apiCallParams.params
       ).then(function(response) 
        vm.result = response.data;
        vm.loading = false;
        vm.$emit('get-response', response);
      );
       console.log(vm.loading)

);

var vm = new Vue(
	el: '#app',
	data: 
		apiCallParams: 
      url: '',
      method: '',
      params: 
    ,
    author: 'aa'
	,
  created() 
  	this.apiCallParams.url = 'https://reqres.in/api/users/1';
  	this.apiCallParams.method = 'get';
    console.log("passing this");
    console.log(this.apiCallParams);
  ,
  methods: 
    search() 
    console.log("searching")
		this.url = 'https://reqres.in/api/users/2';
  	this.apiCallParams.method = 'get';
    ,
    getResponse(response) 
    	console.log("back to parent");
    	console.log(response);
    
  
);
<script src="https://unpkg.com/axios@0.18.0/dist/axios.min.js"></script>
<script src="https://unpkg.com/vue@2.5.13/dist/vue.js"></script>
<div id="app">
try title
  <post :title="title" :author="author" :content="content">
   
  </post>
</div>

<template id="post-template">
	<h1> title </h1>
	<h4> author </h4>
	<p> content </p>
</template>

如果您单击“下一个用户按钮”,它会更新父组件中的数据,但不会调用我的 api-call-template。

【问题讨论】:

【参考方案1】:

您只调用一次,因为您的逻辑位于created(),它只被调用一次(在创建组件时)。

考虑到您的组件是:

<api-call-template :api-call-params="apiCallParams" @get-response="getResponse">...

并且您想在每次api-call-params 更改时请求。你可以做的是:

将您的逻辑从created() 移动到一个方法,例如performRequest() 致电this.performRequest()created()apiCallParams prop 添加观察者 在apiCallParams观察者上致电this.performRequest()

请看下面的演示。

Vue.component('api-call-template', 
  template: '#api-call-templates',
  props: 
    apiCallParams: Object
  ,
  data() 
    return 
      result: [],
      loading: false
    
  ,
  methods: 
    performRequest() 
      console.log("entered?")
      console.log(this.apiCallParams);
      var vm = this;
      vm.loading = true;
      axios(
        method: this.apiCallParams.method,
        url: this.apiCallParams.url,
        data: this.apiCallParams.params
      ).then(function(response) 
        vm.result = response.data;
        vm.loading = false;
        vm.$emit('get-response', response);
      );
      console.log(vm.loading)
    
  ,
  created() 
    this.performRequest();
  ,
  watch: 
    apiCallParams() 
      this.performRequest();
    
  
);

var vm = new Vue(
  el: '#app',
  data: 
    apiCallParams: 
      url: '',
      method: '',
      params: 
    
  ,
  created() 
    this.apiCallParams = url: 'https://reqres.in/api/users/1', method: 'get'
    console.log("passing this");
    console.log(this.apiCallParams);
  ,
  methods: 
    search() 
      console.log("searching")
      this.apiCallParams = url: 'https://reqres.in/api/users/2', method: 'get';
    ,
    getResponse(response) 
      console.log("back to parent");
      console.log(response);
    
  
);
<script src="https://unpkg.com/axios@0.18.0/dist/axios.min.js"></script>
<script src="https://unpkg.com/vue@2.5.13/dist/vue.js"></script>

<div id="app">
  <button @click="search">next user</button>
  <api-call-template :api-call-params="apiCallParams" @get-response="getResponse"></api-call-template>
</div>

<template id="api-call-templates">
  <div>
    <main>
      <div v-if="loading">loading</div>
      <div class="wrapper">
        <div class="row">
          <div v-for="res in result" :key="res.id">
            <div class="col-md-4 cards">
              <div>
                results
                <h3> res.first_name </h3>
              </div>
            </div>
          </div>
        </div>
      </div>
    </main>
  </div>
</template>

只有一个警告:可以触发手表,立即更改apiCallParams,例如:

this.apiCallParams = url: 'https://reqres.in/api/users/2', method: 'get';

不是逐个属性,例如:

this.apiCallParams.url = 'https://reqres.in/api/users/2';      // don't do like this
this.apiCallParams.method = 'get';                             // don't do like this

因为如果你逐个属性地做,Vue 不会接受更改。

【讨论】:

以上是关于道具更改时子组件不会更新的主要内容,如果未能解决你的问题,请参考以下文章

高阶组件状态正在正确更新,但接收道具的包装组件不会在状态更改时重新渲染

在 React 中通过更改父级的道具来更新子组件

Vue cli 3道具(父到子)子在父变量更改后永远不会更新

VueJS 在不更改父数据的情况下编辑道具的正确方法

组件道具未在状态更改时更新

子状态更改时子不重新渲染