Vue.js note3(指令混合练习todolist)

混合练习(一) 表格数据的增删

在这里插入图片描述
在这里插入图片描述
由上图页面的风格可以看出,使用bootstrap来搭建页面,这样也好,可以学着使用一下bootstrap。使用前,要先下载bootstrap

我选择使用cnpm下载,也可以用npm,不过我怕网速不好,下载国外服务器的下载不下来,所以用国内的。因为bootstrap底层是jQuery开发的,所以要先下载jQuery框架依赖。
cnpm install --save bootstrap@3.3.7 下载指定版本的,不加班和版本号,默认下载最新版本
cnpm install --save jquery

也可以两个一起下载:cnpm install --save bootstrap@3.3.7 jquery

如果已经下载下来,但是版本不是我们想要的,可以去package.json里面修改bootstrap的版本号,然后重新 cnpm install ,把依赖重新下载下来。

分析小程序的业务逻辑:
1、先创建一些假数据,把表格遍历出来 v-for;
2、在表格的最下面,各有一行 暂无数据(无数据) 与 删除全部 (有数据)

  • 思路:判断存储表格中数据的数组arr的长度,若为0说明当前没有数据,则显示 暂无数据;否则显示 删除全部 这一行。

3、向表格中添加数据

  • 思路:
    (1)使用 v-model 让输入框绑定变量 (模型数据)
    (2)给添加按钮绑定点击事件调用处理函数
    (3)输入框中输入的数据,插入到arr中,靠双向绑定 v-model
    (4)插入数据之后,输入框清空

4、判断添加按钮是否禁用

  • 思路:
    (1)给按钮添加disabled属性,属性值使用 v-bind 指令绑定一个布尔值,控制disabled属性值的变化
    (2)监听输入框的变化。使用vue的watch来进行监听(watch实时监控)
    (3)在watch中监听两个变量的变化,除非是两个输入框里都有数据,才解除禁用

5、删除按钮的功能,单个删除全部删除

  • 思路:
    (1)设置一个变量,通过变量=不同数字来判断是单个删除,还是全部删除;(比如 @click=“number=index” 、@click=“number=-100” 表达式)
    (2)给模态框的确认按钮绑定点击事件调用处理函数
    (3)处理函数中,通过number的值判断是哪个操作(单个删除设置变量>= 0;全部删除设置变量<0;)
    (4)如果是全部删除,则直接清空arr;如果是单个删除,则可以用arr.splice()方法删除某个index的值。

然后功能分析基本上就完成了。

<style>
    #container {
        padding: 10%;
    }

    .form-group {
        margin: 10px 0;
    }

    table tr {
        text-align: center;
    }

    .text_right {
        text-align: right;
    }
</style>
    
<!-- 使用练习bootstrap -->
<!-- 引入文件的script脚本数据放在下面吧,这样就不用等加载完在渲染 -->
<!-- 先引入jQuery -->
<!-- 然后引入bootstrap -->

<div class="container demoSky">
    <div class="form-group">
        <label for="exampleInputEmail1">Please input your name here.</label>
        <input type="email" class="form-control" id="exampleInputEmail1" placeholder="Name" v-model="inputValue1">
    </div>
    <div class="form-group">
        <label for="exampleInputEmail1">Please input your age here.</label>
        <input type="email" class="form-control" id="exampleInputEmail1" placeholder="Age" v-model="inputValue2">
    </div>

    <button class="btn btn-default" type="submit" @click="add()" :disabled="bool">Add</button>
    <button type="button" class="btn btn-primary" @click="reset()">Reset</button>

    <h2>用户信息表</h2>
    <table class="table table-bordered">
        <tr>
            <td>序号</td>
            <td>名字</td>
            <td>年龄</td>
            <td>操作</td>
        </tr>
        <!-- vue 的v-for指令 遍历生成数据 -->
        <tr v-for="(item,index) in arr">
            <td>{{index+1}}</td>
            <td>{{item.name}}</td>
            <td>{{item.age}}</td>
            <td><button type="button" class="btn btn-success" data-toggle="modal"
                    data-target="#myModal" @click="number=index">Delete</button></td>
        </tr>
        <!-- v-if 与 v-else 共同判断 -->
        <tr v-if="arr.length<=0">
            <td colspan="4">暂无数据......</td>
        </tr>
        <tr v-else="">
            <td colspan="4" class="text_right">
                <button type="button" class="btn btn-info" data-toggle="modal" data-target="#myModal" @click="number=-120">Delete
                    All</button>
            </td>
        </tr>
    </table>

    <!-- Modal 模态框 在需要出发的标签写上属性 data-toggle="modal" data-target="#myModal"-->
    <div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel">
        <div class="modal-dialog" role="document">
            <div class="modal-content">
                <div class="modal-header">
                    <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span
                            aria-hidden="true">&times;</span></button>
                    <h4 class="modal-title" id="myModalLabel">Modal title</h4>
                </div>
                <div class="modal-body">
                    确定删除吗?
                </div>
                <div class="modal-footer">
                    <button type="button" class="btn btn-default" data-dismiss="modal" @click="del()">确定</button>
                    <button type="button" class="btn btn-primary" data-dismiss="modal">取消</button>
                </div>
            </div>
        </div>
    </div>
</div>

<script>
    // vue代码
    new Vue({
        el: ".demoSky",//视图挂载时,确保命名唯一
        data: {
            arr: [
                { name: "yy1", age: 12 },
                { name: "yy2", age: 100 },
            ],
            // arr:[],
            inputValue1: "",
            inputValue2: "",
            bool: true,//默认按钮禁用
            number: -1,//随便给个值,反正只要不被使用即可
        },
        methods: {
            // 事件处理函数
            add() {
                // if(this.inputValue1 == ""||this.inputValue2 == "") return;//因为有对按钮的禁用功能,所以这儿可以不写
                this.arr.push({ name: this.inputValue1, age: this.inputValue2 });
                this.valueNull();
            },
            // sum:function(){}, //这种格式是正式全写的格式,上面那种是简写,是不是跟对象中的函数很像
            reset() {
                this.valueNull();
            },
            del() {
                if(this.number<0){
                    console.log("全部删除");
                    this.arr.splice(0,this.arr.length);
                    // this.arr=[];
                    // this.arr.length=0
                }else{
                    console.log("单个删除");
                    this.arr.splice(this.number,1);//删除当前arr的index的一个元素
                }
            },
            // 处理其他业务逻辑的方法
            valueNull() {
                this.inputValue1 = "";
                this.inputValue2 = "";
            },
            boolChange() {
                if (this.inputValue1 && this.inputValue2) this.bool = false;//如果输入框没数据的话
                else this.bool = true;
            }
        },
        watch: {
            inputValue1(newVal, oldVal) {
                this.boolChange();
            },
            inputValue2(newVal, oldVal) {
                this.boolChange();
            },
        }
    })
</script>



<script src="./node_modules/jquery/dist/jquery.js"></script>
<script src="./node_modules/bootstrap/dist/js/bootstrap.js"></script>

通过这个例子,我发现了一个事实:vue的指令中可以直接使用模型数据的变量名。比如v-if=“arr.lenght<=0”。

watch 监听模型数据,模型数据改变时就会被触发;watch在初始化的时候不会运行,只有在数据发生改变的时候才会运行。


混合练习(二) todolist

所要实现的功能,实现数据的增删改查。
在这里插入图片描述

业务处理逻辑:
1、使用假数据初始化,模型数据arr:[{}];
2、v-model 双向绑定 ,input输入框与模型数据inputVal;
3、增加任务

  • 思路:
    (1)input设置change事件,回车触发
    (2)添加按钮设置click事件,点击触发
    (3)事件处理函数都为add(),都是实现向数组arr中添加一条新的对象数据
    (4)添加成功后,input输入框重新置空

4、按钮禁用

  • 思路:
    (1)给 添加按钮 设置disabled属性,属性值用v-bind绑定数据模型bool,控制该添加按钮的禁用功能
    (2)vue的watch属性,监听inputVal的变化,为空则bool=true,启用禁用功能

5、统计任务总数:arr.length;
6、统计剩余任务数

  • 思路:
    (1)给arr数组的每条数据设置一个status属性,用来存储复选框的状态
    (2)遍历arr,统计status为false的数据的数量
    (3)将这个数量值return出去
    (4)将这个函数添加到view中的某个位置,语法是:{{last()}}

7、勾选复选框,任务样式改变

  • 思路:
    (1)将复选框双向绑定到arr数据的status属性,v-model="item.status"
    (2)写一个样式 .del{},加删除线,字体颜色也变暗
    (3)v-bind指令,可以使用status的值,然后判断arr里每条数据的status属性值,为true则添加删除样式,否则添加 ’ ’ 空字符,:class="item.status?'del':''"

8、点击 完成 删除已选任务

  • 思路:
    (1)给完成按钮添加点击事件,事件处理如下:
    (2)将arr复制给另外的newArr
    (3)然后把arr清空
    (4)然后再重新遍历newArr,找到 status为false的内容 ,插入到原始数据中,更新view。以下我找到两种写法:
    第一种,我的写法:
    delTask(){
    	let newArr=this.arr.concat();
    	this.arr.splice(0);
    	newArr.forEach((item,index)=>{
        	if(item.status==false) this.arr.push(item);
    	})
    }
    
    第二种,老师的写法:
    del(){    
        var newarr=this.arr; // 1.把原始数据赋值给一个新变量保存    
        this.arr=[]; // 2.把这个原始数据清空    
        for(var i=0;i<newarr.length;i++){ // 3.遍历新数据 并且找到 style为false的内容 插入到原始数据中
            if(newarr[i].style==false){
                this.arr.push(newarr[i])
            }
        }
    }
    

9、点击修改任务名

  • 思路:
    (0)在文本标签span后面再跟一个input输入框,并设置v-if、v-else命令,控制二者永远只显示一个,并在arr数据里设置一个变量edit进行控制。
    (1)点击标签触发事件,切换成input输入框
    (2)输入框绑定blur事件,输入完成后失焦时触发,切换回span标签
    (3)绑定同一个事件处理函数,实现非删除状态下(未选中复选框),控制切换的变量的正反状态更改

10、当修改单个文本时,禁用复选框;
11、点击文本进入编辑模式,但是我发现切换成输入框后,必须手动聚焦,才能触发失焦事件,那么怎么让文本输入框自动聚焦?
发现了一篇超棒的文章:Vue 中如何让 input 聚焦?(包含视频讲解)

下面是完整代码,不过点击进入文本编辑模式时文本自动聚焦的功能我没实现。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="./node_modules/vue/dist/vue.js"></script>
    <style>
        .del {
            text-decoration: line-through;
            color: #ccc;
        }
    </style>
</head>

<body>
    <div id="demoSky">
        <h1>任务列表</h1>
        <p>
            任务总数:{{arr.length}};剩余任务:{{last()}};点击 <button @click="delTask()">完成</button>,移除任务
        </p>
        <ul>
            <li v-for="(item,index) in arr">
                <input type="checkbox" v-model="item.status" :disabled="!item.edit">
                <span :class="item.status?'del':''" @click="clickHandler(item)" v-if="item.edit">{{item.title}}</span>
                <input type="text" v-model="item.title" @blur="clickHandler(item)" v-else  id="autoget">
            </li>
        </ul>
        <input type="email" placeholder="任务" v-model="inputVal" @change="add()" > <button :disabled="bool" @click="add()">添加</button>      
    </div>

    <script>    
        new Vue({
            el: "#demoSky",
            data: {
                arr: [
                    { title: "设计1", status: false, edit: true },
                    { title: "设计2", status: false, edit: true },
                    { title: "设计3", status: false, edit: true },
                    { title: "设计4", status: false, edit: true },
                ],
                inputVal: "",
                bool: true,
                ifBool: true,
                checBool: false,
            },
            methods: {
                add() {
                    this.arr.push({ title: this.inputVal, status: false, edit: true });
                    this.inputVal = "";
                },
                last() {
                    let num = 0;
                    for (let i = 0; i < this.arr.length; i++) {
                        if (this.arr[i].status == false) num++;
                    }
                    return num;
                },
                delTask() {
                    let newArr = this.arr.concat();
                    this.arr.splice(0);
                    newArr.forEach((item, index) => {
                        if (item.status == false) this.arr.push(item);
                    })
                },
                clickHandler(item) {
                    console.log("before:", item.edit)
                    if (item.status) return;
                    item.edit = !item.edit;
                    console.log("after:", item.edit)
                }
            },
            watch: {
                // 监听输入框的改变,然后改变其后button的disabled值,来判断是否进行该按钮
                inputVal(newVal, oldValue) {
                    if (this.inputVal) {
                        this.bool = false;
                    } else {
                        this.bool = true;
                    }
                }
            }
        })
    </script>
</body>
</html>
>> 补充几个事件简介:change&input&keydown&blur&focus

1、change

js的onchange事件:

  • 会在域的内容改变时发生。
  • 也可用于单选框与复选框改变后触发的事件。
  • onchange 触发需要三个步骤:
    • input 元素获得焦点
      input 元素的值发生变化
      input 元素失去焦点

jQuery的change事件与change()方法:

  • 当元素的值发生改变时,会发生 change 事件。
    该事件仅适用于文本域(text field),以及 textarea 和 select 元素。
  • change() 函数触发 change 事件,或规定当发生 change 事件时运行的函数。
    注释:当用于 select 元素时,change 事件会在选择某个选项时发生。当用于 text field 或 text area 时,该事件会在元素失去焦点时发生。

我说:因为最常使用的是input的文本输入复选框checkbox嘛,我就从这两个方向看一下change到底是怎么用的。

  • 如果是文本输入input添加change事件,那么每次改变数据回车后,只会触发一次change事件;
  • 如果是checkbox的话,只要点击就会触发;
  • 我还试了一下密码的,也会触发change事件。

2、input

  • 文本 input 是输入时触发,回车不能触发
  • checkbox选中或者取消选中都可以触发

3、keydown
keydown 按下按键的时候触发,啥键都行,而且如果查看当前触发的事件, 而且打印的事件对象有个属性 keycode 可以查看当前按下的按键的键码值。

Event 对象代表事件的状态,比如事件在其中发生的元素、键盘按键的状态、鼠标的位置、鼠标按钮的状态。

4、blur

  • onblur:当元素失去焦点的时候。
  • 常用的地方有 从单选按钮上移开焦点。

5、focus
onfocus:当元素获取到焦点的时候触发



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值