vue2 14个指令详解,v-bind操作style,v-bind操作class,以及v-bind动态绑定图片地址不生效的问题

vue常用指令

vue一共14个指令,常用的有大约10个

按照不同的用途可以分为如下 6 大类:

  • 内容渲染指令(v-html、v-text)

  • 条件渲染指令(v-show、v-if、v-else、v-else-if)

  • 事件绑定指令(v-on)可简写为冒号:

  • 属性绑定指令 (v-bind)可简写为@

  • 双向绑定指令(v-model)

  • 列表渲染指令(v-for)

内容渲染指令

内容渲染指令会覆盖掉元素中原有的内容

v-text

类似innerText,不可以解析标签

示例:

  <div id="app" v-text="msg">我会被覆盖</div> <!--会覆盖掉div中原有的内容-->
   <script>
     new Vue({
      el:'#app',
      data:{
        msg:`<a href="www.baidu.com">百度</a>`,
        name:'小十七'
      }
     })
   </script>

在这里插入图片描述

v-html

类似 innerHTML,可以解析标签

  <div id="app" v-html="msg">我会被覆盖</div>  <!--会覆盖掉div中原有的内容-->
   <script>
     new Vue({
      el:'#app',
      data:{
        msg:`<a href="www.baidu.com">百度</a>`,
        name:'小十七'
      }
     })
   </script>

在这里插入图片描述

条件渲染指令

v-show

  1. 作用: 控制元素显示隐藏
  2. 语法: v-show = "表达式",表达式值为 true 显示,为 false 隐藏
  3. 原理: 切换 display:none 控制显示隐藏
  4. 场景:频繁切换显示隐藏的场景

v-if

  1. 作用: 控制元素显示隐藏(条件渲染)
  2. 语法: v-if = "表达式",表达式值 true 显示,为 false 隐藏
  3. 原理: 基于条件判断,是否创建或移除元素节点
  4. 场景: 要么显示,要么隐藏,不频繁切换的场景

示例:

  <style>
     p{
      width: 100px;
      height: 100px;
      background-color: skyblue;
     }
  </style>
</head>
<body>
  <div id="app">
    <p v-show="flag">我是v-show</p>
    <p v-if="flag">我是v-if</p>
  </div>
  <script>
     new Vue({
      el:'#app',
      data(){
        return{
          flag:true
        }
      },
     })
  </script>

v-elsev-else-if

  1. 作用:辅助v-if进行判断渲染(类似于if多分支语句)
  2. 语法:v-else ; v-else-if=“表达式” ;v-else后面不需要加表达式
  3. v-if v-else v-else-if 使用时需要紧挨着,中间不能断开

示例:

  <div id="app">
    <p v-if="gender === 1">性别:♂ 男</p>
    <p v-else=>性别:♀ 女</p>
    <hr>
    <p v-if="score >=90">成绩评定A:奖励电脑一台</p>
    <p v-else-if="score >=70">成绩评定B:奖励周末郊游</p>
    <p v-else-if="score >=60">成绩评定C:奖励零食礼包</p>
    <p v-else>成绩评定D:惩罚一周不能玩手机</p>
  </div>
  <script>
    const app = new Vue({
      el: '#app',
      data() {
        return {
          gender: 1,
          score: 95
        }
      }
    })
  </script>

template标签

template标签/元素只是起到占位的作用,不会真正的出现在页面上,也不会影响页面的结构

示例:

<!-- 需求:同时控制以下3个标题一起出现或者隐藏
    上述的需求就可以使用template标签去实现,普通标签虽然也可以但是多个结构
-->
      <template v-if="false">
        <h2>六下匹,人当送,内。</h2>
        <h3>六下匹,人当送,内。</h3>
        <h4>六下匹,人当送,内。</h4>
      </template>

事件绑定指令

v-on

<button v-on:事件名="内联语句">按钮</button>
<button v-on:事件名="methods中的函数名">按钮</button>
<button v-on:事件名="处理函数(实参)">按钮</button>

v-on:可以简写为 @

<button @事件名="内联语句">按钮</button>

示例1:内联语句

<!--按钮加减功能-->
<div id="app">
    <button v-on:click="count--">-</button>
    <span>{{count}}</span>
    <button @click="count++">+</button> <!-- v-on简写为@ -->
</div>
   <script>
       new Vue({
        el:'#app',
        data(){
          return{
            count:100,
          }
        }
       })
   </script>

示例2:methods

<div id="app">
    <button @click="fn">切换显示隐藏</button>
    <h1 v-show="isShow">我是小十七</h1>
 </div>
   <script>
      const app =  new Vue({
           el:'#app',
           data(){
            return{
              isShow:true
            }
           },
           methods:{
            fn(){
              this.isShow=!this.isShow
            }
           }
        })
   </script>

事件处理函数传参

  • 如果不传递任何参数,则方法无需加小括号
  • methods方法中如果没有传参可以直接使用 e 当做事件对象
  • 如果传递了参数,则实参 $event 表示事件对象,固定用法

示例:减5、减10 的处理逻辑是一样的,所以可以封装成方法,在调用的时候传参

 <div id="app">
    <button @click="result(5)">减5</button>  <!--如果不传入参数就不需要写小括号,直接写result-->
    <button @click="result(10)">减10</button>
    <p>余额{{money}}</p>
  </div>
  <script>
    new Vue({
      el: '#app',
      data() {
        return {
          money: 100
        }
      },
      methods:{
        result(price){
          this.money -= price
        }
      }
    })
  </script>

事件处理函数的事件对象

methods方法中如果没有传参可以直接使用 e 当做事件对象

  <div id ="root">
   <button @click="fn">事件对象</button>  
  </div>
  <script>
   var vm = new Vue({
    el: '#root',
    methods:{
      fn(e){
        console.log(e)   // 打印出事件对象
      }
    }
   });
  </script>

如果传递了参数,则实参 $event 表示事件对象,固定写法只能写成$event

  <div id="root">
    <button @click="fn($event,'love')">方法传参事件对象</button>
  </div>
  <script>
    var vm = new Vue({
      el: '#root',
      methods: {
        fn(str, e) {
          console.log(str);  // love
          console.log(e);  // 事件对象
        }
      }
    });
  </script>

属性绑定指令

v-bind

  • v-bind:可以绑定元素的属性

  • 语法:v-bind:属性名=“表达式”

  • v-bind:可以简写成冒号 :

  • 表达式会关联到data的数据,只要data的数据发生变化,v-bind绑定属性后面的表达式执行结果立即发生变化

  • 凡是标签体的内容想要动态,用插值语法

  • 凡是需要标签的属性是动态的,就用指令语法

示例:点击随机变色

 <!-- v-bind可以简写成 : -->
<div id="root" v-bind:style={backgroundColor:bgColor} style="width: 100px;height: 100px;">
    <!--点击触发changeColor函数-->
    <button @click="changeColor">变色</button>
  </div>
  <script>
    var vm = new Vue({
      el: '#root',
      data() {
        return {
          bgColor: 'skyblue'
        }
      },
      methods: {
        changeColor() {
          this.bgColor = this.getRandomColor()
        },
        // 随机色函数
        getRandomColor() {
          const letters = '0123456789ABCDEF'
          let color = '#'
          for (let i = 0; i < 6; i++) {
            color += letters[Math.floor(Math.random() * 16)]
          }
          return color
        }
      }
    })
  </script>

双向绑定指令

v-model

  • v-model双向数据绑定

  • v-model只能用在表单元素

    • 输入框 input:text --> value
    • 文本域 textarea --> value
    • 复选框 input:checkbox --> checked
    • 单选框 input:radio --> checked
    • 下拉菜单 select
  • 可以快速获取或设置表单元素的内容

  • 视图或数据变化,另一个自动更新

语法:

 // 完整写法
  v-model:value="表达式"
 // 简写
  v-model="表达式"

示例:

 <style>
    textarea {
      display: block;
      width: 240px;
      height: 100px;
      margin: 10px 0;
    }
 </style>
 <div id="app">
    <h3>小黑学习网</h3>
    姓名:
      <input type="text" v-model="uname"> 
      <br><br>
    是否单身:
      <input type="checkbox" v-model="isSingle"> 
      <br><br>
    <!-- 
      前置理解:
        1. name:  给单选框加上 name 属性 可以分组 → 同一组互相会互斥
        2. value: 给单选框加上 value 属性,用于提交给后台的数据
        3.结合 Vue 使用 → v-model 
        4.使用 v-model时单选框的name属性可以不要,但是value属性必须要有
        5.当 v-model 的值与某个单选框的 value 值相等时,Vue.js 会自动设置该单选框为选中状态
    -->
    性别: 
      <input type="radio" value="1" v-model="gender"><input type="radio" value="0" v-model="gender"><br><br>
    <!-- 
      前置理解:
        1. option 需要设置 value 值,提交给后台
        2. select 的 value 值,关联了选中的 option 的 value 值
        3. 结合 Vue 使用 → v-model
    -->
    所在城市:
    <!-- 当 v-model 的值与下拉菜单的某个选项的 value 值相等时,Vue.js 会自动设置该单选框为选中状态 -->
      <select v-model="cityId">
        <option value="101">北京</option>
        <option value="102">上海</option>
        <option value="103">成都</option>
        <option value="104">南京</option>
      </select>
      <br><br>
    自我描述:
      <textarea v-model="text"></textarea> 
    <button>立即注册</button>
  </div>
  <script>
    const app = new Vue({
      el: '#app',
      data: {
        uname:'',
        isSingle:true,
        gender:'1',
        cityId:'102',
        text:''
      }
    })
  </script>

v-model的双向绑定实现原理

用在表单元素上

  • 文本框或密码框相当于::value="数据" + @input="数据=$event.target.value"
  • 复选框::checked="数据" + @change="数据=$event.target.checked"
  • 下拉列表::selected="数据" + @change="数据= $event.target.selected"

​ 用v-on给表单控件绑定数据,此时数据是单向的,修改input的值data里面的数据不会发生变化,我们可以给输入框绑定input事件,给单/复选框、下拉框绑定change事件,触发事件时通过事件对象$event,拿到表单控件的值,然后赋值给data的数据,实现双向绑定

用在组件实现父子数据双向绑定

:value="数据" + @input=" 数据=$event"

列表渲染指令

v-for

  • v-for 列表渲染指令
  • 作用:基于数据循环,多次渲染整个元素
  • 可以渲染 :Array | Object | number | string | Iterable (2.6 新增)
  • 当和 v-if 一起使用时,v-for 的优先级比 v-if 更高

遍历数组语法:

<div v-for="(item, index) in arr"> {{value}} </div> 
<!-- 也可以写成这样v-for="(item, index) of arr 看自己的习惯 -->
<!-- 
     item数组中的每一项,必须项
     index 是每一项的索引,可选项,不需要可以省略
     arr 是被遍历的数组
-->
<div v-for="item in arr"> {{value}} </div>
<!-- 省略index的写法 -->

也可以遍历 对象、数字

<!--遍历对象-->
<div v-for="(value, key, index) in object">{{value}}</div>
<!-- 
     value:对象中的值
     key:对象中的键
     index:遍历索引从0开始
-->

<!--遍历数字-->
<p v-for="item in 10">{{item}}</p>
<!--item从1开始-->

遍历数组示例:

 <div id="root">
    <ul>
      <li v-for="item in list">{{item}}</li>
    </ul>
  </div>
  <script>
    let vm = new Vue({
      el: '#root',
      data() {
        return {
          list: ['西瓜', '苹果', '香蕉', '火龙果', '芒果']
        }
      }
    })
  </script>

其它指令

v-pre

  • 不需要表达式

  • 用法

    跳过这个元素和它的子元素的编译过程,可以用来显示原始标签,跳过大量没有指令的节点会加快编译

  • 示例

    <span v-pre>{{ this will not be compiled }}</span>
    

v-cloak

  • 不需要表达式
  • 此指令会一直在元素身上,直到编译结束,会被去除
  • 可用于隐藏尚未完成编译的 DOM 模板
  • 场景:当文件加载速度慢,导致编译变慢,会将一些语法原样显示在页面,可以利用v-cloak作为属性选择器去隐藏,直到编译完成,v-cloak被去除,元素显示出来

场景模拟示例:

 <style>
    [v-cloak] {
      display: none;
    }
  </style>
  <body>
    <div id="app">
      <h1 v-cloak>{{msg}}</h1>
    </div>
    <script>
      // 晚3s引入vue.js
      setTimeout(() => {
        let scriptElt = document.createElement("script");
        scriptElt.src = "./js/vue.js";
        document.head.append(scriptElt);
      }, 3000);
      // 晚4s创建vm实例
      setTimeout(() => {
        var vm = new Vue({
          el: "#app",
          data: {
            msg: "v-cloak",
          },
        });
      }, 4000);
    </script>

在这里插入图片描述

编译结束在哪个阶段?

在Vue中,v-cloak 指令主要用于解决插值表达式的闪烁问题。当Vue实例还没有编译完成时,v-cloak 所在的元素会保持隐藏状态,直到Vue实例编译结束,v-cloak 才会从DOM元素上移除,此时页面内容才会正常显示。

关于Vue的生命周期,它主要分为四个阶段:初始化阶段、模板编译阶段、挂载阶段和卸载阶段。

  1. 初始化阶段:从创建Vue实例开始,到beforeCreatecreated这两个生命周期钩子之间的阶段。在这个阶段,Vue实例会进行初始化设置,包括数据观测(data observer),属性和方法的运算,以及e**l属性等等,但是还没有挂载‘el,且$el`属性目前不可见。
  2. 模板编译阶段:在createdbeforeMount这两个钩子之间的阶段。这个阶段主要是将模板编译为渲染函数,为后续的挂载阶段做准备。
  3. 挂载阶段:在beforeMountmounted这两个钩子之间的阶段。Vue在这个阶段会将实例挂载到DOM元素上,即将模板渲染到指定的DOM元素上。此时,页面内容会正常显示,v-cloak指令也会在这个阶段从DOM元素上移除。
  4. 卸载阶段:当调用vm.$destroy()方法后,Vue实例会进入卸载阶段。在这个阶段,Vue会将自身从父组件中删除,取消实例上所有依赖的追踪并且移除所有的事件监听器。

所以,对于v-cloak编译结束后消失的问题,编译结束实际上是指Vue实例的挂载阶段。当Vue实例完成模板编译并成功挂载到DOM元素上时,v-cloak指令就会被移除,页面内容会正常显示

v-once

  • 不需要传入参数
  • 只能渲染一次,数据修改后也不会再渲染,相当于静态渲染,可以用于优化性能
<h1 v-once> {{msg}} </h1>

v-for 中的 key

在这里插入图片描述

  • v-for 的默认行为会尝试原地修改元素而不是移动它们(就地复用)
  • 要强制其重新排序元素,你需要用特殊 attribute key 来提供一个排序提示
  • key的作用:给元素添加的唯一标识

语法:

<div v-for="item in arr" :key="item.id"> {{ item.text }} </div>

示例:

   <div id="app">
      <h3>小黑的书架</h3>
      <ul>
        <li v-for="item in booksList" >
          <span>{{item.name}}</span>
          <span>{{item.author}}</span>
          <button @click="del(item.id)">删除</button>
        </li>
      </ul>
   </div>
    <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
    <script>
      const app = new Vue({
        el: '#app',
        data: {
          booksList: [
            { id: 1, name: '《红楼梦》', author: '曹雪芹' },
            { id: 2, name: '《西游记》', author: '吴承恩' },
            { id: 3, name: '《水浒传》', author: '施耐庵' },
            { id: 4, name: '《三国演义》', author: '罗贯中' }
          ]
        },
        methods: {
          del(id) {
            this.booksList = this.booksList.filter(item => item.id !== id)
          }
        }
      })
    </script>

v-bindv-model区别

  • v-bindv-model都可以完成数据的绑定 data ==> 视图
  • v-bind是单向数据绑定 data ==> 视图
  • v-model 是双向数据绑定 data <==> 视图
  • v-bind可以用在任何html标签上,v-model只能用在表单元素( input、radio、select、textarea等 )

v-ifv-show

  1. v-show不论初始条件是什么,元素始终都会被渲染到 DOM 中,只是简单地通过切换 CSS 的 display 属性来控制其可见性
  2. v-if 指令是依据条件渲染元素,条件变化时需要重新渲染整个条件块,这包括销毁、重新创建和挂载元素;依靠销毁创建元素来控制可见性,性能不好
  3. 如果一个元素在页面上被频繁的隐藏和显示,建议使用v-show,因为用 v-if 反复创建和销毁节点性能不好
  4. v-if 的优点:v-show不论如何都要渲染整个元素,v-if 依据条件来判断是否渲染,所以页面加载速度快,能提高页面的渲染效率

v-bind操作class

为了方便开发者进行样式控制, Vue 扩展了 v-bind 的语法,可以针对 class 类名 和 style 行内样式 进行控制

字符串写法

  <style>
   .big {
       width: 200px;
       height: 200px;
     }
  </style>
  <div :class="styles"></div> 
  <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
  <script>
    const app = new Vue({
      el: '#app',
      data: {
        styles:"big"
    })
  </script>

对象写法

  • 当class动态绑定的是对象时,键是类名
  • 值是布尔值,值为true,就有这个类名,为false,就没有这类名
  • 适用场景:一个类名,来回切换(例如tab栏切换)
<div class="box" :class="{ 类名1: 布尔值, 类名2: 布尔值 }"></div>

数组写法

  • 当class动态绑定的是数组时,数组中所有的类,都会添加元素上
  • 本质就是一个 class 列表
  • 使用场景:批量添加或删除类
<div class="box" :class="[ 类名1, 类名2, 类名3 ]"></div>

案例:tab 栏切换

CSS

  <style>
     * { margin: 0;padding: 0;}
    ul { display: flex;border-bottom: 2px solid #e01222;padding: 0 10px;}
    li { width: 100px;height: 50px; line-height: 50px;list-style: none; text-align: center;}
    li a { display: block; text-decoration: none; font-weight: bold;color: #333333; }
    li a.active { background-color: #e01222; color: #fff; }
  </style>

JS

 <div id="app">
    <ul>
      <!-- v-for动态渲染,注册点击事件,更改activeIndex数值,数据渲染视图 -->
      <li v-for="(item,index) in list" :key="item.id" @click="activeIndex=index">
        <!-- 绑定class属性,对象写法,用于频繁切换 -->
        <a :class="{active:index === activeIndex}" href="#">{{item.name}}</a>
      </li>
    </ul>
  </div>
  <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
  <script>
    const app = new Vue({
      el: '#app',
      data: {
        list: [
          { id: 1, name: '京东秒杀' },
          { id: 2, name: '每日特价' },
          { id: 3, name: '品类秒杀' }
        ],
        activeIndex: 0
      }
    })
  </script>

v-bind操作style

字符串写法

示例:


 <div id="app" class="box" :style="styleStr"></div>
 <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
 <script>
      const vm = new Vue({
        el: "#app",
        data: {
         // 用一个变量存储数据,不同样式之间用分号; 隔开
          styleStr: "background-color:green; width:500px; height: 100px",
        },
      });
 </script>

对象写法

语法:

<div class="box" :style="{ CSS属性名1: 'CSS属性值', CSS属性名2: 'CSS属性值' }"></div>
<!--
遇到background-color带横杠的css属性名,
可以用驼峰写法: backgroundColor
或者加上双引号:'background-color'
-->
<!--css属性值是需要加上双引号的,否则报错-->

示例:

<div :style="{ width: '100px' , height:'50px' , backgroundColor:'skyblue' }"> </div>

进度条案例:

CSS

<style>
    .progress {height: 25px;width: 400px;border-radius: 15px;background-color: #272425;border: 3px solid #272425;box-sizing: border-box;margin-bottom: 30px;}
    .inner {width: 50%;height: 20px;border-radius: 10px;text-align: right;position: relative;background-color: #409eff;background-size: 20px 20px;box-sizing: border-box;transition: all 1s;}
    .inner span {position: absolute;right: -20px;bottom: -25px;}
  </style>

JS

   <div id="app">
      <div class="progress">
       <div class="inner" :style="{width: percent + '%'}">
        <span>{{percent}}%</span>
      </div>
    </div>
    <button @click="percent=25">设置25%</button>
    <button @click="percent=50">设置50%</button>
    <button @click="percent=75">设置75%</button>
    <button @click="percent=100">设置100%</button>
  </div>
  <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
  <script>
    const app = new Vue({
      el: '#app',
      data: {
        percent: 20
      }
    })
  </script>

数组写法

示例:

  <div id="app" class="static" :style="styleArr">动态写法:数组形式</div>
  <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
  <script>
    const app = new Vue({
      el: '#app',
      data: {
        styleArr:[{'background-color':'green'},{'color':'red'}]
      }
    })
  </script>

v-bind脚手架环境绑定图片src

在 Vue 中使用动态绑定图片地址时,如果你使用相对路径,并且是在构建后的环境中(比如通过 webpack 或其他打包工具打包后部署到服务器上),可能会遇到路径解析不正确的问题。这是因为打包工具会处理资源文件,并改变它们在构建后的目录结构

对于 Vue CLI 创建的项目,通常推荐使用requireimport来引入图片资源,这样 webpack 可以正确地处理图片路径,并在构建时将其包含在输出中

这里,@符号通常是 Vue CLI 项目中src目录的别名。确保你的图片位于public文件夹或src/assets文件夹内,并相应地调整路径

如果你坚持使用相对路径,并且确实知道图片在构建后的位置,你可以直接绑定构建后的路径。但请注意,这通常不是推荐的做法,因为它依赖于构建后的目录结构,这可能在不同的部署环境中有所不同

<img :src="require(`../../public/img/${sendWeatherData.wea_img}.png`)" class="weather-icon" />

关于key的面试题

在这里插入图片描述

  • 26
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

十七同志

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值