【问题标题】:DOM is not updating when props value changes in Vuejs当 Vuejs 中的 props 值更改时,DOM 不会更新
【发布时间】:2018-10-06 17:19:10
【问题描述】:

我有一个父母和一个孩子。在父母中,我将 3 个变量作为道具传递给孩子。在孩子中,我使用 watch() 来寻找可变的变化。当孩子第一次被创建时,watch 会按预期工作,但是当来自 props 的数据更新时,孩子的 DOM 不会更新。正在寻找变量数据变化的 watch 函数根本没有运行。

这是我的代码。篇幅有点长,请多多包涵。

父组件.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>

子组件 CategoryItems.vue 在下面

<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>

正如您所见,只要子项中的 category 变量更改了函数 GetProducts 应该运行但它没有发生。 仅在创建子组件时执行。

我的逻辑哪里出错了。 谢谢

【问题讨论】:

  • 道具的名字是catsgory。道具:['gender','catsgory','catlog'],

标签: vue.js vuejs2 vue-component


【解决方案1】:

您只是在 created 挂钩中设置子组件的变量,因此它们不是反应式的。

最好的方法是基于该属性创建一个响应式数据是基于该属性创建一个computed property

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

只要 props 发生变化,这个计算值就会自动更新。

你也可以直接watch prop,强制watcher立即触发(看the API)。

您的子组件的观察者将如下所示:

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

【讨论】:

  • 非常感谢!我有 2 个问题 Q1-您说在创建的钩子中设置子组件的变量不会使它们反应。那么让他们反应的理想方法是什么,所以我将来不会遇到这个问题。 Q2- 在我的子组件中,它是初始化数据的好方法吗? data(){ return { genders : this.gender, category : this.catsgory, catalog : this.catlog } },
  • Q1 : 你应该基于 props 创建一个计算属性,或者直接使用 props(记住你不应该直接修改 props)。 Q2:不,参见 Q1。我正在更新答案。
  • codepen.io/handsomer223/pen/BxLjej 我尝试使用计算属性来实现相同的结果。我做对了。
  • 这个计算属性完全没有任何作用。道具反应性的,你不需要将它们包装在一个计算属性中
【解决方案2】:

在我的例子中,如果初始 props value(array) 是 undefind,即使 props 发生变化,渲染也不会被触发。

所以我将初始道具值更改为空数组[]

那么问题就解决了。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-07-25
    • 2019-09-30
    • 2021-05-21
    • 1970-01-01
    • 2018-08-04
    • 2021-10-03
    • 2019-11-03
    • 1970-01-01
    相关资源
    最近更新 更多