当前位置:   article > 正文

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

vue尚硅谷笔记

一、vue学习的基本语法

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

  1. <form action="">
  2. <input v-model="name">
  3. </form>

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

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

 (一)mvvm模型

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

(二)Object.defineproperty()

  • 函数有三个参数:

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

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

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

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

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

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

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

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

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

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

控制台输出内容:

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

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

控制台内容如下:

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

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

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

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

也能阻止冒泡

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

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

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

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

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

 四、按键别名与键盘事件

(一)什么是按键别名?

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

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

  1. <form action="" id="formContainer">
  2. <input type="text" placeholder="输入完内容后点击回车!" @keyup="keyMethod">
  3. </form>
  4. <script>
  5. new Vue({
  6. el: "#formContainer",
  7. methods:{
  8. keyMethod(ev){
  9. console.log("您按的键是:" + ev.key);
  10. }
  11. }
  12. })
  13. </script>

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

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

(二)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中内容也要发生改变。
  1. <form action="" id="formContainer">
  2. <input type="text" v-model="firstName"><br><br>
  3. <input type="text" v-model="lastName"><br><br>
  4. <!--直接动态绑定input输入框的值到Vue的属性,实现span内容自动更新-->
  5. <span>{{firstName}}-{{lastName}}</span>
  6. </form>
  7. <script>
  8. var vm = new Vue({
  9. el: "#formContainer",
  10. data:{
  11. firstName: "陈",
  12. lastName: "湫"
  13. },
  14. methods:{
  15. keyMethod(ev){
  16. console.log("您按的键是:" + ev.key);
  17. }
  18. }
  19. });
  20. </script>

 (二)Vue的计算属性

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

最终效果和上面一致。

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

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

 属性值也跟着变化:

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

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

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

六、监视属性

(一)什么是监视属性?

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

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

 (二)监视属性案例练习

  1. <div id="weatherTest">
  2. <span>我爱着{{rel}}!</span><br>
  3. <button @click="changeWeather">点我改变天气</button>
  4. </div>
  5. <script>
  6. new Vue({
  7. el: "#weatherTest",
  8. data: {
  9. season: "冬天"
  10. },
  11. computed: {
  12. rel(){
  13. if(this.season == "冬天"){
  14. return "北风吹雪";
  15. }else if(this.season == "春天"){
  16. return "鸟语花香"
  17. }
  18. }
  19. },
  20. methods:{
  21. changeWeather(){
  22. if(this.season == "冬天"){
  23. this.season = "春天";
  24. }else{
  25. this.season = "冬天";
  26. }
  27. }
  28. },
  29. watch:{
  30. season:{
  31. //immediate: true, //在值发生变化之前先执行一次函数
  32. handler(newValue,oldValue){
  33. console.log("值发生了改变,改变前是:" + oldValue + "\n改变后的值是:" + newValue);
  34. }
  35. }
  36. }
  37. })
  38. </script>

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

  •  另一种监视写法:

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

(三)深度属性监视 

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

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

  1. <div id="deepSeeContainer">
  2. <span>a的值是:{{number.a}}</span><br>
  3. <button @click="number.a++">点我给a的值加1</button><br>
  4. <span>b的值是:{{number.b}}</span><br>
  5. <button @click="number.b++">点我给a的值加1</button>
  6. </div>
  7. <script>
  8. new Vue({
  9. el: "#deepSeeContainer",
  10. data:{
  11. number:{
  12. a: 1,
  13. b: 2
  14. }
  15. },
  16. watch:{
  17. "number.a":{
  18. //注意监视层级结构的语法,加引号是因为键本来就只能是字符串,不过我们习惯直接写了,这里却不允许去掉引号
  19. handler(newValue,oldValue){
  20. console.log("a的值发生了改变,原来的值是:" + oldValue)
  21. }
  22. }
  23. }
  24. });
  25. </script>

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

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

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

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

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

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

(一)class样式绑定练习

  • 首先我们要明确一点:
  • 下面这种情况div是可以同时使用上面三种样式的:
    1. <style>
    2. .one{
    3. }
    4. .two{
    5. }
    6. .three{
    7. }
    8. </style>
    9. <div class="one two three"></div>
  • 用数组方式实现div三种样式的随机切换:
  1. <style>
  2. .one{/*div的基础样式*/
  3. border:2px solid green;
  4. border-radius: 3px;
  5. width: 200px;
  6. height: 200px;
  7. }
  8. .two{
  9. background-color:aquamarine;
  10. }
  11. .three{
  12. background-color:brown;
  13. }
  14. .four{
  15. background-color:aliceblue;
  16. }
  17. </style>
  18. <body>
  19. </div>
  20. <div id="classShuan" class="one" :class="colorChoose" @click="changeColor"></div>
  21. <script>
  22. new Vue({
  23. el:"#classShuan",
  24. data:{
  25. colorChoose: "two",
  26. //这个属性我们利用函数把它的值随机化
  27. //而它又被上面的class属性绑定到,所以class选择也是随机的
  28. },
  29. methods:{
  30. changeColor(){
  31. var colorArr = ["two","three","four"];
  32. //生成一个0到3的随机整数,不包括3,把数组下标随机化
  33. var downIndex = Math.floor(Math.random()*3);
  34. //修改colorChoose的值
  35. this.colorChoose = colorArr[downIndex];
  36. //最后要把该函数绑定到div点击事件上,实现点击随机切换三种效果
  37. }
  38. }
  39. })
  40. </script>
  41. </body>

测验通过!

  • 用数组的方式动态让用户改变样式,用对象的方式
  1. <style>
  2. .one{/*div的基础样式*/
  3. border:2px solid green;
  4. border-radius: 3px;
  5. width: 200px;
  6. height: 200px;
  7. }
  8. /* 让按钮在div元素的下方居中不动 */
  9. #classShuan div{
  10. margin: 140px auto auto auto;
  11. text-align: center;
  12. }
  13. .five{
  14. text-shadow: 3px 3px 5px red;
  15. /*添加文字阴影效果*/
  16. }
  17. .six{
  18. text-align: center;
  19. }
  20. </style>
  21. <body>
  22. <div id="classShuan" class="one" :class="colorChoose">
  23. <span>我是神仙不下凡</span>
  24. <div>
  25. <button @click="addTextShadow">点我增加文本阴影</button>
  26. <button @click="addTextCenter">点我让文字居中</button>
  27. </div>
  28. </div>
  29. <script>
  30. new Vue({
  31. el:"#classShuan",
  32. data:{
  33. colorChoose:{
  34. "five": false,
  35. "six": false
  36. //这时候我们动态绑定到class的是一个对象,
  37. //这个对象的键就是我们要动态添加的class,只有为true时才会生效
  38. },
  39. },
  40. methods:{
  41. addTextShadow(){
  42. this.colorChoose.five = true;//增加文字阴影的函数,绑定到按钮上
  43. },
  44. addTextCenter(){
  45. this.colorChoose.six = true;//增加文字居中的函数,绑定到按钮上
  46. }
  47. }
  48. })
  49. </script>
  50. </body>

 点击第一个按钮效果:

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

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

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

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

   2 .Vue动态绑定的写法

  1. <body>
  2. <span :style="myStyleObj">我是神仙不下凡</span>
  3. <script>
  4. new Vue({
  5. el:"#classShuan",
  6. data:{
  7. myStyleObj:{
  8. fontSize: "48px",
  9. //这是样式对象内部,键值就是要修改的样式属性名
  10. //跟原来不一样的是要改成驼峰命名法
  11. }
  12. },
  13. });
  14. </script>
  15. </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的绑定值即可
  1. <div id="classShuan" class="one" :class="colorChoose" v-if="a">
  2. <span :style="myStyleObj">我是神仙不下凡</span>
  3. <div>
  4. <button @click="addTextShadow">点我增加文本阴影</button>
  5. <button @click="addTextCenter">点我让文字居中</button>
  6. </div>
  7. </div>
  8. <script>
  9. var vmMe = new Vue({
  10. el:"#classShuan",
  11. data:{
  12. colorChoose:{
  13. "five": false,
  14. "six": false
  15. //这时候我们动态绑定到class的是一个对象,
  16. //这个对象的键就是我们要动态添加的class,只有为true时才会生效
  17. },
  18. myStyleObj:{
  19. fontSize: "48px",
  20. //这是样式对象内部,键值就是要修改的样式属性名
  21. //跟原来不一样的是要改成驼峰命名法
  22. },
  23. a: true
  24. },
  25. </script>

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

  • v-if可以和v-else-if以及v-else一起使用实现多级判断。
  1. <div id="ifTest">
  2. <div v-if="a == 1">第一个</div>
  3. <div v-else-if="a == 2">第二个</div>
  4. <div v-else>最后一个</div>
  5. </div>
  6. <script>
  7. var vmIf = new Vue({
  8. el: "#ifTest",
  9. data:{
  10. a: 0,//默认设置为零
  11. }
  12. })
  13. </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中的形参。

(二)案例演示

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

效果:

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

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

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

 

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

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

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

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

 

原因: 

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

十一、列表过滤

(一)用监听属性来实现

  1. <div id="filterTest">
  2. <h1>列表搜索</h1>
  3. <!-- v-model绑定到Vue,让Vue监测到变化-->
  4. <input type="text" placeholder="请输入要搜索的关键字" v-model="inContent">
  5. <ul>
  6. <li v-for="value in needPeoples" :key="value.id">
  7. {{value.name}}--{{value.age}}--love:{{value.love}}
  8. </li>
  9. </ul>
  10. </div>
  11. <script>
  12. new Vue({
  13. el: "#filterTest",
  14. data:{
  15. inContent:"" ,//默认为空串
  16. peoples:[//数据源
  17. {id:"001",name:"路飞",age: 23,love:"雏田"},
  18. {id:"002",name:"鸣人",age: 19, love:"娜美"},
  19. {id:"003",name:"萧炎",age: 22, love:"美杜莎"},
  20. {id:"004",name:"老王",age: 22,love: "云韵"}
  21. ],
  22. needPeoples:[]
  23. },
  24. watch:{
  25. inContent:{
  26. immediate: true,
  27. //让函数开始就执行一次,即看是否包含空字符,肯定包含全部展示
  28. //创建数组处理后返回
  29. handler(val){
  30. var shuzu = [];
  31. //查看数据中的值是不是包含输入框中的值
  32. this.needPeoples = this.peoples.filter((p)=>{
  33. return p.name.includes(val);
  34. })
  35. }
  36. }
  37. }
  38. })
  39. </script>

(二)用计算属性实现

  1. <div id="filterTest">
  2. <h1>列表搜索</h1>
  3. <!-- v-model绑定到Vue,让Vue监测到变化-->
  4. <input type="text" placeholder="请输入要搜索的关键字" v-model="inContent">
  5. <ul>
  6. <li v-for="value in needPeoples" :key="value.id">
  7. {{value.name}}--{{value.age}}--love:{{value.love}}
  8. </li>
  9. </ul>
  10. </div>
  11. <script>
  12. new Vue({
  13. el: "#filterTest",
  14. data:{
  15. inContent:"" ,//默认为空串
  16. peoples:[//数据源
  17. {id:"001",name:"路飞",age: 23,love:"雏田"},
  18. {id:"002",name:"鸣人",age: 19, love:"娜美"},
  19. {id:"003",name:"萧炎",age: 22, love:"美杜莎"},
  20. {id:"004",name:"老王",age: 22,love: "云韵"}
  21. ],
  22. },
  23. computed:{
  24. needPeoples:{
  25. get(){
  26. return this.peoples.filter((p)=>{
  27. return p.name.includes(this.inContent);
  28. })
  29. }
  30. }
  31. }
  32. })
  33. </script>

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

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

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

(一)重温Vue中的数据

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

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

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

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

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

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

加载完页面如下:

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

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

  • 数组对象已确定,要在页面加载完成后,向数组添加新值和修改元素值,并且要求被响应
  1. <body>
  2. <!-- Vue数据监测测试,作如下结构-->
  3. <div id="seeText">
  4. <ul>
  5. <li>{{people[0]}}--{{people[1]}}--{{people[2]}}</li>
  6. </ul>
  7. </div>
  8. </body>
  9. <script>
  10. var vm =new Vue({
  11. el:"#seeText",
  12. data:{
  13. people:["路飞",34]
  14. }
  15. })
  16. </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进行的表单数据同步及细节

  • 首先创建一个具有各种类型的表单
  1. <!-- 阻止默认行为 -->
  2. <form id="formGet" @submit.prevent="printInfo">
  3. 账号:<input type="text" v-model="custer"><br>
  4. 密码:<input type="password" v-model="pass"><br>
  5. 性别:<!--因为v-model自动同步的是value值,而单选框没有输入所以要指定-->
  6. <input type="radio" v-model="sex" name="sex" value="male">
  7. <input type="radio" v-model="sex" name="sex" value="female"><br>
  8. 兴趣:
  9. 打篮球<input type="checkbox" v-model="inster" value="basketball">
  10. 跳舞<input type="checkbox" v-model="inster" value="dance">
  11. 下棋<input type="checkbox" v-model="inster" value="chess"><br>
  12. 选择城市:
  13. <select v-model="city">
  14. <option value="shanghai">上海</option>
  15. <option value="beijing">北京</option>
  16. <option value="shenzhen">深圳</option>
  17. <option value="zhengzhou">郑州</option>
  18. </select><br>
  19. 其他信息:
  20. <textarea v-model="it"></textarea><br>
  21. <input type="checkbox" v-model="agree">是否同意协议<a>某某协议</a><br>
  22. 提交信息:<input type="submit">
  23. </form>
  24. <script>
  25. new Vue({
  26. el: "#formGet",
  27. data:{
  28. custer:"",
  29. pass: "",
  30. sex: "",
  31. inster: [],//这里注意因为多选框,所以要用数组接收,可能的多个值。
  32. city: "",
  33. it: "",
  34. agree: ""
  35. },
  36. methods:{
  37. printInfo(){
  38. //将收集到的信息打印到控制台,虽然_data有getter和setter但是转换成json的只有数据。
  39. console.log(JSON.stringify(this._data));
  40. }
  41. }
  42. })
  43. </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
本文内容由网友自发贡献,转载请注明出处:https://www.wpsshop.cn/w/小丑西瓜9/article/detail/69899
推荐阅读
相关标签
  

闽ICP备14008679号