四、实现todolist的删除功能(知识点:子组件向父组件传值)

2019-02-13  本文已影响0人  李浩然_6fd1

依然利用沿用上次的例子(去掉了component组件中的点击事件,出现"clicked"弹窗的方法):

<body>
    <div id="root">
        <div>
            <input v-model="inputValue" />
            <button @click="handleSubmit">提交</button>
        </div>
        <ul>
            <todo-item
            v-for="(item, index) of list"
            :key="index"
            :content="item"
            >
            </todo-item>
        </ul>
    </div>
    
    <script>
        Vue.component('todo-item',{
            props:['content'],
            template:'<li @click="handleClick">{{content}}</li>',
        })
        new Vue({
            el:"#root",
            data:{
                inputValue:'hello',
                list:[]
            },
            methods:{
                handleSubmit:function(){
                    this.list.push(this.inputValue)
                    this.inputValue =''
                }
            }
        })
    </script>
</body>

现在要实现一个需求:点击li标签的数据,数据可以被删除。
分析一下这个需求:li标签是在子组件中创建的,但是li标签内的数据是来自父组件,如果要删除子组件的这个数据,肯定要删除父组件中对应的数据。
在Vue中,实现子组件和父组件之间的通讯,需要一个发布订阅模式来处理。

在处理这个需求之前,还需要一个参数,是当前子组件在list中的下标。在ul中,父组件循环显示子组件的时候,额外再带一个参数index,这个参数等于循环显示的下标index(即“:index='index'”),然后再component组件中的props内增加这个index(即:“props:['content','index']”),让子组件接收父组件中的content属性的同时,接收index属性,
尝试下能不能接收到index属性,component中的template模板增加一个插值表达式{{index}},template的模板即写成:

template:'<li @click="handleClick">{{content}}{{index}}</li>',

结果是:


图片.png

可以看到子组件成功接收了list下标。现在删除template中的{{index}}。
在需求中,可以看到是点击li标签,然后会删除li标签的内容。
这样其实是在点击li标签的时候,触发了是一个事件,这个事件将删除li标签的内容。
但是li标签是在子组件中创建的,list的内容是是在父组件中创建的,如何将删除li标签的删除传达到父组件中,将是这节的重点。
点击li标签将触发事件,这个事件的方法删除父组件中的数据。直接删除是不可能的,因为无法通信。
答案是通过订阅模式,子组件创建一个自定义的事件,在模板中绑定delete事件和一个新的方法(handleDelete,方法将删除数据),当触发这个方法的时候,模板中会监听到这个事件的触发,然后handleDelete事件将起作用,然后删除数据。
下面是代码的具体表现:

<body>
    <div id="root">
        <div>
            <input v-model="inputValue" />
            <button @click="handleSubmit">提交</button>
        </div>
        <ul>
            <todo-item
            v-for="(item, index) of list"
            :key="index"
            :content="item"
            :index="index"
            @delete="handleDelete"
            >
            </todo-item>
        </ul>
    </div>
    
    <script>
        Vue.component('todo-item',{
            props:['content','index'],
            template:'<li @click="handleClick">{{content}}</li>',
            methods:{
                handleClick:function(){
                    this.$emit('delete',this.index)
                }
            }
        })
        new Vue({
            el:"#root",
            data:{
                inputValue:'hello',
                list:[]
            },
            methods:{
                handleSubmit:function(){
                    this.list.push(this.inputValue)
                    this.inputValue =''
                },
                handleDelete: function(index) {
                    this.list.splice(index, 1)
                }
            }
        })
    </script>
</body>

当点击li标签的时候,会触发handleClick方法,这个方法向外释放了一个名为delete的事件,这个事件对应的值是触发的内容的下标签。
因为在父标签中订阅了delete事件(@delete="handleDelete"),当触发的时候,就会执行handleDelete方法(handleDelete方法是父组件还是子组件的?是父组件的,因为它写在父组件对应的模板中),这个方法将删除所点击的内容(function括号内的index参数是接收的参数,将指导下标对应的什么数据内容)

上一篇下一篇

猜你喜欢

热点阅读