本文介绍了当 Vuejs 中的 props 值发生变化时,DOM 不会更新的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

这是我的代码.有点长,请耐心看完.

Parentcomponent.vue

 <div><button type="button" v-on:click="LoadCatalog()">点击我!!<div v-if="displayCategoryList" class="row"><h3>选择类别男士</h3><select v-model="menCategory" v-on:change="passDataToChild()"><option v-for="item in categoryfordisplay.men" v-bind:key="item">{{ 物品 }}</选项></选择><h3>选择类别女性</h3><select v-model="WomenCategory" v-on:change="passDataToChild()"><option v-for="item in categoryfordisplay.women" v-bind:key="item">{{ 物品 }}</选项></选择>

<div v-if="displayData" class="row"><div v-for="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>

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

</模板><脚本>从 'axios' 导入 axios从'./CategoryItems'导入CategoryItems导出默认{name: 'GetCategoryItemsAndDisplayOne',道具:['categoriesfordisplay','ismainpage','catalogselected'],成分:{类别项目,},数据(){返回 {IsMainPage_1 : "",data_to_show_on_mainpage : [],猫 :[],显示数据:真,男士类别:"",女性类别 : "",displayCategoryList: 真,displayCategoryData : false,CategoryFromImage : "",//dataSentToChild : {}性别 : "",猫科动物:",目录:"}},方法:{passDataToChild(){if(this.menCategory != ""){this.catsgory = this.menCategorythis.gender = "男人"this.catlog = this.catalogselectedthis.menCategory = ""}else if(this.WomenCategory != ""){this.catsgory = this.WomenCategorythis.gender = "女性"this.catlog = this.catalogselectedthis.WomenCategory = ""}this.displayData = falsethis.displayCategoryData = true},更改值(){this.data_to_show_on_mainpage = []},CatlogService(catlog_name,category,gender,mainpage){让 url = "http://localhost:5000/xyz/" + (this.catalogselected).replace(/'/g,"%27") +"/api/"+ (gender) + "/catalogvis/"+(类别)+"/items"axios.get(encodeURI(url)).then((resp)=>{var jsonData = {"data": resp.data.response.Results.results[0], "cat": category, "gender": 性别})this.data_to_show_on_mainpage.push(jsonData)}).catch(错误 => {console.log("我们得到一个错误,网址是" + url)控制台日志(错误);})},GetItemsToShowonMainPage(){this.changevalue()如果(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");控制台日志(类别)this.CatlogService(this.catalogselected,category,'men',this.ismainpage)}}如果(this.categoriesfordisplay.women_for_display.length>0){for(让我= 0;我<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)}}},加载目录(){this.displayCategoryData = falsethis.GetItemsToShowonMainPage()this.displayData = 真this.displayCategoryList = true},新功能(猫,性别){this.displayCategoryData = truethis.displayData = falsethis.catsgory = 猫this.gender = 性别this.catlog = this.catalogselected}},创建(){this.GetItemsToShowonMainPage()}}<风格></风格>

子组件 CategoryItems.vue 在下面

<div><h4>{{ 性别 }}</h4><h4>{{ 类别 }}</h4><h4>{{目录}}</h4>

</模板><脚本>导出默认{name : 'CategoryItems',道具 : ['性别','catsgory','catlog'],数据(){返回 {性别:"",类别 : "",目录 : "",}},手表 : {类别:函数(){this.GetProducts()}},方法:{获取产品(){this.genders = this.genderthis.category = this.catsgorythis.catalogue = this.catlog}},创建(){this.genders = this.genderthis.category = this.catsgorythis.catalogue = this.catlog}}<风格></风格>

正如您所看到的,每当子项中的 category 变量发生变化时,GetProducts 函数都应该运行,但它没有发生.仅在创建子组件时执行.

我的逻辑哪里出了问题.谢谢

解决方案

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

最好的方法是基于 prop 创建一个响应式数据是创建一个 基于该属性的计算属性:

计算:{类别:函数(){返回 this.catsgory;},},

每当道具改变时,这个计算将自动更新.

也可以直接看prop,强制立即触发watcher(看API).

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

观看:{类别: {处理程序:函数(){this.GetProducts();},立即:真实,},},

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

这篇关于当 Vuejs 中的 props 值发生变化时,DOM 不会更新的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-21 15:00