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

vue的常用指令

v-bind指令

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

使用方式:


<a v-bind:href='url'>跳转a>



<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代码

    // 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">
        
        <h3 class="title" :class="activeObj">我是一个标题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="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 @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">
          
          <div @click.stop="click">我是一个点击事件div>
        div>
        
        <input type="text" @keyup.ctrl.enter="onEnter">
        <hr>
        
        <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中定义的数据 
      受控组件 
       
      
    

    举个栗子
    — html代码

      <div id="app">
        <input type="text" v-model="title">
        <hr>
        
        <textarea v-model="intro">textarea>
        <hr>
        
        
        <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">
        
        <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>我是一个标题App2div>
      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>
            
            <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: ''
          }
        })
    

    你可能感兴趣的:(vue.js,javascript,前端)