当 Vuejs 中的 props 值更改时,DOM 不会更新

I have a parent and a child. In the parent am passing 3 variables as props to the child. In the Child I am using the watch() to look for varaible changes. When the child is created for the 1st time the watch works as expected but when the data from the props in updated then DOM of the child is not updated. The watch function which is looking for data change of the variable is not running at all.

Here is my code. Its a bit lengthy so please bear with it.

Parentcomponent.vue

 <template>
 <div>


 <button type="button" v-on:click="LoadCatalog()">Click me!! </button>

 <div v-if="displayCategoryList" class="row">
    <h3>Select Category Men</h3>
    <select v-model="menCategory" v-on:change="passDataToChild()">
        <option v-for="item in categoriesfordisplay.men"  v-bind:key="item">
            {{ item }}
        </option>
    </select> 
    <h3>Select Category Women</h3>
    <select v-model="WomenCategory" v-on:change="passDataToChild()">
        <option v-for="item in categoriesfordisplay.women" v-bind:key="item">
            {{ item }}
        </option>
    </select> 
 </div>

 <div v-if="displayData" class="row">

        <div v-for="item in data_to_show_on_mainpage"  v-bind:key="item" >
            <button v-on:click="newfunction(item.cat,item.gender)" >
                <img v-bind:src="item.data.image"> </img>
                <p >{{ item.cat }}</p>
            </button>
         </div>



 </div>

 <category-items v-if="displayCategoryData" v-bind:gender="gender" v-bind:catsgory="catsgory" v-bind:catlog="catlog" ></category-items>





 </div>
 </template>


<script>
  import axios from 'axios'
  import CategoryItems from './CategoryItems'
   export default {
   name:  'GetCategoryItemsAndDisplayOne',
   props: ['categoriesfordisplay','ismainpage', 'catalogselected'],

components:{
    CategoryItems,
    },
    data(){
    return {
        IsMainPage_1 : "",
        data_to_show_on_mainpage : [],
        cat :[],
        displayData : true,
        menCategory : "",
        WomenCategory : "",
        displayCategoryList: true,
        displayCategoryData : false,
        CategoryFromImage : "",
        //dataSentToChild : {}
        gender : "",
        catsgory : "",
        catlog : ""


    }
  },
     methods:{
    passDataToChild(){
        if(this.menCategory != ""){

            this.catsgory = this.menCategory
            this.gender = "men"
            this.catlog = this.catalogselected
            this.menCategory = "" 

        }else if(this.WomenCategory != ""){
            this.catsgory = this.WomenCategory
            this.gender = "women"
            this.catlog = this.catalogselected
            this.WomenCategory = ""
        } 
        this.displayData = false
        this.displayCategoryData = true
    },
    changevalue(){
        this.data_to_show_on_mainpage = []
    },
    CatlogService(catlog_name,category,gender,mainpage){


        let url = "http://localhost:5000/xyz/" + (this.catalogselected).replace(/'/g,"%27") +"/api/"+ (gender) + "/catalogvis/" + (category) +"/items"

        axios.get(encodeURI(url)).then((resp)=>{
            var jsonData = {"data": resp.data.response.Results.results[0] , "cat": category , "gender" : gender}
            )
            this.data_to_show_on_mainpage.push(jsonData)

        })
        .catch(err => {
            console.log("we got an error the url is " + url)
            console.log(err);
        })
    },

    GetItemsToShowonMainPage(){
        this.changevalue()


        if(this.categoriesfordisplay.men_for_display.length>0){
            for(let i =0;i<this.categoriesfordisplay.men_for_display.length;i++){
                let category = this.categoriesfordisplay.men_for_display[i].replace(/"/g,"%27");
                console.log(category)
                this.CatlogService(this.catalogselected,category,'men',this.ismainpage)
            }

        }
        if(this.categoriesfordisplay.women_for_display.length>0){

            for(let i = 0;i<this.categoriesfordisplay.women_for_display.length;i++){
                let category = this.categoriesfordisplay.women_for_display[i].replace(/"/g,"");

                this.CatlogService(this.catalogselected,category,'women',this.ismainpage)
            }

        }
    },
    LoadCatalog(){
        this.displayCategoryData = false
        this.GetItemsToShowonMainPage()
        this.displayData = true
        this.displayCategoryList = true

    },
    newfunction(Cats,gender){
        this.displayCategoryData = true
        this.displayData = false
        this.catsgory = Cats
        this.gender = gender
        this.catlog = this.catalogselected
    }



},
created(){

    this.GetItemsToShowonMainPage()
}



}
</script>

<style>

</style>

The Child component CategoryItems.vue is below

<template>

<div>
    <h4>{{ genders }}</h4>
    <h4>{{ category }}</h4>
    <h4>{{ catalogue }}</h4>
</div>
</template>


<script>


export default{
name : 'CategoryItems',
props : ['gender','catsgory','catlog'],



data(){
    return {
        genders : "",
        category : "",
        catalogue : "",

    }
},
watch : {
    category : function(){

        this.GetProducts()
    }
},
methods:{
    GetProducts(){
    this.genders = this.gender
    this.category = this.catsgory
    this.catalogue = this.catlog

    }
},
created(){
    this.genders = this.gender
    this.category = this.catsgory
    this.catalogue = this.catlog


 }

 }
 </script>


 <style>
 </style>

As You can see whenever the category variable in the child changes the function GetProducts should run but it is not happening. It is executed only when the child component is created.

Where I am going wrong with my logic. Thanks

解决方案

You are only setting the child component's variable in the created hook, therefor they are not reactive.

The best way is to make a reactive data based on the prop is to create a computed property based on that property :

computed: {
  category: function() {
    return this.catsgory;
  },
},

This computed will be automatically updated whenever the props changes.

You also can watch the prop directly, and force the watcher to trigger immediately (take a look at the the API).

Your child component's watcher will look like this :

watch : {
  category: {
    handler: function() {
        this.GetProducts();
    },
    immediate: true,
  },
},

相关文章