简体   繁体   中英

Child component doesn't get updated when props changes

I am having trouble understanding how vue js's reactivity work. I am trying to make a component for all kinds of ajax call, the problem is when I change the props to be passed on to the component it doesn't get the changes in the data.

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>

If you click the "next user button" it updates the data in the parent component but it doesn't call my api-call-template.

You are only calling one time because your logic is at created() , which is called only once (when the component is created).

Considering your component is:

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

And you want to request every time api-call-params changes. What you could do is:

  • Move your logic from created() to a method, say performRequest()
  • Call this.performRequest() on created()
  • Add a watcher to apiCallParams prop
  • Call this.performRequest() on apiCallParams watcher

See demo below.

 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>

There is only one caveat: to trigger the watch, change apiCallParams at once, like:

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

Not property by property, like:

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

As Vue won't pick up changes if you do it prop by prop.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM