vue 父子组件数据互相监听问题

父组件有个input文本框 子组件也是很多input框 这是效果图:

clipboard.png

嗯想实现的功能是:

我再父文本框里输入: ?get=1&name=2&name=3能自动在子组件里生成数据

在子文本框里输入 数据能自动填充到父文本框里

clipboard.png

下面代码是简化版本:

父组件

<template>

<input type="text" v-model = "requestUrl">

<component :is = "view" :requestUrl = "requestUrl" @queryString = "queryString"></component>

</template>

<script>
//利用动态组件实现选项卡切换
import formView from './form';
import queryView from './query';
import jsonView from './json';

export default {
   components: {
        formView,
        jsonView,
        queryView,
    },
    data()
    {
        return {
            view: "formView",     //默认组件
            viewIndex:0,         //组件索引
            requestUrl: "",      //接口地址
            //选项卡
            tab: [{
                "name": "Form",
                "view": "formView",
                //表示form下面的二级选项卡
                "options": [{
                    "name": "Form",
                    "view": "formView"
                },{
                    "name": "JSON",
                    "view": "jsonView",
                }, {
                    "name": "XML",
                    "view": "xmlView"
                }]

            }, {
                "name": "Query",
                "view": "queryView",

            }],
        }
    },
    methods: {
        //接受query子组件抛出的事件
        queryString(data)
        {
            var params = '?';

            for(var i = 0; i < data.length; i++) {

                if($.trim(data[i].value)) {

                    params += data[i].key + '=' + data[i].value + '&';

                } else {

                    params += data[i].key + '&';

                }
            }
            this.requestUrl = this.requestUrl.replace(/\?.+/, '') + params
        }
    }
}
</script>

query子组件:

<template>
    <div class = "query">
        <table v-if="data">
            <tr v-for = "val,index in data">
                <td>
                    <input :checked="val.is" type = "checkbox">
                </td>
                <td>
                    <input v-model = "val.key"></input>
                </td>
                
                <td>
                    <input v-model = "val.value"></input>
                </td>
            </tr>
        </table>
    </div>
</template>

<script>
export default {
    props:["requestUrl"],
    data()
    {
        return {
            data:[],
            
        }
    },
    
    watch: {
        requestUrl()
        {
            var url = this.requestUrl.split('?');

            var data = [];

            if(url.length > 1) {

                url = url[1].split('&');

                for(var i = 0; i < url.length; i++) {

                    // var data =
                    var u = url[i].split('=');

                    if(u[1] == undefined) {

                        u[1] = '';

                    }

                    data.push({
                        "is": 1,
                        "key": u[0],
                        "value": u[1]
                    });
                }
            }

            this.data = data;
        }
    },
    updated()
    {
        //计算data数据变化, 收集key不为空且is=1的数据 传递给父组件
        var data = [];

        for(var i = 0; i < this.data.length; i++) {

            if($.trim(this.data[i].key) && this.data[i].is) {

                data.push(this.data[i]);
            }
        }

        this.$emit('queryString', data);
    },
}
</script>

我说下我的逻辑(看对不对)
1、因为页面有很多选项卡 我采用的是动态组件方式加载的选项卡 每个子组件的data都是子组件自己处理的并不是父组件传过来的。我再子组件内部监听数据变化updated过滤一些数据后$emit给父组件的querySting方法,父组件的queryStirng方法接受到之后处理一些逻辑 修改requestUrl (实现了子组件的input发生变化父组件的input框也跟着发生变化)

2、query子组件接受父组件传过来的requestUrl值 然后在子组件内部watch监听requestUrl变化进行修改data(实现父组件url框发生变化 子组件内部的data也跟着变化。)

很辛运的是这样并没有发生死循环

碰到的问题是: 我在父组件url框进行编辑的时候

clipboard.png

=号以及&号没办法输入 最终都会被queryString方法重新处理一遍

        {
            var params = '?';

            for(var i = 0; i < data.length; i++) {

                if($.trim(data[i].value)) {

                    params += data[i].key + '=' + data[i].value + '&';

                } else {

                    params += data[i].key + '&';

                }
            }
            this.requestUrl = this.requestUrl.replace(/\?.+/, '') + params
        }

我不太清楚vue还有没有更好的一种方式实现。

阅读 3.1k
1 个回答

你可以这样做,现在问题是你传递给子组件是未处理的requestUrl,在子组件里解析加工(queryString)显示,子组件更新后,应该把加工后的数据还原(queryString的逆过程)后再$emit到父组件中。

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