vue child监听parent的prop变化失败

需求

省市区层级菜单自动加载并自动切换

代码

# form.html
<area-three-select v-bind:inits="['1','40','596']"></area-three-select>
#AreaThreeSelect.vue
<template>
    <div class="form-row">
        <SelectItem v-for="(item,index) in items" :key="index" :item="item" :inits.sync="inits"/>
    </div>
</template>

<script>
    import axios from "axios"
    import SelectItem from './SelectItem.vue'

    let nextTodoId = 1;

    export default {
        props: ['inits'],
        components: {
            SelectItem
        },
        data() {
            return {
                items: [
                    {id: "d1", name: "省份"},
                    {id: "d2", name: "地区"},
                    {id: "d3", name: "城市"}
                ]
            }
        },
        mounted() {
            let vm = this;
            this.$root.$on('changed2', (key, val) => {
                vm.inits[key] = val;
                for (let i = key + 1; i < vm.inits.length; i++) {
                    vm.inits[i] = '0';
                }
                console.log('changed2 = ', this.inits)
            })
        }
    }
</script>
# SelectItem.vue
<template>
    <div class="col-md-3 mb-3">
        <label v-bind:for="'link-'+item.id">{{ item.name }}</label>
        <select v-bind:id="'link-'+item.id" v-bind:name="item.id" v-on:change="onChange()" class="custom-select"
                v-model="selected">
            <option v-for="option in options" v-bind:value="option.id">{{ option.name }}</option>
        </select>
    </div>
</template>

<script>
    import axios from "axios"

    export default {
        props: {
            inits: {
                type: Array,
                required: true
            },
            item: {
                type: Object,
                required: true
            }
        },
        data() {
            return {
                selected: '',
                options: []
            }
        },
        methods: {
            onChange(e) {
                this.$root.$emit('changed2', this.$vnode.key, this.selected);
            },
            make() {
                console.log('make ' + this.$vnode.key);
                let pid = -1;
                if (this.$vnode.key === 0) {
                    pid = 0;
                } else if (this.inits.hasOwnProperty(this.$vnode.key - 1) && this.inits[this.$vnode.key - 1] > 0) {
                    pid = this.inits[this.$vnode.key - 1];
                }

                if (pid > -1) {
                    axios.get('/api/area/json/' + pid)
                        .then(resp => {
                            this.options = [{id: "", name: ""}, ...resp.data];
                        })
                        .catch(err => console.log('err => ', err))
                }
            }
        },
        watch: {
            inits: {
                immediate: true,
                handler(val) {
                    console.log('watch inits key = ', this.$vnode.key, val)
                },
                deep: true
            }
        },
        created() {
            this.selected = this.inits[this.$vnode.key];
            this.make();
        }
    }
</script>

问题

运行之后自动定位了加载了层级,但是当父节点传入进来的inits这个prop发生改变之后,省市区的子节(inits[0] inits[1] inits[2] )监听了,但是子节点里没有任何运行(几个子节点,文件SelectItem.vue的watch里面不执行)。

阅读 2.7k
2 个回答

在#AreaThreeSelect.vue 使用 立即监听inits, 回调函数中对 inits 进行手动初始化

试试 this.$set 改变 inits

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题