vue学习笔记(一)(学自尚硅谷)

一、vue学习的基本语法

  • vue2的使用要先下载vue.js文件,然后引入html页面
 <script src="js/vue.js"></script>
  • 如何使用vue,Vue的基本语法是什么?
  1. Vue可以实现在标签体和标签属性中的数值绑定。分别叫做差值语法与绑定语句
  2. 下面首先演示插值语法,要用到{{}}。见下:
<body>
    <div id="boxOne">我是{{name}}</div>
   <script>
    new Vue({//首先创建一个Vue对象
        el: "#boxOne",//通过el来确定数据要绑定到的容器
        data:{
            name: "程咬金",//这个是Vue中存储的数据,对象套对象。
        }
    })
   </script>
</body>

 3.然后我们再尝试绑定属性,就以name属性为例

在上面的div中添加name属性并绑定到Vue的值:

<div id="boxOne" v-bind:name="name">我是{{name}}</div>

v-bind也可以简写为:         你没看错就是冒号,所以上面的等价于下面

 <div id="boxOne"   :name="name">我是{{name}}</div>

这种绑定有个缺点就是当标签中的属性值发生改变时,Vue中的值并不会发生变化,这时候就要用到v-model,v-model专门用于input表单场景中,我们新创建一个表单测试

<form action="">
        <input v-model="name">
    </form>

 这样当输入框中文本发生改变时,Vue中的name值也会发生改变!

二、Vue底层用到的重要函数和模型

 (一)mvvm模型

mvvm模型就是model view viewmodel三个缩写,二Vue扮演的角色就是在model和view中间的viewmodel,它将底层的数据model,经过自己的处理展现到界面上,这就是viewmodel,简称vm。

(二)Object.defineproperty()

  • 函数有三个参数:

Object.defineproperty("要更改属性的对象",要变化的属性,{键值对};

var people = {
        name: "chenpei",
        sex: "女"
    }
    //向对象中添加属性
    Object.defineProperty(people,"age",{
        value: 22,
         writable: true, 
        //规定添加的属性值能否被修改。
        enumerable: true,
        //规定能否在遍历的时候被遍历到,还有其他原数据在之前提到过这里不再提
    });

 所以通过这种方法赋值和普通的赋值具有本质上的不同,这也是Vue底层选用的原因。

  • 利用Object.defineProperty()进行的数据代理
  1. Object.definePeoperty()实现简单的数据代理
var people = {
        name: "chenpei",
        sex: "女"
    }
    var peopleTwo = {
           name: "wuji",
           sex: "男",
    }
    //向对象中添加属性
    Object.defineProperty(people,"age",{
        value: 22,
         writable: true, 
        //规定添加的属性值能否被修改。
        enumerable: true,
        //规定能否在遍历的时候被遍历到,还有其他原数据在之前提到过这里不再提
    });
     //修改peopleTwo的getter和setter
     Object.defineProperty(peopleTwo,"sex",{
        //当有人从peopleTwo中读取sex属性时,会执行get方法获得people中sex属性的值
        get(){
        return people.sex;
        },
        //同上理,当有人修改sex属性时,people中的sex属性也会被setter改变
        set(value){
           people.sex = value;
        }
     });  

2.Vue底层就用到了这种数据代理,请看下图(图片来源:尚硅谷)

 3.这样实现数据代理之后,Vue即vm将自身_data对象中储存的数据被vm自身代理,实现数据同步,这样也方便了我们在插值语法中书写,只需要写数据名即可。

三、事件处理与事件修饰符

(一)事件绑定符:v-on:事件名="要调用的函数名"   可以简写为@事件名="要调用的函数"

(二)事件处理(Vue中方法的声明)

<div id="boxOne" v-bind:name="name">
        我是{{name}}
        <!--事件绑定中指定的函数会默认传入event事件对象,但是当参数中有其他参数传入,事件对象就会被覆盖,用Vue语法$符标记一下就可以不被覆盖-->
        <button id="clickTest" @click="myClick($event,22)" value="点击事件"></button>
    </div>
<script>
    new Vue({//首先创建一个Vue对象
        el: "#boxOne",//通过el来确定数据要绑定到的容器
        data:{
            name: "程咬金",//这个是Vue中存储的数据,对象套对象。
        },
        methods:{
            myClick(event,num){
                //在控制台输出测试
             console.log(event,num);
            }
        }
    })
</script>

控制台输出内容:

(三)事件处理修饰符之取消冒泡修饰符

  • 我们对上面例子再增加内容,如下了解下冒泡事件触发
<div id="boxOne" v-bind:name="name" @click="myClickDiv">
        我是{{name}}
        <!--事件绑定中指定的函数会默认传入event事件对象,但是当参数中有其他参数传入,事件对象就会被覆盖,用Vue语法$符标记一下就可以不被覆盖-->
        <button id="clickTest" @click="myClick($event,22)" value="点击事件"></button>
    </div>
<script>
new Vue({//首先创建一个Vue对象
        el: "#boxOne",//通过el来确定数据要绑定到的容器
        data:{
            name: "程咬金",//这个是Vue中存储的数据,对象套对象。
        },
        methods:{
            myClick(event,num){
                //在控制台输出测试
             console.log(event,num);
               //看看事件的触发者
               console.log("内部button的触发者是:" + event.target);
            },
            //div的点击事件函数
            myClickDiv(event){
               console.log(event,"我是div中的点击事件函数");
               console.log("div中事件的触发者是:" + event.target);
            }
        }
    })
</script>

控制台内容如下:

 由以上内容我们可以知道:

  1. 所谓冒泡,就是事件自里向外触发
  2. 触发者都是最里面的元素
  • 原始方式取消冒泡,在上文中最内部方法坐如下修改
myClick(event,num){
                //取消冒泡
                event.stopPropagation();
                //在控制台输出测试
             console.log(event,num);
               //看看事件的触发者
               console.log("内部button的触发者是:" + event.target);
            }

然后当我们点击按钮的时候就只有最里面的函数得到执行。

  •  用Vue的事件修饰符的方式,只需要在函数绑定的时候加上.修饰符即可
 <button id="clickTest" @click.stop="myClick($event,22)">

也能阻止冒泡

(三)其他的事件处理修饰符

  • 都有哪些事件修饰符:
prevent阻止元素默认事件,像a标签的跳转等等
stop阻止冒泡
once事件仅允许触发一次
capture使用事件的捕获模式,就是由外到内执行函数
self只有Event.target是自己的时候才执行函数,如果在例子中加入此,也可阻止冒泡
passive事件的默认函数立即执行,无需等待回调函数执行完毕
  • passive解释:
  1. 有些事件是先执行回调后执行默认事件的,比如说wheel(滚轮滚动)
<style>
    #textSmall{
        width: 100px;
        height: 40px;
        background-color: aquamarine;
        overflow: auto;  /*设置溢出显示滚动条*/
    }
  </style>
<body>
<div id="textSmall" @wheel="whenWheel">
        Vue (读音 /vjuː/,类似于 view) 是一套用于构建用户界面的渐进式框架。
        与其它大型框架不同的是,Vue 被设计为可以自底向上逐层应用。
        Vue 的核心库只关注视图层,不仅易于上手,还便于与第三方库或既有项目整合。
        另一方面,当与现代化的工具链以及各种支持类库结合使用时,
        Vue 也完全能够为复杂的单页应用提供驱动。
    </div>

<script>
new Vue({
        el: "#textSmall",
        methods:{
            whenWheel(){
                //制造函数执行长时间,看看默认行为执行情况
                for(i = 0; i<10000;i++){
                    console.log("我行");
                }
            }
        }
      })
</script>
</body>

结果是每当我在内容上面通过鼠标滚轮滚动时,要等一万个我行输出完毕,滚动条才会移动内容才会变化。

2.要取消这种行为,只需要修饰符passive

<div id="textSmall" @wheel.passive="whenWheel">

 四、按键别名与键盘事件

(一)什么是按键别名?

当我们绑定键盘事件的时候,事件对象会自动获取你所按的按键的别名和键码保存在属性中

下面例子用input元素的keyup事件来在控制台获取按键别名,利用event.key属性

<form action="" id="formContainer">
        <input type="text" placeholder="输入完内容后点击回车!" @keyup="keyMethod">
    </form>
<script>
new Vue({
        el: "#formContainer",
        methods:{
            keyMethod(ev){
            console.log("您按的键是:" + ev.key);
           }
        }
       })
</script>

再给按键事件指定特定的键触发,需要加上if判断语句

 if(ev.keyCode == 13)//十三是回车键的键码
            console.log("您按的键是:" + ev.key);
           }

(二)Vue键盘别名绑定事件快捷方式

  • 格式:

@keyup.键盘别名 ="要绑定的函数";

  • 常见的键盘别名:enter(回车)、delete(删除键和退格键)、esc(退出)、tab(换行)、 up\down\right\left(上下左右)
  • 要注意有些键已经绑定了浏览器事件,要注意,比如tab点下去就会转移元素焦点,所以该键只能配合keydown使用。还有alt control shift 和徽标键,属于修饰键,如果用keyup的话只有control键不动按住其他键松开才会生效,要想单独使用就要用keydown了。

@keyup.ctrl.y = "函数" 按住ctrl和y,y起才能执行函数

  • 还要注意,有些键盘别名是驼峰命名,要想用.的方式,命名要改为纯小写中间用-隔开 ,举例如下

@keyup.caps-lock ="函数" 

修饰符可以连着写

  五、Vue属性与计算属性

(一)属性

  • Vue中的属性是在data中定义的:

  •  那么我们利用属性来实现个效果,两个输入框,一个span,当输入框内容发生改变时,span中内容也要发生改变。
<form action="" id="formContainer">
        <input type="text" v-model="firstName"><br><br>
        <input type="text" v-model="lastName"><br><br>
        <!--直接动态绑定input输入框的值到Vue的属性,实现span内容自动更新-->
        <span>{{firstName}}-{{lastName}}</span>
</form>
<script>
var vm = new Vue({
        el: "#formContainer",
        data:{
            firstName: "陈",
            lastName: "湫"
        },
        methods:{
            keyMethod(ev){  
            console.log("您按的键是:" + ev.key);
           }
        }
       });
</script>

 (二)Vue的计算属性

  • 像上面span中的内容是有Vue中的两个属性计算出来的就可以指定为一个计算属性,以满足Vue在html界面上的简洁化。
  • Vue计算属性的声明:
<form action="" id="formContainer">
        <input type="text" v-model="firstName"><br><br>
        <input type="text" v-model="lastName"><br><br>
        <!--直接动态绑定input输入框的值到Vue的属性,实现span内容自动更新-->
        <span>{{fullName}}</span>
</form>
<script>
var vm = new Vue({
        el: "#formContainer",
        data:{
            firstName: "陈",
            lastName: "湫"
        },
        methods:{
            keyMethod(ev){  
            console.log("您按的键是:" + ev.key);
           }
        },
        computed:{
            fullName:{
                //当有调用fullName时,会自动执行getter和setter,来给fullName属性赋值
                get(){
                    //这里的this被Vue优化为了vm对象
                return this.firstName + "-" + this.lastName;
                }
            }
        }
       });
</script>

最终效果和上面一致。

  • 再加上set,来实现,当页面加载完成后,更改fullname的值后,Vue中的相关属性也发生改变
set(value){
       var zu = value.split("-");//将值以-为间隔拆分成数组
       this.firstName = zu[0];
       this.lastName = zu[1];
                }

实现效果,我更改fullname的值,自动调用setter

 属性值也跟着变化:

  • 这种方式跟插值的方式比有什么优点呢?
  1. 页面更加清晰。
  2. 计算属性有缓存,当fullName被多次调用时,get方法只用执行一次,只有当fullName相关联的属性值发生变化时,才会再次执行;而插值语法动态绑定不一样,只要是Vue中的属性变化,都要重新再读取属性值。

(三)Vue中计算属性的简写

  • 使用简写的前提条件是:确定计算属性只需要计算并展示,并不会被修改(即没有setter)的情况下,才可以使用。
  • 据此上面的fullName计算属性可以直接改写为:相当于getter了
fullName(){
     return this.firstName + "-" + this.lastName;
            }

六、监视属性

(一)什么是监视属性?

  • 它能够监视Vue中的属性值和计算属性值,当他们发生变化时,执行一些自定义的逻辑
  • 语法,以监视上面例子的fullName为例:
watch:{
    fullName:{
        handler(newValue,oldValue){
        console.log("属性发生了改变变化前的值是:" + oldValue );
             }
         }
     }

然后我们修改在页面控制台修改fullName的值,发现watch的handler执行了

 (二)监视属性案例练习

<div id="weatherTest">
        <span>我爱着{{rel}}!</span><br>
        <button @click="changeWeather">点我改变天气</button>
    </div>
    
   <script>
    new Vue({
        el: "#weatherTest",
        data: {
            season: "冬天"
        },
        computed: {
          rel(){
            if(this.season == "冬天"){
                return "北风吹雪";
            }else if(this.season == "春天"){
                return "鸟语花香"
            }
          }
        },
        methods:{
            changeWeather(){
                if(this.season == "冬天"){
                    this.season = "春天";
                }else{
                    this.season = "冬天";
                }
            }
        },
        watch:{
            season:{
                   //immediate: true, //在值发生变化之前先执行一次函数
                handler(newValue,oldValue){
                    console.log("值发生了改变,改变前是:" + oldValue + "\n改变后的值是:" + newValue);
                }
            }
        }
    })
</script>

效果是当季节发生变化,我爱的天气发生变化,同时season属性被监控,改变前后的值被输出到控制台

  •  另一种监视写法:

vm.$watch(要监视的变量,{handler函数和一系列原数据对});

(三)深度属性监视 

  • 当属性里面有对象(即层级结构时,需要用到深度属性监视),看下面例子。

当number中a的值发生改变的时候,控制台输出它的上一个值,而b值的变化不会影响到handler函数:

 <div id="deepSeeContainer">
        <span>a的值是:{{number.a}}</span><br>
        <button  @click="number.a++">点我给a的值加1</button><br>
        <span>b的值是:{{number.b}}</span><br>
        <button  @click="number.b++">点我给a的值加1</button>
    </div>
<script>
      new Vue({
        el: "#deepSeeContainer",
        data:{
            number:{
                a: 1,
                b: 2
            }
        },
        watch:{
            "number.a":{
//注意监视层级结构的语法,加引号是因为键本来就只能是字符串,不过我们习惯直接写了,这里却不允许去掉引号
                handler(newValue,oldValue){
                    console.log("a的值发生了改变,原来的值是:" + oldValue)
                }
            }
        }
      });
</script>

  •  那么如何实现number中只要有值改变就触发函数呢?修改一下代码,仅展示watch部分:
watch:{
     number:{
         deep: true, //不开启这个参数,Vue的watch就无法看到直接属性内的数据
     //因为选的是上层结构,所以这里传入的参数发生了改变,是一个对象,里面分别有a和b的新值
         handler(old){
         console.log("a或b的值发生了改变,原来的值是:" + "a的新值是" +old.a +"b的新值是:" + old.b);
              }
          }
      }

这样两者的变化都能触发handler函数了

七、Vue中使用函数时的this指代

  • 当Vue中是Vue中规定的要写函数的地方,我们用普通的函数声明方法,当中的this指代的是Vue实例vm。仅举例子:

  • 当Vue需要用setTimeout这种js原生函数时,用传统的函数声明(或调用)方法,那么里面的this就是windows对象,要是用箭头函数this就指代的是vm对象。 
  • 原因,当用箭头函数声明时,this指的是拥有者,普通方式是函数的调用者。
  • 所以由以上总结出最佳实践,当是vue规定的函数时,用普通声明方式,当用到原生函数时且涉及到Vue中属性的this调用,要用箭头函数声明。

八、class样式绑定和style属性的绑定(上面学习内容的综合练习)

(一)class样式绑定练习

  • 首先我们要明确一点:
  • 下面这种情况div是可以同时使用上面三种样式的:
  • <style>
    .one{
    
    }
    .two{
    }
    .three{
    }
    
    </style>
    <div class="one two three"></div>
  • 用数组方式实现div三种样式的随机切换:
<style>
.one{/*div的基础样式*/
        border:2px solid green;
        border-radius: 3px;
        width: 200px;
        height: 200px;
    }
    .two{
        background-color:aquamarine;
    }
    .three{
        background-color:brown;
    }
    .four{
        background-color:aliceblue;
    }
</style>
<body>
</div>
    <div id="classShuan" class="one" :class="colorChoose" @click="changeColor"></div>
<script>
new Vue({
        el:"#classShuan",
        data:{
            colorChoose: "two",
            //这个属性我们利用函数把它的值随机化
            //而它又被上面的class属性绑定到,所以class选择也是随机的
        },
        methods:{
            changeColor(){
                var colorArr = ["two","three","four"];
                //生成一个0到3的随机整数,不包括3,把数组下标随机化
                var downIndex = Math.floor(Math.random()*3);
                //修改colorChoose的值
                this.colorChoose = colorArr[downIndex];
                //最后要把该函数绑定到div点击事件上,实现点击随机切换三种效果
            }
        }
    })
</script>

</body>

测验通过!

  • 用数组的方式动态让用户改变样式,用对象的方式
<style>
.one{/*div的基础样式*/
        border:2px solid green;
        border-radius: 3px;
        width: 200px;
        height: 200px;
    }
/* 让按钮在div元素的下方居中不动 */
    #classShuan div{
       margin: 140px auto auto auto;
       text-align: center;
   }
    .five{
        text-shadow: 3px 3px 5px red;
        /*添加文字阴影效果*/
    }
    .six{
        text-align: center;
    }
  </style>
<body>
<div id="classShuan" class="one" :class="colorChoose">
        <span>我是神仙不下凡</span>
        <div>
        <button @click="addTextShadow">点我增加文本阴影</button>
        <button @click="addTextCenter">点我让文字居中</button>
        </div>
    </div>
<script>
new Vue({
        el:"#classShuan",
        data:{
            colorChoose:{
                "five": false,
                "six": false
                //这时候我们动态绑定到class的是一个对象,
                //这个对象的键就是我们要动态添加的class,只有为true时才会生效
            },
           
        },
        methods:{
           addTextShadow(){
              this.colorChoose.five = true;//增加文字阴影的函数,绑定到按钮上
           },
           addTextCenter(){
             this.colorChoose.six = true;//增加文字居中的函数,绑定到按钮上
           }
        }
    })
</script>
</body>

 点击第一个按钮效果:

 再点击第二个按钮增加居中效果:

(二)style属性样式动态绑定

  • 需要用到样式对象,要声明在Vue中
  • 例子,放大文本的字体到45px;
  1. 原来的写法:

<div style="font-size:45px;"></div>

   2 .Vue动态绑定的写法

<body>
<span :style="myStyleObj">我是神仙不下凡</span>
<script>
new Vue({
   el:"#classShuan",
   data:{
       myStyleObj:{
           fontSize: "48px",
           //这是样式对象内部,键值就是要修改的样式属性名
           //跟原来不一样的是要改成驼峰命名法
        }
           
    },
});
</script>
</body>

两种方式效果一致:

 九、v-if和v-show的简单使用

(一)两者的异同之处

  • 相同之处
  1. 可以单独使用,不用跟标签属性绑定。
  2. 都只能是布尔值,可以在Vue中读取值。
  3. 如果为false都能做到让元素消失
  • 不同之处
  1. v-show值为false时,实际上是改变了元素的display属性值为none,但是元素节点还在。
  2. v-if值为false时,就是直接把元素节点删除了

(二)v-if的整体使用

  • 简单的例子,改变v-if的值来控制元素的出现与消失。直接利用上面例子,仅需要注意v-if和a的绑定值即可
<div id="classShuan" class="one" :class="colorChoose" v-if="a">
        <span :style="myStyleObj">我是神仙不下凡</span>
        <div>
        <button @click="addTextShadow">点我增加文本阴影</button>
        <button @click="addTextCenter">点我让文字居中</button>
        </div>
    </div>
<script>
var vmMe = new Vue({
        el:"#classShuan",
        data:{
            colorChoose:{
                "five": false,
                "six": false
                //这时候我们动态绑定到class的是一个对象,
                //这个对象的键就是我们要动态添加的class,只有为true时才会生效
            },
            myStyleObj:{
                fontSize: "48px",
                //这是样式对象内部,键值就是要修改的样式属性名
                //跟原来不一样的是要改成驼峰命名法
            },
            a: true
           
        },
</script>

我们在控制台模仿用户改变a的值让元素消失:

  • v-if可以和v-else-if以及v-else一起使用实现多级判断。
<div id="ifTest">
        <div v-if="a == 1">第一个</div>
        <div v-else-if="a == 2">第二个</div>
        <div v-else>最后一个</div>
 </div>
<script>
    var vmIf = new Vue({
        el: "#ifTest",
        data:{
            a: 0,//默认设置为零
        }
    })
</script>

因为默认a为0,前面几个条件都不满足,所以v-else生效:

 然后我们模仿用户修改a的值

 

  • 使用上面的配套if这几个div中间不能被其他没带v-if的元素打断,否则就会报错
  • 当使用标准的v-if,v-else-if,那么当有一个条件满足,其他的都直接略过为false。 

十、列表渲染(v-for的使用)

(一)使用前置信息

  • v-for的形式:

<ul>

<li v-for="(value,key) in 要遍历的对象或数组" :key="key">

{{value.对应的键名}}

</li>

</ul>

  1. 这样书写后,在加载界面的时候,v-for就会帮我们遍历在Vue中对应的对象,并且增加对应数量的li 
  2. 在遍历时会从对象或数组中获取两个内容,一个是对应的值,另一个是键或者下标
  3. :key需要动态绑定一个值,保证每个li的唯一性,这里用的是数组下标。
  4. 插值语法中的变量也可以来自v-for中的形参。

(二)案例演示

  • 遍历一个数组,数组中储存的是对象,那么遍历拿到的就是对象
<ul id="ulTest" >
        <li v-for="(obj,key) in peoples" :key="key">
            {{obj.name}}-{{obj.age}}-love:{{obj.love}}
        </li>
</ul>
<script>
    new Vue({
        el: "#ulTest",
        data:{
            peoples:[
                {name:"路飞",age: 23,love:"雏田"},
                {name:"鸣人",age: 19, love:"娜美"},
                {name:"萧炎",age: 22, love:"美杜莎"}
            ]
        }
    })
</script>

效果:

 (三)案例使用的key绑定为数组下标的隐患

       一、Vue的虚拟dom对比算法,那我们修改上面的例子为例,仅展示增加部分

 <button @click="addPeople">点我添加新人</button>

---------------------------
methods:{
            addPeople(){
                var wang = {name:"老王",age: 22,love: "云韵"};
                //将新人推入数组,注意从前面进入
                this.peoples.unshift(wang);
            }
        }
  • 这里我们增加了一个按钮,实现点击增加新人。那么在这个过程中虚拟dom是如何实现对比算法的呢?
  1. 页面加载时的虚拟dom中有三个对象,分别是路飞、鸣人、萧炎,然后我们点击按钮,数组中的数据发生变化了,就会触发虚拟dom的对比算法,对比算法根据key值确定对比双方

 

 这样还会连累无辜,导致出错,例如每个li中都加了一个输入框

<li v-for="(obj,key) in peoples" :key="key">
            {{obj.name}}-{{obj.age}}-love:{{obj.love}}
            <input>
        </li>

加载完页面后,我们在输入框输入各自对应的数据,

然后点击添加新人错误出现:input内容全乱了!

 

原因: 

  •  解决方法,
  1. 将数据从后面插入。
  2. 将key值指定为每个对象中的唯一值,这样key的对应对象就固定了,那么diff算法对比的对象就都一样了。

十一、列表过滤

(一)用监听属性来实现

<div id="filterTest">
        <h1>列表搜索</h1>
        <!-- v-model绑定到Vue,让Vue监测到变化-->
        <input type="text" placeholder="请输入要搜索的关键字" v-model="inContent">
        <ul>
            <li v-for="value in needPeoples" :key="value.id">
                {{value.name}}--{{value.age}}--love:{{value.love}}
            </li>
        </ul>
    </div>
<script>
    new Vue({
        el: "#filterTest",
        data:{
            inContent:"" ,//默认为空串
            peoples:[//数据源
                {id:"001",name:"路飞",age: 23,love:"雏田"},
                {id:"002",name:"鸣人",age: 19, love:"娜美"},
                {id:"003",name:"萧炎",age: 22, love:"美杜莎"},
                {id:"004",name:"老王",age: 22,love: "云韵"}
        ],
           needPeoples:[]
        },
        watch:{
            inContent:{
                immediate: true,
                //让函数开始就执行一次,即看是否包含空字符,肯定包含全部展示
                 //创建数组处理后返回
            handler(val){
                 var shuzu = [];
                //查看数据中的值是不是包含输入框中的值
                this.needPeoples = this.peoples.filter((p)=>{
                   return  p.name.includes(val);
                })
                }
         }      
        }       
    })
</script>

(二)用计算属性实现

<div id="filterTest">
        <h1>列表搜索</h1>
        <!-- v-model绑定到Vue,让Vue监测到变化-->
        <input type="text" placeholder="请输入要搜索的关键字" v-model="inContent">
        <ul>
            <li v-for="value in needPeoples" :key="value.id">
                {{value.name}}--{{value.age}}--love:{{value.love}}
            </li>
        </ul>
    </div>
   <script>
    new Vue({
        el: "#filterTest",
        data:{
            inContent:"" ,//默认为空串
            peoples:[//数据源
                {id:"001",name:"路飞",age: 23,love:"雏田"},
                {id:"002",name:"鸣人",age: 19, love:"娜美"},
                {id:"003",name:"萧炎",age: 22, love:"美杜莎"},
                {id:"004",name:"老王",age: 22,love: "云韵"}
        ],
        },
        computed:{
            needPeoples:{
                get(){
                    return this.peoples.filter((p)=>{
                        return p.name.includes(this.inContent);
                    })
                }
            }
        }
    })
</script>

(三)在给表格添加根据年龄排序的功能

<div id="filterTest">
        <h1>列表搜索</h1>
        <!-- v-model绑定到Vue,让Vue监测到变化-->
        <input type="text" placeholder="请输入要搜索的关键字" v-model="inContent">
        <button @click="sortType = 1" >年龄正序</button>
        <button @click="sortType = 2">年龄逆序</button>
        <button @click="sortType = 0">原顺序</button>
        <ul>
            <li v-for="value in needPeoples" :key="value.id">
                {{value.name}}--{{value.age}}--love:{{value.love}}
            </li>
        </ul>
    </div>
   <script>
    new Vue({
        el: "#filterTest",
        data:{
            sortType: 0,
            inContent:"" ,//默认为空串
            peoples:[//数据源
                {id:"001",name:"路飞",age: 23,love:"雏田"},
                {id:"002",name:"路阳",age: 34,love:"雏田"},
                {id:"003",name:"花路",age: 12,love:"雏田"},
                {id:"004",name:"鸣炮",age: 23,love:"雏田"},
                {id:"005",name:"鸣人",age: 19, love:"娜美"},
                {id:"006",name:"萧炎",age: 22, love:"美杜莎"},
                {id:"007",name:"老王",age: 13,love: "云韵"}
        ],
        },
        computed:{
            needPeoples:{
                //每当计算变量依赖的Vue变量发生变化,getter都会再次执行
                get(){
                    //先用变量承接,以后排序在此基础上进行,保证在搜索中的数据排序
                    const arrMe = this.peoples.filter((p)=>{
                        return p.name.includes(this.inContent);
                    });
                    //在这里判断排序的类型0为正常顺序,1为正序,2为逆序
                    //判断,默认为0即为false,不会执行排序,即原顺序
                    if(this.sortType){
                        arrMe.sort((a,b)=>{
                            return (this.sortType == 1)? b.age - a.age:a.age - b.age;
                        })
                    }
                    //记得返回
                    return arrMe;
                }
            }
        }
    })
</script>

 十一、Vue如何实现对自身实例中属性的监控?

(一)重温Vue中的数据

  • Vue中的数据都在data中,分为数组和对象两种类型。在其中声明的数据会受到Vue实例vm的管理
  • 那么如何管理?
  • 就对象而言,当vm创建完成之后,Vue中data中的对象以及对象中的每个键都会被增加getter和setter方法,放在vm._data这个属性中,同时数据代理到了vm.一级属性名中.
  1. 如下
<!-- Vue数据监测测试,作如下结构-->
    <div id="seeText">
      <ul>
        <li>{{people.name}}--{{people.age}}</li>
      </ul>
    </div>
</body>
<script>
    var vm =new Vue({
        el:"#seeText",
        data:{
            people:{
                name:"路飞",
                age: 34
            }
        }
    })

3.上面的数据在生成页面之后people对象中间的数据都交给了vm实例管理,对象中的各个属性也都被数据劫持,增加了对应的getter和setter,以实现响应式(响应式就是当people中的数据改变时就会调用setter,setter中会引起整个模版用到该属性的位置重新加载。所以对象的属性拥有setter和getter很重要,这也是属性被Vue实例监测的重要条件。

  • 就数组而言,如下,
 <!-- Vue数据监测测试,作如下结构-->
    <div id="seeText">
      <ul>
        <li>{{people[0]}}--{{people[1]}}</li>
      </ul>
    </div>
</body>
<script>
    var vm =new Vue({
        el:"#seeText",
        data:{
            people:["路飞",34]
        }
    })
</script>
  1. 数组在Vm中数据没有对应的getter,setter来监控数据的变化,但是Vue是采用将数组中原生的对原数组有影响的方法做了强化,当页面生成后,被Vue管理的数组调用的像push、pop,shift,unshift等等方法,都被强化过,调用修改后还是会被监测,并及时响应到页面。

(二)那如何在vm形成后(即页面完成后)再添加属性到Vue中,且实现响应式?

一、错误的写法,还以上例为例。

  • 对象数据已经确定,我们想要再添加love属性到Vue中且会被自动解析到页面上。
<!-- Vue数据监测测试,作如下结构-->
    <div id="seeText">
      <ul>
        <li>{{people.name}}--{{people.age}}--{{people.love}}</li>
      </ul>
    </div>
</body>
<script>
    var vm =new Vue({
        el:"#seeText",
        data:{
            people:{name:"路飞",age:34}
        }
    })
</script>

加载完页面如下:

 我们模仿用户在vm中添加love属性。

添加完后,love的数据并没有被解析,这说明数据虽然添加了,但是Vue并没有发现属性值的增加,而新添加的属性也绝没有setter和getter。

  • 数组对象已确定,要在页面加载完成后,向数组添加新值和修改元素值,并且要求被响应
<body>
    <!-- Vue数据监测测试,作如下结构-->
    <div id="seeText">
      <ul>
        <li>{{people[0]}}--{{people[1]}}--{{people[2]}}</li>
      </ul>
    </div>
</body>
<script>
    var vm =new Vue({
        el:"#seeText",
        data:{
            people:["路飞",34]
        }
    })
</script>

 

 二、根据上面知识给出正确方法:

  • 数组

应使用语句:

修改值,使用splice函数

vm._data.people.splice(0,1,"鸣人");

增加值,使用push();

 可见都修改成功

  • 对象

应使用语句

格式:

Vue.set(要添加属性的对象,要添加或修改的属性,属性值);

或者

vm.$set((要添加属性的对象,要添加或修改的属性,属性值); 

具体:

vm.$set(vm._data.people,"love","雏田");

Vue.set(vm._data.people,"love","雏田");

 

  十二、利用v-model进行的表单数据同步及细节

  • 首先创建一个具有各种类型的表单
 
<!-- 阻止默认行为 -->
    <form id="formGet" @submit.prevent="printInfo">
        账号:<input type="text" v-model="custer"><br>
        密码:<input type="password" v-model="pass"><br>
        性别:<!--因为v-model自动同步的是value值,而单选框没有输入所以要指定-->
        男<input type="radio" v-model="sex"  name="sex" value="male">
        女<input type="radio" v-model="sex" name="sex" value="female"><br>
        兴趣:
        打篮球<input type="checkbox" v-model="inster" value="basketball">
        跳舞<input type="checkbox" v-model="inster" value="dance">
        下棋<input type="checkbox" v-model="inster" value="chess"><br>
        选择城市:
        <select v-model="city">
            <option value="shanghai">上海</option>
            <option value="beijing">北京</option>
            <option value="shenzhen">深圳</option>
            <option value="zhengzhou">郑州</option>
        </select><br>
        其他信息:
        <textarea v-model="it"></textarea><br>
        <input type="checkbox" v-model="agree">是否同意协议<a>某某协议</a><br>
        提交信息:<input type="submit">
    </form>
<script>
    new Vue({
        el: "#formGet",
        data:{
            custer:"",
            pass: "",
            sex: "",
            inster: [],//这里注意因为多选框,所以要用数组接收,可能的多个值。
            city: "",
            it: "",
            agree: ""
        },
        methods:{
            printInfo(){
                //将收集到的信息打印到控制台,虽然_data有getter和setter但是转换成json的只有数据。
                console.log(JSON.stringify(this._data));
            }
        }
    })
</script>

效果:

 

  •  单选框和多选框要注意的点:
  1. v-model要用数组接收,同时每个多选框都要指定value的值
  2. 当多选框只有一个时,就会统计是否选中,值为布尔值
  3. 当单选框没指定value时,则默认收集的是checked的内容(布尔值),即是否被选中。
  • 如何用修饰符限制v-model收集的model类型,如下

<input type="number" v-model.number="age">

这样的话收集到的数据都会转化为数值

  • v-model的其他修饰符:
  1. v-model.trim 去掉前后的空格
  2. v-model.lazy v-model的数据同步要等到元素失去焦点再执行 m
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值