vue 父组件如何实时监听子组件数据变化

vue 父组件如何实时监听子组件data数据变化 然后进行业务逻辑处理。

父组件代码:

<template lang = "pug">

    #debugger

        .debugger-1
            //- 请求
            .debugger_body_request

                .debugger_body_request_host

                    input(autocomplete = "off", placeholder = "服务器未配置",readonly = "readonly","type" = "text", value = "http://localhost")

                .debugger_body_request_method_url

                    .debugger_body_request_method(@mouseleave = "isShowRequestMethod = false", style = "display: -webkit-inline-box;")

                        button.btn(@click = "isShowRequestMethod = !isShowRequestMethod")

                            strong {{ currentRequestMethod }}

                            i.iconfont.icon-xia1(style = "font-size:13px;")

                        .prohibition_of_replication(v-show = "isShowRequestMethod")

                            ul.xiahua

                                li(v-for = "method in requestMethod", @click = "selectiveRequestMethod(method)") {{ method }}

                        .debugger_body_request_url

                            input(v-model = "requestUrl" type = "text", name = "requestUrl", placeholder = "http://", autocomplete = "off")

                .debugger_body_reset_params.prohibition_of_replication

                    a(href="#") 重置为文档参数

                .debugger_body_params

                    .tabcontrol.prohibition_of_replication

                        .abcontrol-1(v-if = "tab")

                            div(v-for="tab, index in tab", @click = "showView(tab.view, index)", :class = "{tab: true, updateStyle: index == viewIndex}") {{ tab.name }}

                                div(v-if = "tab.options", @mouseleave = "isShowParamsFormat = false", style = "display:inline-block")

                                    i.iconfont.icon-xia1(@click.stop = "isShowParamsFormat =!isShowParamsFormat", style = "vertical-align: middle")

                                    ul.xiahua(v-show = "isShowParamsFormat", style = "widthd:82px")

                                        li(v-for = "option,optionIndex in tab.options" @click.stop = "selectiveParamsFormat(option.name, option.view, index)") {{ option.name }}

                    keep-alive
                        component(:is = "view", :type = "type", @cacheParams = "cacheParams")

                .el_button

                    button.request_test(type = "button") 请求测试

                    div(style = "float: left;width:60%")

                        button.saveArchive(type = "button") 生成文档

        //- 响应
        .debugger_response(style = "width:40%")

            .debugger_response_statusCode

                ul

                    li
                        span Status:

                        span(style = "color:red") 200

                    li

                        span Time: 7ms

                    li
                        span Size: 123kb


</template>


<script>
import formView from './form';
import queryView from './query';
import jsonView from './json';
import xmlView from './xml';
import headerView from './header';

export default {
    components: {
        formView,
        jsonView,
        queryView,
        xmlView,
        headerView,
    },
    data()
    {
        return {
            view: "formView",
            viewIndex: 0,
            type: 'Form',
            //接口地址
            requestUrl: '',
            isShowRequestMethod: false,
            isShowParamsFormat: false,
            requestMethod: [
                'GET',
                'POST',
                'PUT',
                'DELETE',
                'OPTIONS'
            ],
            currentRequestMethod: 'GET',
            tab: [{
                "name": "Form",
                "view": "formView",
                "options": [{
                    "name": "Form",
                    "view": "formView"
                },{
                    "name": "JSON",
                    "view": "jsonView",
                }, {
                    "name": "XML",
                    "view": "xmlView"
                }]

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

            }, {
                "name": "Header",
                "view": "headerView",
            }],

            params: []
        }
    },
    methods: {
        selectiveRequestMethod(method)
        {
            this.currentRequestMethod = method;

            this.isShowRequestMethod  = !this.isShowRequestMethod;
        },

        /**
         * 二级选项卡处理
         *
         * @param string name 展示的内容
         * @param string view 要显示的视图
         * @index intger index 父级选项卡的索引
         */
        selectiveParamsFormat(name, view, index)
        {
            this.type               = name;

            this.tab[index].name    = name;

            this.tab[index].view    = view;

            this.showView(view, index);

            this.isShowParamsFormat = !this.isShowParamsFormat;

        },
        showView(view, index)
        {
            this.viewIndex       = index;

            this.view            = view;
        },
        cacheParams(data)
        {
            console.log(data);
        }
    }
}
</script>

子组件代码:

<template lang = "pug">

    #form

        .form_form

            table(v-if = "data")

                tr(v-for = "val, index in data")

                    td(style="width:7%")

                        label

                            input.check.form_input(:checked = "val.is", @click = "data[index].is = !data[index].is", type = "checkbox")
                    td

                        div

                            input.params_key.form_input.input-placeholder(v-model = "val.key", placeholder = "key")

                    td
                        div

                            input.form_input(v-model = "val.value", @keyup.enter = "", placeholder = "value")
                    td

                        i.iconfont.icon-shanchu.debugger_icon(@click = "deleteParams(index)")

        button.form_button(@click = "addParams()", type = "button")

            i.iconfont.icon-iconjia(style="font-weight:400, font-size:15px")

            span 添加参数

</template>

<script>
export default {
    data()
    {
        return {
            data: [],
            //QUERY_STRING Params
            params: '?'

        }
    },

    updated()
    {
        this.$emit('cacheParams', this.data);
    },

    methods: {
        addParams()
        {
            this.data.push({"key":"", "value":"","is":1});
        },
        deleteParams(index)
        {
            this.data.splice(index, 1);
        },
    }
}
</script>

页面:

clipboard.png

下面那个input框是子组件, 我想实现的效果是 input框发生变化实时通知给父组件 然后父组件在上面那个url框进行拼接 比如: test.php?id=1&name=3

已尝试的解决方案:

1、在子组件里声明updated方法然后抛出事件给父组件 this.$emit('cacheParams', this.data);

这样每次data发生变化都会通知父组件并把改过的或者新增的data数据传递给父组件, 
但是这样会把全部数据给父组件 父组件每次都需要for循环一遍全部数据 很浪费性能。

请问还有没有一些其他的解决方案

阅读 22.2k
2 个回答

首先。。。麻烦简化一下你的代码。。。八哥看着头大。
其次,简要说一下父组件监听子组件数据的方法(没看你的示例,不知道是不是你要的)

// 父组件
<template>
    <child-comp v-model="a"></child-comp>
</template>
export default {
    data() {
        a: ''
    }
}
// 子组件
<template>
    <input @input="handleInput" />
</template>
export default {
    methods: {
        handleInput() {
            this.$emit('input', e.target.value)
        }
    }
}

Vue关于组件的章节

其实这里的v-model也是一个语法糖,省略了在父组件里监听input事件的代码。
如果你的数据项比较多,那就分别发事件吧。

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