美文网首页
模仿todolist 的功能

模仿todolist 的功能

作者: bby365 | 来源:发表于2018-06-13 16:42 被阅读0次

    基础实现

    刚开始学习vue,做一个简单的todolist , 用到 v-for v-on v-model

    整体功能比较简单,直接说遇到的问题:怎样删除点击的li ?
    首先想到的是this.items.splice(e.target.id,1) 这种方法需要在每个li上面添加一个id,因为items 是个数组,需要转成一个对象数组,也就是:

    items:['first','two','three']
    变成:
    items: [
            {
                message:'first',
                id:0
            },
            {
                message:'two',
                id:0
            } ]
    

    这样写感觉有点太麻烦,而且新增li,也麻烦,那就换一种。


    第二种想法:是渲染li 时,直接绑定 id 属性:
    <li v-for="item in items" :id = "count">
    然后,每次点击新增时,count++,但是,count改变所有的li的id属性都会改,所以这种想法失败;同时,初始化时,所有的li 的id属性都一样,因为没有点击,所以count不会变。


    第三种: e.target.innerHTML
    这种想法,就是itmes 去查找点击的文本,获取到index值,然后再有splice去删除当前的点击的li。
    测试遇到一个坑:每次点击返回index值都是 -1,发现是因为有空格,所以需要e.target.innerHTML.trim()
    这样就完成了功能。

    // html
        <div id="app">
            <input  v-model="message" placeholder="edit me" type='text' @keyup.enter = "addInfo"/>
            <button v-on:click='addInfo'> 提交</button>
    
            <p>新任务:</p>
            <ul v-on:click='addPlan'>
                <li v-for="item in items" >
                    {{item}}
                </li>
            </ul>
    
            <p>已完成:</p>
            <ul >
                <li v-for="plan in plans">
                    {{plan}}
                </li>
            </ul>
    
        </div>
    
    // js
            var vm = new Vue({
                el:'#app',
                data:{
                    items:['first','two','three'],
                    plans:[],
                    message:''
                },
                methods:{
                    addInfo: function(){
                        if(!this.message) return;
                        this.items.push(this.message);
                        this.message='';
                    },
                    addPlan:function(e){
                        var value = e.target.innerHTML.trim()
                        var index = this.items.indexOf(value);
                        this.items.splice(index,1)
                        this.plans.push(value)
                    }
                }
            })
    

    组件化改造

    首先改造按钮组件,需要解决两个问题:1.组件中使用v-model,2.按钮的点击事件传值;

    • 按钮组件
    Vue.component('button-add',{
                props:['value'],
                template:`
                    <div>
                        <input  v-bind:value="value" 
                        v-on:input="$emit('input',$event.target.value)"
                        placeholder="edit me" type='text' >
                        <button v-on:click='$emit("add-info")'> 提交</button>
                    </div>
                `
            });
    // 全局中引用如下:
            <button-add
                v-model="message"
                v-on:add-info='addInfo'>
            </button-add>
    
    遇到的问题:
    1.怎么触发事件
    2.组件上怎么使用v-model事件
    
    • 列表组件
    Vue.component('list-info',{
                props:['items'],
                template:`
                    <div>
                        <ul v-on:click='$emit("add-plan",$event)'>
                            <li  v-for="item in items" >
                                {{item}}
                            </li>
                        </ul>
                    </div>
                `
            })
    
    //全局中引用如下:
            <list-info 
                :items='items'  
                v-on:add-plan='addPlan'>
            </list-info>
    
    其实,可以只把 li 改写成组件就行,因为刚学vue,所以故意把这个整体改写成组件。
    
    遇到的问题:
    控制台一直报错:target undefined,这是因为全局中的addPlan中使用了 e.target ,但是组件中没有传递event ,调试了很久,后来知道了原因 :
    <ul v-on:click='$emit("add-plan",$event)'>   $emit  需要传参。
    

    改进:
    1.关于 删除当前点击的元素,不用e.target.innerHTML 。

    1. li 中 增加一个 ID属性
    <li  
        :id='index'
        v-for="(item,index) in items" >
        {{item}}
    </li>
    
    2. 同时将id 值传递给父组件:
    v-on:click='$emit("add-plan",$event.target.id)'
    
     3. 全局 addPlan 改写如下:
    addPlan:function(index){
        // var value = e.target.innerHTML.trim()
        // var index = this.items.indexOf(value);
        var value = this.items.splice(index,1)
        this.plans.push(value.toString())
    }
    这种方法比之前简单多了,主要数组遍历时,可以拿到index
    

    程序源文件

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Document</title>
        <script src="vue.js"></script>
    </head>
    <body>
        <div id="app">
        
            <button-add
                v-model="message"
                v-on:add-info='addInfo'>
            </button-add>
    
            <p>新任务:</p>
            <list-info 
                :items='items'  
                v-on:add-plan='addPlan'>
            </list-info>
    
            <p>已完成:</p>
            <ul >
                <li v-for="plan in plans">
                    {{plan}}
                </li>
            </ul>
    
        </div>
        <script>
    
            Vue.component('button-add',{
                props:['value'],
                template:`
                    <div>
                        <input  v-bind:value="value" 
                        v-on:input="$emit('input',$event.target.value)"
                        placeholder="edit me" type='text' >
                        <button v-on:click='$emit("add-info")'> 提交</button>
                    </div>
                `
            });
            Vue.component('list-info',{
                props:['items'],
                template:`
                    <div>
                        <ul v-on:click='$emit("add-plan",$event.target.id)'>
                            <li  
                                :id='index'
                                v-for="(item,index) in items" >
                                {{item}}
                            </li>
                        </ul>
                    </div>
                `
            })
            var vm = new Vue({
                el:'#app',
                data:{
                    items:['first','two','three'],
                    plans:[],
                    message:''
                },
                methods:{
                    addInfo: function(){
                        if(!this.message) return;
                        this.items.push(this.message);
                        this.message='';
                    },
                    addPlan:function(index){
                        // var value = e.target.innerHTML.trim()
                        // var index = this.items.indexOf(value);
                        var value = this.items.splice(index,1)
                        this.plans.push(value.toString())
            
                        
                    }
                }
            })
    
        </script>
    </body>
    </html>  
    

    相关文章

      网友评论

          本文标题:模仿todolist 的功能

          本文链接:https://www.haomeiwen.com/subject/fwnjeftx.html