vue的常用指令【v-bind v-for v-on v-model 自定义指令】

本文详细介绍了Vue.js中的常用指令,包括v-bind用于动态绑定属性,v-for进行循环渲染,v-on处理事件,v-model实现双向数据绑定,并探讨了事件对象、事件修饰符和按键修饰符的使用。此外,还讲解了如何创建自定义指令,例如用于设置主题颜色和表单验证。
摘要由CSDN通过智能技术生成

vue的常用指令

v-bind指令

作用:动态绑定一个或多个属性,属性值是一个动态的【值是依赖于data中的数据源】

使用方式:

<!-- v-bind绑定href属性值 -->
<a v-bind:href='url'>跳转</a>


<!-- v-bind绑定href属性值(简写形式) -->
<a :href='url'>跳转</a>

绑定

绑定HTML Class

1.对象绑定

– html代码

<ul class='app' :class="{'Fone':isOne, 'Ftwo':isTwo}"></ul>

– js代码

var vue = new Vue({
    el:'.app',
    data:{
        isOne:true,
        isTwo:true
    }
})

最终渲染为

<ul class='app Fone Ftwo' ></ul>

当data里的 isOne 或 isTwo 变化时,class列表会相应更新

以上代码等价于

// html代码

<ul class='app' :class="classObject"></ul>

// js代码


var vue = new Vue({
    el:'.app',
    data:{
        classObject:{
            'Fone':true,
            'Ftwo':true
        }
    }
})

2.数组语法

— html代码

<ul class="box" :class="[classA, classB]"></ul>

— js代码

var vm= new Vue({
    el:'.box',
    data:{
        classA:'Fone',
        classB:'Ftwo'
    }
})

补充

可以使用三目运算符

— html代码

<ul class="box" :class="[isA ? classA:'', classB]"></ul>

— js代码

var vm= new Vue({
    el:'.box',
    data:{
        classA:'Fone',
        classB:'Ftwo'
        isA:false 
    }
})

:属性=“data中的属性数据/methods/props/computed”

:属性=“js表达式环境,认为它就是可以直接写js了,字符串相关就要用引号”

— html代码

    <a :href="`http://www.baidu.com?id=${id}`">百度一下</a>
    <hr>
    <a :href="`http://www.baidu.com?id=`+id">百度一下</a>

— js代码

    const app = new Vue({
      el: '#app',
      data: {
        url: 'http://img.1314000.cn/face.png',
        id: 100
      },
    })

绑定 HTML css

  1. 对象绑定

— html代码

<div id="box" :style="{color:activeColor, fontSize:size, textShadow:shadow}">社恐泡面</div>

— js代码

var vm= new Vue({
    el:'#box',
    data:{
        activeColor:'#f00',
        size:'30px',
        shadow:'5px 2px 6px #000'
    }
})

或者
— html代码

	
<div id="box" :style="styleObject">社恐泡面</div>

— js代码

var vm= new Vue({
    el:'#box',
    data:{
        styleObject:{
            color:'red',
            fontSize:'30px'
        }
    }
})

2.数组语法

举个栗子
— html代码

  <div id="app">
    <!-- 样式class它也是属性,动态属性 :class="对象|数组" -->
    <h3 class="title" :class="activeObj">我是一个标题</h3>
    <!-- 数组 -->
    <!-- 
      如果新增样式,则默认情况下,对象无法直接生效,而数组可以生效
      如果对已有的样式,进行开关操作,建议用对象
     -->
    <!-- <h3 :class="activeArr">我是一个标题</h3> -->
    <button @click="setActive">让标题高亮</button>
  </div>

— js代码

    const app = new Vue({
      el: '#app',
      data: {
        // 对象的方式,key,定义的的style中的样式名称
        activeObj: { active: true, font: true },
        // 数组中的元素就是样式名
        activeArr: []
      },
      methods: {
        setActive() {
          // Object.defineProperty
          // this.activeObj.active = true
          // this.activeObj.font = true
          // this.activeObj = { active: false, font: true }
          // this.activeObj = { ...this.activeObj, font: true }
          // Object方法完成对象的合并,返回一个新对象,引用地址不同
          // this.activeObj = Object.assign({},this.activeObj,{font: true})
          // vue2中为了解决Object.defineProperty动态添加属性无法监听问题,提供一个成员方法 $set
          // 参数1:对象是谁
          // 参数2:属性名称
          // 参数3:值
          // 推荐
          // this.$set(this.activeObj, 'font', true)
          // 触发视图更新
          // this.$delete(this.activeObj, 'font')

          // this.activeArr.length == 0 ? this.activeArr.push('active') : this.activeArr.pop()
          // this.activeArr.push('font')
        }
      }
    })

设置内联样式
— html代码

  <div id="app">
    <!-- 内联样式,它的优先级更高,一般用于已有样式的覆盖 -->
    <div :style="styleObj">我是style样式 -- 对象</div>
    <hr>
    <div :style="styleArr">我是style样式 -- 数组</div>
  </div>

— js代码

    const app = new Vue({
      el: '#app',
      data: {
        // styleObj: { color: 'red', fontSize: '50px' }
        styleObj: { color: 'red', 'font-size': '50px' },
        styleArr: [{ color: 'blue' }, { fontSize: '30px' }]
      }
    })

属性里有函数

— html代码

    <img :src="getImg()" alt="">

— js代码

    const app = new Vue({
      el: '#app',
      data: {
        url: 'http://img.1314000.cn/face.png',
        id: 100
      },
      methods: {
        getImg() {
          return 'http://img.1314000.cn/face.png'
        }
      }
    })

注意: 有()

v-for

用于循环取出列数中的数据

语法:v-for="(item,index) in/of 数组"
语法:v-for="(item,key,index) in/of 对象"
    
注:
v-for中建议在迭代时,最好是给第个迭代的元素添加一个唯一不重复的key值,以达到提升性能

key值尽量不要用index索引导它的key值,index索引,如果目标增加或删除,则会触发index值的变化,这样达不到性能优化,index塌陷

今后在和后端合作,通过请求接口拿数据时,一定要确保拿过来数据中一定要有id值

如果你指定了key,新key在的节点中找不到,则创建,旧的key如果在新的节点中找不到,删除

使用:
— html代码

  <div id="app">
    <ul>
      <!-- <li v-for="item,index of users" :key="index"> -->
      <li v-for="item,index of users" :key="item">
        <span>{{index}}</span>
        <span>{{item}}</span>
      </li>
    </ul>
    <hr>
    <!-- 迭代对象方案,在工作中很少有,了解就可以,如果用到知道它可以就可以 -->
    <div v-for="item,key,index in info">
      {{key}} -- {{index}} -- {{item}}
    </div>
  </div>

— js代码

    const app = new Vue({
      el: '#app',
      data: {
        users: [
          // {id:1,name:'张三'}
          '张三',
          '李四',
          '王五'
        ],
        info: { id: 1, name: '赵六', age: 100 }
      }
    })

v-on

  事件绑定:v-on:事件名="绑定的方法" : vue中的绑定的方法可以加小括号也可以不加括号
  绑定的方法定义的位置:data/methods,推荐写在methods
  因为事件绑定在工作中经常用,简单 @事件名="方法" 【h函数中 onClick】

事件对象 event

1.如果绑定的方法没有写小括号,则vue事件系统会自动注入一个event对象到实现在的方法形参中
2.如果绑定的方法有写小括号,则你需要手动把event对象传过来去,vue提供一个变量 $event

如果你的绑定的方法,需要传实现的参数,则写小括号,如果还用到事件对象,则手动传一下,一般我们手动传的事件对象,都写在第1个形参

试一试
— html代码

  <div id="app">
    <h3>{{num}}</h3>
    <!-- <button v-on:click="addNum">++++</button> -->
    <!-- <button @click="addNum">++++</button> -->
    <!-- <button @click="addNum($event,2)">++++</button> -->
    <button @click="addNum(2)">++++</button>
    <hr>
    <input type="text" @keyup="onEnter">

  </div>

— js代码

    const app = new Vue({
      el: '#app',
      data: {
        num: 100
      },
      methods: {
        // addNum(evt, n) {
        //   console.log(evt);
        //   this.num += n
        // }
        addNum(n) {
          this.num += n
        },
        onEnter(evt) {
          // console.log(evt)
          // 如果我是回车,则获取数据
          if ('Enter' === evt.key) {
            console.log(evt.target.value)
            evt.target.value = ''
          }
        }
      }
    })

事件修饰符

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xtn3gZvZ-1668606202270)(C:\Users\dell\AppData\Roaming\Typora\typora-user-images\1668568835001.png)]

— html代码

  <div id="app">
    <div @click="click">
      <!-- 阻止冒泡  stop -->
      <div @click.stop="click">我是一个点击事件</div>
    </div>
    <!-- 绑定keyup的额组合按键 ctrl+enter -->
    <input type="text" @keyup.ctrl.enter="onEnter">
    <hr>
    <!-- 阻止默认行为 prevent -->
    <a href="http://www.baidu.com" @click.prevent="gourl">百度</a>
  </div>

— js代码

    const app = new Vue({
      el: '#app',
      data: {
      },
      methods: {
        onEnter(evt) {
          console.log(evt.target.value)
        },
        click() {
          console.log('click');
        },
        gourl() {
          console.log('百度一下');
        }
      }
    })

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dyrLOp7z-1668606202272)(C:\Users\dell\AppData\Roaming\Typora\typora-user-images\1668605424230.png)]

按键修饰符

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-sgEtdXfG-1668606202273)(C:\Users\dell\AppData\Roaming\Typora\typora-user-images\1668605439477.png)]

v-model

  vue中一个语法糖:快捷方式
  v-model: 绑值 事件  ==> 双向数据绑定

  text/radio/checkbox ==> value/input checked/change

  title它是在data中定义的数据 
  受控组件 
  <input type="text" :value="title" @input="onInput"> 
  <input type="text" v-model="title">

举个栗子
— html代码

  <div id="app">
    <input type="text" v-model="title">
    <hr>
    <!-- 多行文本 -->
    <textarea v-model="intro"></textarea>
    <hr>
    <!-- 单个复选框 全选 、记住登录、声明确认 -- 状态只有两个 true/false -->
    <!-- false则不选中,为true选中 事件和状态修改 -->
    <input type="checkbox" v-model="checked" @change="changeHandle">
    <hr>
    <ul>
      <li v-for="item of targetCourse">
        <label>
          <input type="checkbox" :value="item.id" v-model="course" @change="changeOneHandle"> 
          {{item.title}}
        </label>
      </li>
    </ul>
    <hr>
    <div>
      <input type="radio" value="1" v-model="sex">先生
      <input type="radio" value="2" v-model="sex">女士
    </div>
    <hr>
    <select v-model="city" @change="aa">
      <option value="0">请选择所在城市</option>
      <option value="1">芜湖</option>
      <option value="2">杭州</option>
      <option value="3">南京</option>
    </select>
    <select v-model="region">
      <option value="10">镜湖区</option>
      <option value="11">鸠江区</option>
    </select>
    <button @click="login">提交信息</button>
  </div>

— js代码

    const app = new Vue({
      el: '#app',
      data: {
        title: 'aa',
        intro: 'bb',
        // 单个复选框,用boolean
        checked: false,
        // 多个复选框,array,数组中的元素值,和value值相同时,则界面中选中
        course: [],
        targetCourse: [
          { id: 1, title: '浠浠呀小白入门' },
          { id: 2, title: '浠浠呀你不知道的js' },
          { id: 3, title: 'kerwin老师精品大师' },
        ],
        sex: '2',
        city: '1',
        region: ''
      },
      methods: {
        login() {
          console.log({ ...this.$data });
        },
        changeHandle() {
          let course = []
          if (this.checked) {
            course = this.targetCourse.map(({ id }) => id)
          }
          this.course = course
        },
        changeOneHandle(){
          this.checked = this.course.length==this.targetCourse.length ? true : false;
        },
        aa() {
          console.log(this.city);
        }
      }
    })

v-model修饰符

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fCmofASN-1668606202273)(C:\Users\dell\AppData\Roaming\Typora\typora-user-images\1668605832908.png)]

— html代码

  <div id="app">
    <!-- 
      v-model修饰符 
      .number把表单项中的字符串转为数字,
      如果你的字符是以数字开头,则转为数字,如果不能转为数字,则不转
    -->
    <input type="text" v-model.number="n1"> +
    <input type="number" v-model.number="n2">
    <button @click="onCalc">结果</button>
    {{sum}}
    <hr>
    <!-- 去除两边空格 -->
    <input type="text" v-model.trim="title">
    <!-- 延时更新,优化用 -->
    <input type="text" v-model.trim.lazy="title">
  </div>

— js代码

    const app = new Vue({
      el: '#app',
      data: {
        n1: 1,
        n2: 2,
        sum: 3,
        title: ''
      },
      methods: {
        onCalc() {
          // this.sum = +this.n1++this.n2
          // this.sum = Number(this.n1) + Number(this.n2)
          this.sum = this.n1 + this.n2
        }
      }
    })

自定义指令

  除了用内置的指令完成vue工作需要后,还可以根据vue提供的方案完成自定义指令
  自定义指令:操作dom
  dom对象.style.color='red'
  自定义指令它提供了5个钩子函数,它可以帮我们实现所需要的各种业务场景
  el 当前绑定到指令元素的dom对象,bindings 修饰符和传入的值
  bind     第一次绑定到元素时调用
  inserted 被绑定元素插入父节点时调用 (仅保证父节点存在,但不一定已被插入文档中)
  update   数据更新时调用
  componentUpdated  指令所在组件的 VNode 及其子 VNode 全部更新后调用。
  unbind  只调用一次,指令与元素解绑时调用。

  // 定义自定义指令有两种方案
  // 1.全局  --- 本项目中所有的组件都能使用
  // 2.局部  --- 当前组件可以用

    注:自定义指令中不能使用 this来获取 new Vue组件中的data和方法       

举个栗子–定义主题颜色

— html代码

  <div id="app">
    <div v-red v-if="show">
      <span>我是标题</span>
      <div>
        <input type="text" v-model="title">
      </div>
      <button  v-red>蓝色</button>
    </div>
  </div>
  <div id="app2">
    <div v-red>我是一个标题App2</div>
  </div>

— js代码

    // 1.定义全局指令  -- 定义一次,全局可用
    // 参数1:指定指令的名称,不要v-开头
    // 参数2:对象[定义这5个钩子函数实现] | 回调函数[它是bind/update简写]
    Vue.directive('red', {
      bind(el) {
        el.style.cssText = `color:red;
                            font-size: 30px;`
      }
    })

    const app = new Vue({
      el: '#app',
      data: {
        title: '',
        show: true
      }
    })

    const app2 = new Vue({
      el: '#app2',
      data: {
        title: '',
        show: true
      }
    })

举个栗子-- 表单验证

— html代码

  <div id="app">
    <div>
      <div>
        <!-- 用户名必须是以a开头 -->
        <input type="text" v-model="username" v-username>
      </div>
      <div>
        <input type="text" v-model="password" v-password>
      </div>
    </div>
  </div>

— js代码

    // Vue.directive('username', {
    //   bind(el) {
    //     // 用户名必须是以a开头
    //     if (el.value.startsWith('a')) {
    //       // el.style.color = 'red'
    //       el.style.cssText = `border: 1px solid red;outline:none;`
    //     } else {
    //       // el.style.color = 'black' 
    //       el.style.cssText = `border: 1px solid black;`
    //     }
    //   },
    //   update(el) {
    //     // 用户名必须是以a开头
    //     // console.log(el.value);
    //     // console.log(el.value.startsWith('a'))
    //     // 输出的账号中不能有a字母
    //     // console.log(el.value.includes('a'))

    //     // 用户名必须是以a开头
    //     if (el.value.startsWith('a')) {
    //       // el.style.color = 'red'
    //       el.style.cssText = `border: 1px solid red;outline:none;`
    //     } else {
    //       // el.style.color = 'black' 
    //       el.style.cssText = `border: 1px solid black;`
    //     }
    //   }
    // })

    //  简写,它相当于 bind/update合集
    Vue.directive('username', el => {
      // 用户名必须是以a开头
      if (el.value.startsWith('a')) {
        el.style.cssText = `border: 1px solid red;outline:none;`
        // 当前我没有兄弟,创建
        if (!el.nextSibling) {
          const spanDom = document.createElement('span')
          spanDom.innerHTML = '账号不能以a字母开头'
          el.parentNode.appendChild(spanDom)
        }
      } else {
        el.style.cssText = `border: 1px solid black;`
        // el?.nextSibling?.remove()
        el && el.nextSibling && el.nextSibling.remove()
      }
    })

    Vue.directive('password', el => { })

    const app = new Vue({
      el: '#app',
      data: {
        username: '',
        password: ''
      }
    })
 => {
      // 用户名必须是以a开头
      if (el.value.startsWith('a')) {
        el.style.cssText = `border: 1px solid red;outline:none;`
        // 当前我没有兄弟,创建
        if (!el.nextSibling) {
          const spanDom = document.createElement('span')
          spanDom.innerHTML = '账号不能以a字母开头'
          el.parentNode.appendChild(spanDom)
        }
      } else {
        el.style.cssText = `border: 1px solid black;`
        // el?.nextSibling?.remove()
        el && el.nextSibling && el.nextSibling.remove()
      }
    })

    Vue.directive('password', el => { })

    const app = new Vue({
      el: '#app',
      data: {
        username: '',
        password: ''
      }
    })
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值