2day,Vue基础语法(二)

Vue基础语法(二)

1.v-on绑定事件

v-on的使用
缩写:@
参数:event
用法:绑定事件回调函数

1.1 基本使用

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <style>
      .box{
        width: 100px;
        height: 100px;
        background-color: orange;
        margin-top: 10px;
      }
    </style>
  </head>
  <body>
    <div id="app">
      <!-- 基本使用 -->
      <div class="box" v-on:click="divClick"></div>
      <!-- 简写 重点掌握 -->
      <div class="box" @click="divClick"></div>
      <!-- 不推荐 绑定方法的时候也可以写一个表达式 -->
      <h2>{{counter}}</h2>
      <button @click="add">+1</button>
      <button @click="counter--">-1</button>
      <!-- 绑定其他事件 -->
      <div class="box" @mousemove="divMouse">66</div>
      <!-- 绑定多个事件 -->
      <div class="box" @mousemove="divMouse" @click="divClick">66</div>
      <!-- 一个事件类型绑定多个事件处理函数 -->
      <div class="box" @mousemove="divMouse" @click="[divClick,divMouse]">66</div>
      <!-- 多个事件2 -->
      <div class="box" v-on="{click:divClick,mousemove:divMouse}">88</div>
      <div class="box" @="{click:divClick,mousemove:divMouse}">88</div>
    </div>
    <script src="../lib/vue.js"></script>
    <script>
      const app = Vue.createApp({
        data(){
          return {
            counter:0,
          }
        },
        methods: {
          divClick(){
            console.log("6666");
          },
          add(){
            this.counter++;
          },
          divMouse(){
            console.log("鼠标移动了");
          }
        }
      });
      app.mount("#app");
    </script>
  </body>
</html>


1.2 参数的传递

你要传递的参数就得在@绑定的时候加上(),就可以将需要传递的参数写入小括号中,不需要就不加

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <div id="app">
      <!-- 默认传递 event -->
      <button @click="btn1">按钮1</button>
      <!-- 有自己的参数 -->
      <button @click="btn2(username,age)">按钮2</button>
      <!-- 自己的参数和event我都要 -->
      <!-- 明确告知vue需要事件对象 -->
      <!-- 手动在添加一个$event -->
      <button @click = btn3()(username,age)>按钮3</button>
    </div>
    <script src="../lib/vue.js"></script>
    <script>
      const app = Vue.createApp({
        data(){
          return {
            username:"alex",
            age:18
          }
        },
        methods: {
          // 绑定时没有传递任何参数的情况下,event对象会被默认传递进来
          btn1(event){
            console.log(event.target);
          },
          btn2(name,age,event){
            console.log(name,age);
            console.log(event);
          },
          btn3(){
            // console.log(a,b,c);
            console.log(e);
            return function name(username,age) {
              console.log(username,age);
              console.log(e);
            }
          }
        }
      });
      app.mount("#app");
    </script>
  </body>
</html>


1.3 修饰符
常用的是stop阻止冒泡,剩下的看看文档就好:
地址:https://cn.vuejs.org/guide/essentials/event-handling.html#key-modifiers

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <style>
      .box{
        width: 100px;
        height: 100px;
        background-color: aquamarine;
      }
    </style>
  </head>
  <body>
    <div id="app">
      <div class="box" @click.self="haha">
        <button @click="btn">按钮</button>
      </div>
      <form action="" @submit.prevent>
        <input type="submit" value="提交">
      </form>
      <a href="https://www.baidu.com" @click.prevent>去往百度</a>
    </div>
    <script src="../lib/vue.js"></script>
    <script>
      const app = Vue.createApp({
        data(){
          return {
          }
        },
        methods: {
          btn(e){
            // e.stopPropagation();
            console.log("按钮被点击了");
          },
          haha(){
            console.log("盒子被点击了");
          }
        }
      });
      app.mount("#app");
    </script>
  </body>
</html>


2.Vue的条件渲染

根据某些条件来渲染某些元素/组件
v-if
v-else
v-else if
v-show

2.1 demo

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <div id="app">
      <!-- 如果cars 为空,整个ul不显示 -->
      <ul v-if="cars.length > 0">
        <li v-for="good in cars">{{good}}</liv-for>
      </ul>
      <!-- if不展示的时候展示else的东西 -->
      <h2 v-else>🛒为空,快点去淘点东西~~~~</h2>
    </div>
    <script src="../lib/vue.js"></script>
    <script>
      const app = Vue.createApp({
        data(){
          return {
            cars:["xx","qt","zd","rb"],
          }
        },
        methods: {
        }
      });
      app.mount("#app");
    </script>
  </body>
</html>


v-if,v-else,v-else if用于根据条件来渲染某一块内容,只有条件为true时才会渲染,这三个指令与if、else、else if类似

2.2 v-if、v-else使用

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <div id="app">
      <!-- person 由内容的时候展示人的信息 姓名+年龄 -->
      <!-- 为空对象时,不展示 -->
      <div v-if="Object.keys(person).length">
        <h2>个人信息</h2>
        <p>姓名:{{person.name}}</p>
        <p>年龄:{{person.age}}</p>
      </div>
      <div v-else>
        <h2>没有输入信息</h2>
        <p>请输入个人信息</p>
      </div>

    </div>
    <script src="../lib/vue.js"></script>
    <script>
      const app = Vue.createApp({
        data() {
          return {
            person: {
              // name: "lyan",
              // age: 18,
            },
          };
        },
        methods: {
          a(){
            JSON.stringify
          }
        },
      });
      app.mount("#app");
    </script>
  </body>
</html>


2.3 v-else-if

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <div id="app">
      <!-- 90分及以上为 1 80分及以上为 2 60及以上80以下为 3 60以下 4-->
      <h2 v-if="result >= 90">男神</h2>
      <h2 v-else-if="result >= 80">好人</h2>
      <h2 v-else-if="result >= 60">正常人</h2>
      <h2 v-else>ZD</h2>
    </div>
    <script src="../lib/vue.js"></script>
    <script>
      const app = Vue.createApp({
        data() {
          return {
            result: 59,
          };
        },
        methods: {},
      });
      app.mount("#app");
    </script>
  </body>
</html>


2.4 template

用于控制一组元素,但是又不想使用没有意义的div或者其他元素

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <div id="app">
      <!-- 我们加了一个div的目的是为了控制多个元素的渲染与否,但是这个div是一个多余的dom结构,这个时候我们呢可以选择使用template来优化 -->
      <template v-if="Object.keys(person).length">
        <h2 @click="a">个人信息</h2>
        <p>姓名:{{person.name}}</p>
        <p>年龄:{{person.age}}</p>
      </template>
      <div v-else>
        <h2>没有输入信息</h2>
        <p>请输入个人信息</p>
      </div>

      

    </div>
    <script src="../lib/vue.js"></script>
    <script>
      const app = Vue.createApp({
        data() {
          return {
            person: {
              name: "lyan",
              age: 18,
            },
          };
        },
        methods: {
          a(){
            console.dir(document.createElement("div"));
          }
        },
      });
      app.mount("#app");
    </script>
  </body>
</html>


2.5 v-show

v-show后面的条件为true的时候展示,为false不展示和if看起来一样

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <div id="app">
      <button @click="toggle">切换</button>
      <img v-show="isShow" src="https://t7.baidu.com/it/u=727460147,2222092211&fm=193&f=GIF" alt="">
    </div>
    <script src="../lib/vue.js"></script>
    <script>
      const app = Vue.createApp({
        data(){
          return {
            isShow:true,
          }
        },
        methods: {
          toggle(){
            this.isShow = !this.isShow;
          }
        }
      });
      app.mount("#app");
    </script>
  </body>
</html>


v-show和v-if的区别:
本质区别:v-show是通过display:none来让元素消失,而v-if直接把整个don结构都干掉了,v-if=-“false”的时候,其对应的原声dom压根都不会渲染
用法的区别:v-show不支持template,v-show不能v-else一起用
实际开发中:如果是频繁切换那就用v-show,如果不频繁就是用v-if

3.列表渲染(掌握)

1.v-for的时候 给它绑定唯一的key
2.v-for的时候不要使用数组的index作为key
真实开发中,拿到一组数据并且需要渲染,这个时候我们不会一个个的去写,而是使用v-for来完成,v-for类似于js的循环,可以遍历一组数据
比如说京东的商品列表
使用v-for来渲染一组数据,就是我们常说的列表渲染

3.1 v-for的基本使用

v-for的基本格式:“item in 数组”
数组通常是来自于data或者prop,或者请求
item是我们起的一个别名,这个别名可以自定义

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <div id="app">
      <h2>电影列表</h2>
      <ul>
        <li v-for="moive in moives">
          电影名称:{{moive}}
        </li>
      </ul>
    </div>
    <script src="../lib/vue.js"></script>
    <script>
      const app = Vue.createApp({
        data(){
          return {
            moives:[' 哆啦A梦','复仇者联盟','蜘蛛侠']
          }
        },
        methods: {
        }
      });
      app.mount("#app");
    </script>
  </body>
</html>


在我们遍历一个数组的时候,往往可能需要拿到索引来做一些操作
如果在v-for中你需要用到索引的话,v-for=“(item,index) in arr”
注意:item和index的顺序

      <ul>
        <li v-for="(moive,index) in moives">
          电影名称:{{index+1}}-----{{moive}}
        </li>
      </ul>

实际工作中,我们需要渲染的数组往往会比较复杂
渲染稍微复杂一点的数组

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <div id="app">
      <h2>电影列表</h2>
      <ul>
        <li v-for="(moive,index) in moives">
          电影名称:{{index+1}}-----{{moive}}
        </li>
      </ul>
      <h2>商品列表</h2>
      <ul>
        <li v-for="good in goods">
          <p>商品名称:{{good.name}}</p>
          <p>商品价格:{{good.price}}</p>
        </li>
      </ul>
    </div>
    <script src="../lib/vue.js"></script>
    <script>
      const app = Vue.createApp({
        data(){
          return {
            moives:[' 哆啦A梦','复仇者联盟','蜘蛛侠'],
            goods:[
              {name:'mbp',price:1999},
              {name:'imac',price:2999},
              {name:'iphone',price:3999},
            ]
          }
        },
        methods: {
        }
      });
      app.mount("#app");
    </script>
  </body>
</html>


3.2 v-for的其他类型

v-for还支持
对象
数字
字符串(所有的可迭代对象)

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <div id="app">
      <ul>
        <!-- 只要你写了两个或以上的别名,就必须要小括号 -->
        <li v-for="(value,key,index) in info">
          {{value}}----{{key}}----{{index}}
        </li>
      </ul>
      <ul>
        <!-- num就是每个数字,从1 开始 -->
        <li v-for="(num,index) in 10">{{num}}---{{index}}</li>
      </ul>

      <!-- 遍历字符串,str就是单个字符 -->
      <ul>
        <li v-for="str in msg">{{str}}</li>
      </ul>

        // 类似v-if,如果外层的div没有实际的意义,可以用template替换
      <template v-for="item in persons">
        <p>{{item.name}}</p>
        <p>{{item.age}}</p>
        <p>{{item.height}}</p>
      </template>
    </div>
    <script src="../lib/vue.js"></script>
    <script>
      const app = Vue.createApp({
        data() {
          return {
            info: {
              name: "jack",
              age: 18,
              height: 1.88,
            },
            msg: "hello vue",
            persons: [
              {
                name: "jack",
                age: 18,
                height: 1.88,
              },
              {
                name: "alex",
                age: 18,
                height: 1.88,
              },
              {
                name: "hy",
                age: 18,
                height: 1.88,
              },
            ],
          };
        },
        methods: {},
      });
      app.mount("#app");
    </script>
  </body>
</html>


3.3 数组的更新检测

vue2和vue3区别,vue2使用类似this.arr[0]="123"是不能触发视图的更新的,因为Object.defineproperty并不能监听一个对象0的访问和修改,但是vue3可以,因为他用的proxy。vue2的解决方案是采用Vue.set()
其实Vue内部将所有的变更数组的方法进行了重写,保证他们对数组的操作能够被监听到。能够触发视图更新
push:尾部添加
pop:尾部删除
unshift:头部添加
shift:头部删除
splice:任意位置 添加/删除/替换
sort:排序
reverse:反转
slice:截取

3.4 v-for中key的作用

官方:
key属性主要用于Vue的虚拟DOM算法,在新旧Vnode对比辨识Vnode;
如果不使用key,Vue会使用一种最大限度减少动态元素并且尽可能地尝试就地修改/复用相同类型的元素的算法
使用key时,他会基于key的变化重新排列元素的顺序,并且移除/销毁key不存在的元素。
个人:差量更新,就地复用
认识Vnode
因为还没有学习组件,所以我们暂时理解html元素创建出来的vnode
Virtual Node:虚拟节点:无论是组件还是html元素,在vue中都会解析成一个个的虚拟的节点
Vnode本质就是一个js对象

<div class="title" style="font-size: 30px; color: red">哈哈哈</div>
    <script>
      const vnode = {
        type:"div",
        props:{
          class:"title",
          style:{
            'font-size':'30px',
            color:"red"
          }
        },
        children:"哈哈哈哈"
      }
    </script>

vue在解析模版的时候,会把里面的一个个标签都抽象成一个个vnode,实际上我们的页面不只是上述简单的一个div构成,而是许多元素,这些元素被抽象后,最终会形成像真实DOM一样的树结构,这个结构就是VDOM
也就是多个vnode构成的一个相对较大的js对象而已。
插入f案例

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <div id="app">
      <button @click="inserFn">插入f</button>
      <ul>
        <li v-for="item in letters" :key="item">{{item}}</li>
      </ul>
    </div>
    <script src="../lib/vue.js"></script>
    <script>
      const app = Vue.createApp({
        data(){
          return {
            letters:['a','b','c','d','e']
          }
        },
        methods: {
          inserFn(){
            this.letters.splice(2,0,'f')
          }
        }
      });
      app.mount("#app");
    </script>
  </body>
</html>


我们确定一件事,在本次更新中,button和ul都不用更新,需要更新只是li,但是观察控制台的element会发现点击以后闪烁的li有四个,从插入f开始后续的li都会销毁然后重新创建,如果我们绑定了一个唯一的key,就能够更新过程中只更改一个li

<li v-for="item in letters" :key="item">{{item}}</li>

vue的diff算法对于有key和没有key的虚拟dom到底是这么做的
源码
在这里插入图片描述
先来看没有key的操作
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
有key的时候
在这里插入图片描述
在这里插入图片描述

有key的diff操作如下

第一步从头开始遍历,调用patch比较,c和f的key不一致会跳出
第二步从尾部开始遍历,比较b和f的key不一致,会跳出

在这里插入图片描述
在这里插入图片描述

第三步:如果旧节点遍历完了,依然有新节点,那就新增

在这里插入图片描述

第四步:如果新节点遍历完毕以后,依然有旧的节点,移除旧节点

在这里插入图片描述

第五步:最特殊的情况,中间还有很多未知或者乱序的节点

在这里插入图片描述
为什么vue3比vue2还慢,其实就是diff的时候有key的情况下,第五种情况,他会重新遍历一遍旧节点,用map建立一个索引的图结构,目的是为了最大程度的复用旧的节点。

  • 46
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值