【问题标题】:receiving data from parent component vue.js: prop being mutated,从父组件 vue.js 接收数据:prop 正在变异,
【发布时间】:2019-09-09 13:31:29
【问题描述】:

我在控制台中有一个错误提示:

相反,使用基于道具值的数据或计算属性。 正在变异的道具:“sortType”

我的根文件包含一个 api 和一个过滤器函数。我正在将该数据发送到组件。一切都很好,直到我在 filterList() 中添加了一些排序。

这就是我收到sortType 的方式:

<div id="toprow">
       // slider codes...
        <select id="sortBox" v-model="sortData" v-on:change="filterList">
            <option value="">sorting</option>
            <option value="price">cheapest</option>
            <option value="created_at">newest</option>
        </select>
</div>


props:["filterList", "slider", "sliderX", "sortType"],
components: {
    vueSlider,
},
data() {
    return {
        sortData: this.sortType
    }
},
methods: {
    filterList(newType){
        this.$emit('update:type', newType)
    }
}

下面是我的根文件...

<app-toprow v-on:update:type="sortType = $event" :filterList="filterList" :slider="slider" :sliderX="sliderX" :sortType="sortType"></app-toprow>


data(){
    return {
        api: [],
        sortType:"",
    }
},
mounted(){
    axios.get("ajax").then(response => {
        this.api = response.data
    })
},
methods: {

},
computed: {
    filterList: function () {
        let filteredStates = this.api.filter((estate) => {
            return (this.keyword.length === 0 || estate.address.includes(this.keyword)) &&
            (this.rooms.length === 0 || this.rooms.includes(estate.rooms)) &&
            (this.regions.length === 0 || this.regions.includes(estate.region))});

            if(this.sortType == 'price') {
                filteredStates = filteredStates.sort((prev, curr) => prev.price - curr.price);
            }
            if(this.sortType == 'created_at') {
                filteredStates = filteredStates.sort((prev, curr) => Date.parse(curr.created_at) - Date.parse(prev.created_at));
            }

            return filteredStates;
    },
}
}

好的,我收到 sortType 时是不是做错了什么?

【问题讨论】:

    标签: javascript vue.js vuejs2


    【解决方案1】:

    您将 sortType 作为 prop 传递给子组件,同时在 select 中使用 v-model 对其进行变异,从而收到此错误。

    你的子组件应该是这样的:

    <div id="toprow">
    // slider codes...
        <select id="sortBox" v-model="selectedSort" v-on:change="filterList">
            <option value="">sorting</option>
            <option value="price">cheapest</option>
            <option value="created_at">newest</option>
         </select>
    </div>
    
    
    export default {
        data() => ({
            selectedSort: this.sortType
        })
        props:["filterList", "slider", "sliderX", "sortType"],
        components: {
            vueSlider,
        },
        methods: {
            filterList(newType){
                this.$emit('update:type', newType)
            }
        }
    }
    

    现在在v-on:change=filterList 上,您应该在父级上发出一个自定义事件,通知他排序已更改。

    在父级上是这样的:

    <app-toprow v-on:update:type="sortType = $event" :filterList="filterList" :slider="slider" :sliderX="sliderX" :sortType="sortType"></app-toprow>
    

    相关的 SO 问题:https://stackoverflow.com/a/51722100/7482509 相关文档:https://vuejs.org/v2/guide/components-custom-events.htmlhttps://vuejs.org/v2/guide/components-props.html#One-Way-Data-Flow

    【讨论】:

    • 感谢您的回答。我在这里唯一不明白的。这部分。 filterList(newType){ this.$emit('update:type', newType) } 我应该在哪里插入我的 filterList() ?
    • 你为什么不把那个sn-p放到export default { ... }下面components:下面?
    • 你的意思是在子组件中创建一个computed: { 并在里面使用那个sn-p?但我已经在使用 filterList() 并从父级接收 filterList() 。只需检查问题...所以...这没有意义...@AliD。
    • 我更新了我的答案。 filterList 应该进入子组件的方法中。
    • 感谢您的更新。但我已经试过了。您在问题filterList() 中看到的是父母中的功能,我也收到了...这就是为什么当我在孩子中重新创建时。当然我得到错误。我需要父级中的filterList() 来说明我如何进行排序/过滤...这就是我遇到此错误的原因:Method "filterList" has already been defined as a prop. 顺便用最新的代码更新了问题。
    【解决方案2】:

    FIX FOR CLONED[i].apply

    Vue 2 - Uncaught TypeError: cloned[i].apply is not a function at HTMLInputElement.invoker (vue.esm.js?65d7:1810) error

    基本上你应该将道具名称 filterList 更改为其他名称

    新答案

    这是一个更新答案,道具filterList 与我认为是冲突的方法中的名称相同。我也认为您不需要将filterList 方法从父母发送给孩子,因为您已经在通过update:type 收听了

    methods: {
        filterList(event){
            // use the v-model reactive feature..
            this.$emit('update:type', this.sortData)
            // if you don't like this.sortData -> uncomment below
            // this.$emit('update:type', event.target.value)
        }
    }
    

    为什么不使用mounted() 来初始化sortData: this.sortType...

    data() {
        return {
            sortData: null
        }
    },
    mounted() {
      this.sortData = this.sortType
    }
    

    附言

    只是我的理论... 我无法清楚地解释为什么会发生这种情况,但我确实认为这是因为 vue 是响应式的,所有数据值都不应该直接来自 prop 的值。因为如果您考虑它是否来自道具 DIRECTLY 进行编辑,它也应该编辑道具..

    但我真的不知道为什么会这样,最好下次再问。

    【讨论】:

    • 我也在像 this.sortData = this.sortType 这样的挂载钩子中尝试过,但出现了这个错误。 cloned[i].apply is not a function 顺便假设 : 是您安装的代码中的语法错误
    • 抱歉语法错误...但是您在哪里打电话给cloned[i].apply
    • 我确实需要发送filterList(),因为在其中filterList() 不仅sortType 还有其他过滤器,我希望所有过滤器都连接。这就是发送它的原因...例如我的滑块过滤器工作正常...但我的 sortType 没有运行...
    • 顺便说一句。 filterList() 也包含 sortType 过滤器。如果您仔细观察...
    • 我想建议安装 vue-devtools (浏览器扩展) 以便更好地调试.. ;)
    【解决方案3】:

    选择选项是否没有默认值(页面加载时该值始终为sorting)?如果是,则不必使用 v-model

    如果它有默认值,尝试使用:value而不是v-model,并使用props sortType作为值。

    您也不能在filterList 上使用相同的名称,请尝试为函数使用不同的变量。

    <div id="toprow">
           // slider codes...
            <select id="sortBox" :value="sortType" v-on:change="change">
                <option value="">sorting</option>
                <option value="price">cheapest</option>
                <option value="created_at">newest</option>
            </select>
    </div>
    
    

    关于改变功能

    export default {
        methods: {
            change(e){
                this.$emit('update:type', e.target.value)
            }
        }
    }
    

    在你的父组件上

    <app-toprow v-on:update:type="sortType = $event" :filterList="filterList" :slider="slider" :sliderX="sliderX" :sortType="sortType"></app-toprow>
    

    【讨论】:

    • 这是最好的答案。太感谢了。它现在就像魔术一样工作。我不明白的事情。 change() 如何知道数据并与 filterList() 交互,因为我的过滤器代码位于父级的 filterList() 中。但是 change() 函数知道这一点并与之交互。虽然我没有像以前那样在select 中提到filterList()...
    • 不客气! ?。当您更改选择选项时,它将触发change 方法,然后change 方法将值传递/发射给父级。它修改了sortType 变量。由于sortType变量用于filterList,而filterList是一个计算属性,当该属性中使用的任何变量发生变化时,计算属性都会触发
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-02-04
    • 1970-01-01
    • 2019-12-09
    • 1970-01-01
    • 2022-11-23
    相关资源
    最近更新 更多