Vue _ 教程版 02 指令

news/2024/7/10 2:18:51 标签: 前端, Vue

目录

目标

一、模板语法

1.1、插值表达式

1.2、指令

1-2-1. v-text 指令

1-2-2. v-html 指令

二、常用指令

2.1、v-show 指令

2.2、v-if 指令

2.3、v-for 指令

2.4、v-on 指令

4.5、v-bind 指令

2.6、v-model 指令

2.7、v-pre 指令

2.8、v-cloak 指令

2.9、v-once 指令

样式绑定

1、class 样式处理

2、绑定 style

三、自定义指令

图例 :


跳转链接 =>  Vue _ 教程版 01 基础

跳转链接 =>  Vue _ 教程版 03

跳转链接 =>  Vue _ 教程版 04 组件

跳转链接 =>  Vue _ 教程版 05


目标

  • 熟练使用 插值表示式 ( 模板语法 )
  • 掌握 Vue 指令
  • 能够定义 Vue 自定义指令

一、模板语法

1.1、插值表达式

插值表达式是 Vue 框架提供的一种在 html 模板中绑定数据的方式,使用 {{ 变量名 }} 方式绑定 Vue 实例中 data 中的 数据变量。会将绑定的数据实时的显示出来

<!-- 指定 Vue 要去解析的模板挂载点 -->
  <div id="app">
    <div>{{ msg }}</div>
    <div>{{ msg+'123' }}</div>
    <div>{{ 1 + 2 }}</div>
    <div>{{ msg.substr(0,2) }}</div>
    <div>{{ fn() }}</div>
    <div>{{ age<18?'儿童':'成年' }}</div>
    <!-- 这样不可以,不能赋值,只能使用 -->
    <!-- <div>{{ var a=10 }}</div> -->
  </div>
  <script>
    // 实例化 Vue
    const vm = new Vue({
      el: '#app',
      data: {
        msg: '你好Vue',
        age: 18
        /* fn() {
          return 'hello fn'
        } */
      },
      // Vue 专门用来给写方法所用配置
      methods: {
        /* fn() {
          return 'hello fn'
        }  */
        // 在 Vue 中的 methods 方法,定义时不能使用箭头函数,使用后 this 指向就会不对
        // 方法里面定义函数建议使用箭头函数,保持 this 指向
        fn: function () {
          // return 'hello fn@' + this.$data.msg
          setTimeout(() => {
            console.log(this)
          }, 3000);
          return 'hello fn@' + this.msg
        }
        // fn: () => {
        //   // this undefined => 现在没有开启强制模式
        //   // 在vue.js引入的方案中它是window
        //   // console.log(this)
        //   return 'hello fn@' + this.msg
        // }
      }
    })
  </script>

 

1.2、指令

指令 ( Directives ) 就是 Vue 给 html 标签提供的一些 自定义属性 , 这样属性都是带有 v- 前缀的 特殊属性。指令特性的值预期是单个 JS 表达式 ( v-for 是例外情况 ) 。指令的职责是,当表达式的值改变时,将其产生的连带影响,响应式地作用于 DOM 

指令默认不能直接去操作 Vue 配置选项中的 data 和 methods 数据 和 方法

指令作用:

  • 操作 Dom
  • 设置主题
  • 权限限制
  • 表单验证
  • 颜色控制

1-2-1. v-text 指令

    <!-- 下面这是能在界面看见的部分就是 视图 部分 -->
    <!-- 被 Vue 管理 -->
    <!-- 指定 Vue 要去解析的模板挂载点 -->
    <div id="app">
        <!-- {{ 双花括号之间不能有空格 , 需要紧挨在一起 }} -->
        <!-- v-text 等价于 innerText -->
        <!-- Vue 指令是写在标签当中的 , 作为属性的形式来写上去 , 
" 以 v- 开头的 都是称之为 Vue 的指令 , 就相当于是给 Vue 添加上了一个指令 " -->
<!-- {{ 双花括号相当于 v-text 这个指令的语法糖 , 相当于一个简写 }} -->
        <h1 v-text='message'></h1>
        <h1 v-text="1+2+3"></h1>
        <h1 v-text="arr.length"></h1>
        <h1 v-text="arr.join('+')"></h1>
        <h1 v-text="obj.name"></h1>
<!-- v-text 解决有的时候,模板解析过慢会有{{}}闪现问题,用属性不会有闪现 -->
        <hr>
        <h2> {{1+2+3}} </h2>
        <h2> {{arr.length}} </h2>
        <h2> {{arr.join('+')}} </h2>
        <h2> {{obj.name}} </h2>
        <!-- v-text 指令的语法糖 , 简写 -->
            <!-- 进行转义输出 -->
        <h1> {{message}} </h1>
        <p v-text="str"></p>
        <mark>前端</mark>
        <hr>
        <h2>{{message}}, 小灰狼 !</h2>
<h2 v-text="message">, 小灰狼</h2>
<!-- v-text 不灵活 , 会把后面的内容就覆盖掉了 -->
    </div>
    <!-- 不被 Vue 管理 -->
    <div>{{message}}</div>
    <script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
    <script>
        // 创建 Vue 实例
        const vm = new Vue({
            // vue 实例的配置项:
            // element , vue 实例控制这一块 dom
            el: '#app', // 用于挂载要管理的元素
            // vue 实例的属性
            // data 内部的属性和属性值就是 vue 实例的属性和属性值
            // 下面 data 这一部分就是 数据
            data: { // 定义数据
                message: "hello",
                name: '小灰狼',
                arr: ['a', 'b', 'c', 'd'],
                obj: {
                    name: 'zhangsan',
                    age: 20
                },
                str: "<mark>前端</mark>"
            }
        });
    </script>

1-2-2. v-html 指令

<div id="app">
    <!-- Vue 指令 v-html -->
    <!-- v-html 等价于 innerHtml -->
    <p v-html="str"></p>
    <mark>大前端</mark>

    <!-- Vue1.0 版本 -->
    <!-- <p>{{{str}}}</p> -->
    <!-- 2.0 版本以后 已 废弃删除 -->
    <hr>
    <!-- 进行转义输出 -->
    <h2>{{url}}</h2>

    <!-- 我们不需要转义 -->
    <!-- 
    v-html它就是不转义输出 指令 
    它有一定安全问题,可能会有xss攻击
    富文本:内容有html标签
    v-html一般用它来对于后台添加的富文本内容进行展示所用,用它一定要小心
    -->
    <h2 v-html="url"></h2>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
<script>
    const app = new Vue({
        el: '#app', 
        data: {
            str: "<mark>大前端</mark>",
            url: '<a href="http://www.baidu.com">百度一下</a>'
        }
    });
</script>


二、常用指令

指令扩展了 html 标签的功能、大部分的指令的值是 js 的表达式,取代了 DOM 操作。

2.1、v-show 指令

根据表达式的 布尔值 ( true / false ) 进行判断 是否 渲染该元素

<div id="app">
    <!-- v-show 指令 : 里面必须书写的是 表达式 -->
    <!-- 通过控制标签的 display 属性来控制标签是否显示的 -->
    <div class="box" v-show="show">box -- show</div>
<!-- 
v-show
true:显示
false:隐藏
false 时会把 dom 通过 css 给隐藏起来
如果你是频繁的切换操作,建议使用 v-show
v-show 初始性能稍差,切换性能好一些
-->
    <div class="box" v-show="true">box1 -- show</div>
    <!-- style="display: none" -->
    <div class="box" v-show="false">box2</div>
    <!-- box3 为 true -->
    <div class="box" v-show="n>1">box3 -- show</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
<script>
    const app = new Vue({
        el: '#app',
        data: {
            show: true,
            n: 10
        }
    });
</script>

v-show 和 v-if 之间的差别是什么 ?

    1. v-show 通过控制标签的 display 属性 来控制标签是否显示的 , 当为 false 时 , 设置为 none , 当为 true , 设置为 " " , 采用标签原来的 display 属性 ( 原来 display 属性为 block 就为 block , 为 inline 就是 inline )

    2. v-if 通过控制标签是否存在于 DOM 结构中来控制标签是否显示 ( 会删除标签 , 创建标签 , 在 true 和 false 之间切换 )

    ( 控制标签 CSS 的成本 和 JS操作 DOM 去 创建 DOM 和 删除 DOM , 哪一个成本更大呢 ?  => 删除标签 , 创建标签的消耗成本大 , 修改 CSS 让页面重新渲染一下的成本小 )

    3. 因为以上的原因 , v-show 有更高的初始化开销 , v-if 有更高的切换开销

    ( 假如标签刚开始的时候我们并不想看到它 , 需要先隐藏起来 , 当用户点击某个按钮的时候 , 再展示出来给用户看 , 如果你用 v-show 来控制 , 那么在界面初始化的时候 , 就需要将这个标签创建好 , 然后将它的 display 属性设置为 none , 等用户点击某个按钮的时候我再把 它的 display 属性关闭 , 展示出来标签 , 所以你初始化的时候就要创建 , 既 v-show 有更高的初始化开销 )

    ( 如果用户不断地在 true , false 之间点击 切换 的话 , 那么这个标签就要不断地 创建, 销毁 , 所以需要我们合理的进行运用 )


注:v-if 有更高的切换开销,而 v-show 有更高的初始渲染开销。因此,如果需要非常频繁地切换,则使用 v-show 较好;如果在运行时条件很少改变,则使用 v-if 较好。

2.2、v-if 指令

根据表达式的 布尔值 ( true / false ) 进行判断 是否渲染该元素

<div id="app">
<!-- 
v-if
true:显示
false:隐藏
false时它会把dom删除掉
如果你是后台管理菜单建议用v-if,没有可能性来回切换
v-if初始性能好,切换性能稍差一些
-->
    <!-- 下面的指令之间不能断开 , 穿插别的东西 , 否则会报错 , 必须得连起来 -->
<!-- 
    多分支 标签之间只能是多分支,不能有别的
    v-if  v-else-if  v-else
-->
    <!-- 通过控制标签是否存在于 DOM 中来控制标签是否显示 -->
    <div class="box" v-if="show">box</div>
<!-- 指令 v-else-if : 当第一个条件成立 , 后面的语句就不用再判断了 , 里面的运算就少了三步-->
    <div class="box" v-else-if="flag === 'A">box1</div>
    <div class="box" v-else-if="flag === 'B">box2</div>
    <div class="box" v-else-if="flag === 'C">box3</div>
    <div class="box" v-else-if="flag === 'D">box4</div>
    <!-- 当 flag === A 之后并不会跳过下面的三个判断 , 当你等于 A 之后 , 
后面的肯定是不可能成立的 , 也就没有必要再次进行判断了 , 如果你使用 v-if 
你的每个条件都得判断四次 就显得不太友好了 -->
    <!-- 指令 v-else : ( 使用的时候必须要保证前面有一个 v-if , 否则会报错 )-->
    <div class="box" v-if="flag === 'A">box1</div>
    <div class="box" v-else-if="flag === 'B">box2</div>
    <div class="box" v-else-if="flag === 'C">box3</div>
    <div class="box" v-else-if="flag === 'D">box4</div>
    <div class="box" v-else>其他</div>

    <div class="box" v-if="flag === 'A">box1</div>
    <div class="box" v-else>其他</div>
<!-- v-else-if , v-else 指令, 前面必须有 v-if , 并且标签之间不能有其他的文本或标签 -->
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
<script>
    const app = new Vue({
        el: '#app',
        data: {
            show: true,
            flag: 'A'
        }
    });
</script>
<!-- 
    if(表达式) {
        语句
    } else if(表达式2) {
        语句
    } else {
        语句
    }
-->

 

2.3、v-for 指令

根据一组 数组对象 的选项列表进行渲染。

v-for 指令需要使用 ( item, index ) in 或 对象 形式的 特殊语法,同时还需要指定 key 值 , key 的作用在 vue 进行 新旧数据比对 渲染页面里,如果有 key 值会提升比对性能 ,加快渲染,key 使用 唯一 来 赋值 。

循环数组 :

v-if 和 v-for 同时存在时的优先级处理 :

<div id="app">
    <ul>
        <li>{{arr[0]}}</li>
        <li>{{arr[1]}}</li>
        <li>{{arr[2]}}</li>
    </ul>
    <hr>
    <!-- v-for 指令, 对数据进行遍历 -->
    <!-- 所有的遍历第一个位置都是值, 你想要的值, 第二个位置大多是 索引下标 -->
    <!-- 你起的名字并不重要 , 这些名字都是自定义的 -->
    <!-- 对数组进行遍历 -->
    <ul>
        <!-- <li v-for="item in arr"> -->
        <!-- index 索引 , 下标 -->
        <li v-for="(item, index) in arr">
            {{index}} - {{item}}
        </li>
    </ul>
    <ul>
        <!-- <li v-for="item in arr"> -->
        <!-- index 索引 , 下标 -->
        <li v-for="(value, i) in arr">
            {{i}} - {{value}}
        </li>
    </ul>
    <hr>
    <!-- 对 对象进行遍历 -->
    <ul>
        <!-- item 拿到每一项值 -->
        <!-- <li v-for="item in obj"> -->
        <!-- key 拿到你的 键 , 用来表示属性的唯一性-->
        <li v-for="(item, key, index) in obj">
            {{key}} - {{item}} - {{index}}
            <!-- 在对象的遍历中 index 值 没有太大的意义, 知道能获取到就可以了 -->
        </li>
    </ul>
    <hr>
    <!-- 对数字( 正整数 )进行遍历 -->
    <ul>
        <li v-for="item in 5">
            {{item}}
        </li>
    </ul>
    <!-- 遍历是从 1 开始的 , 如果从 0 开始 : 不展示 , 负数和小数点 => 直接报错 -->
    <!-- <ul>
        <li v-for="item in 100">
            {{item}}
        </li>
    </ul> -->
    <ul>
        <li v-for="(item, index) in 5">
            {{index}} - {{item}}
        </li>
    </ul>
    <hr>
    <!-- 对字符串进行遍历 -->
    <ul>
        <!-- <li v-for="item in 'qianduan小灰狼'"> -->
        <!-- <li v-for="(item, index) in 'qianduan小灰狼'"> -->
        <li v-for="(index, item) in 'qianduan小灰狼'">
            {{index}} - {{item}}
            <!-- index 就是 每一个 字符 , item 成了 索引下标 -->
            <!-- 并不是按照我们的名字进行取值的, 而是按照位置取值的 -->
        </li>
    </ul>
</div>
<hr>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
<script>
    const app = new Vue({
        el: '#app',
        data: {
            arr: ['item1', 'item2', 'item3', 'item4', 'item5', 'item6'],
            obj: {
                name: '张三',
                age: 18,
                height: 160
            }
        }
    });
</script>
<div id="app">
<!-- 
  数组循环 
  v-for="(数组元素,索引) in 数据" :key='唯一不重复的'
  v-for="(数组元素,索引) of 数据" :key='唯一不重复的'
  key是vue进行dom比对时的依据,有它则提升性能,没有也可以,但是性能比较低,不写会警告
  key不要用循环中的index索引,索引有塌陷问题
  如果你和后端合作时,一定要求后台给你的数据中有一个唯一不变化值(id)
  在vue2.x时如果你的v-if和v-for在一个标签写,v-for优先于v-if  
  template标签 它可以写v-if或v-for,但它还会编译生成html
  vue3.x中v-if优先级高于v-for
-->
<ul>
  <template v-if="n>=2">
	<li v-for="(item,index) in arr" :key="item">{{index}} -- {{item}}</li>
  </template>
  <template v-else>
	<li>数据加载中...</li>
  </template>
</ul>
<!-- 
  循环对象  vue对于 for of进行增强,它可以循环对象了
  v-for="(元素,key,index) in obj" :key="唯一值"
  v-for="(元素,key,index) of obj" :key="唯一值"
 -->
 <div v-for="(item,key,index) in obj">
   {{index}} --- 
   {{key}} --- 
   {{item}}
 </div>
</div>
<script>
const vm = new Vue({
  el: '#app',
  data: {
	n: 1,
	arr: [1, 2, 3, 4, 5, 6],
	obj: { id: 1, name: '张三' }
  }
})
</script>

JS 中实现循环对象 :利用 Object.defineProperty 方法 把对象中的 key 转变成数组

v-for 指令 遍历的问题 :

<div id="app">
    <!-- 对数组进行遍历 -->
    <ul>
        <li v-for="item in arr">
            {{item}}
        </li>
    </ul>
</div>
<hr>
<button @click="btnAction">按钮</button>
<!-- 
    Vue 第一次渲染的结果 :
    item1   item2   item3   item4   item5   item6
    执行 app.arr.push('new item') 渲染的结果 :
    item1(0)   item2(1)   item3(2)   item4(3)   item5(4)   item6(5)   newitem(6)
    执行 app.arr.splice(3, 1) 渲染的结果 :
    item1(0)   item2(1)   item3(2)   item5(4)   item6(5)   newitem(6)
-->
<!-- 现在出现的问题: 当执行 splice 时, item5 之后的数据都需要重新渲染, 实则没有必要 -->
<!-- 需要告诉 v-for 原来的 item , 和新的 item 要一一对应起来 -->
<!-- 需要给每一个值设置一个标记 , 标记不能使用下标 index -->
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
<script>
    const app = new Vue({
        el: '#app',
        data: {
            arr: ['item1', 'item2', 'item3', 'item4', 'item5', 'item6'],
        },
        methods: {
            btnAction() {
                // this.arr.push('new item')
                this.arr.splice(3, 1)
            }
        }
    });
</script>

解决 v-for 的问题 : 

<div id="app">
  <ul>
    <li v-for="item in arr"  v-bind:key="item.id">
      {{item.value}}
    </li>
  </ul>
  <button @click="btnAction">按钮</button>
  <!-- 
    vue第一次渲染的结果:
    item1   item2    item3   item4   item5   item6
    执行app.arr.push('new item')渲染的结果:
    item1(0)   item2(1)    item3(2)   item4(3)   item5(4)   item6(5)   newitem(6)
    执行app.arr.splice(3, 1)渲染的结果:
    item1(0)   item2(1)    item3(2)   item5(4)   item6(5)   newitem(6)
  -->
  <!-- 现在出现的问题:当执行splice时,item5之后的数据都需要重新渲染,实则没有必要。 -->
  <!-- 需要告诉v-for原来的item,和新的item要一一对应起来。 -->
  <!-- 需要给每一个值设置一个标记, 标记不能使用下标index -->
  <!-- 为了提高渲染的性能: -->
  <!-- 需要给遍历的数据提供唯一标记,并且在使用v-for遍历数据时,设置上key -->
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
  const app = new Vue({
    el: '#app',
    data: {
      // arr: ['item1', 'item2', 'item3', 'item4', 'item5', 'item6']
      arr: [
        {
          value: 'item1',
          id: 0
        },
        {
          value: 'item2',
          id: 1
        },
        {
          value: 'item3',
          id: 2
        },
        {
          value: 'item4',
          id: 3
        },
        {
          value: 'item5',
          id: 4
        },
        {
          value: 'item6',
          id: 5
        }
      ]
    },
    methods: {
      btnAction(){
        this.arr.splice(3, 1);
      }
    }
  });
</script>

2.4、v-on 指令

绑定事件监听器( 事件绑定

<div id="app">
<!-- 
  vue 中绑定事件 v-on:事件类型="方法"  v-on 简写 @
  方法可以不写小括号
  绑定的方法可以定义在 data 或 methods 方法中,但是 data 中不建议去定义,因为 data 中会有数据劫持
  如果不写小括号,vue 会自动把 event 对象给传入参数中,不写小括号事件没有办法传参数
  如果写小括号,vue 不会自动把 event 对象给传入参数中,需要手动传入,提供【$event】变量,有小括号传参数就很方便
-->
<!-- username这不是button标签默认属性,自定义属性,获取时一定要用getAttribute -->
<!-- <button username='张三' v-on:click="fn">点击事件</button> -->
<!-- html5中提供dataset对象 -->
<button data-username='张三' v-on:click="fn">点击事件</button>
<!-- <button v-on:click="fn($event,1,2,3)">点击事件</button> -->
<hr>
<!-- <input type="text" v-model='todo' @keyup.enter.ctrl="onenter"> -->
<!-- <input type="text" v-model='todo' @keyup.ctrl.90.prevent="onenter"> -->
<input type="text" v-model='todo' @keyup.ctrl.zzz="onenter">
</div>
<script>
Vue.config.keyCodes = {zzz:90}
// 实例化 Vue
const vm = new Vue({
  el: '#app',
  data: {
	msg: '你好 Vue',
	todo: ''
  },
  methods: {
	/* fn(ev, ...args) {
	  console.log('fn', ev, args)
	} */
	fn(ev) {
	  // console.log(ev.target.getAttribute('username'))
	  console.log(ev.target.dataset.username)
	},
	onenter(ev) {
	  // console.log(ev.keyCode == 13)
	  // console.log(this.todo)
	  console.log(ev.keyCode)
	}
  }
})
</script>
  • 事件处理函数传参 -- 事件对象--- event 对象
<div id="app">
    <!-- v-on 指令就是用来绑定事件的 -->
    <!-- 只要是 DOM 的事件 , 都可以使用 v-on 绑定 -->
    <div class="box" v-on:click="action1" v-on:mousemove="action2" v-on:contextmenu="action3">
    </div>
    <input type="text" v-on:keydown="action1">
    <!-- 简写 语法糖 -->
    <div class="box" @click="action1" @mousemove="action2" @contextmenu="action3"></div>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
<script>
    const app = new Vue({
        el: '#app',
        data: {
        },
        methods: {
            /* ES6 对象简写语法 :
            当某一个 key 的值是一个函数, 并且不是箭头函数的时候
            => 可以直接省略 function 关键字和 冒号(:) 不写 */
            action1: function () {
                console.log(1)
            },
            action2() {
                console.log(22)
            },
            action3: function () {
                console.log(333)
            }
        }
    });
</script>

v-on 指令传参 :

<div id="app">
    <div class="box" @click="action"></div>
    <!-- 添加事件后, 事件名字后面如果没有添加(), 那么事件参数使用 js 原生的
    但是如果添加了 () , 事件参数 , 按照 () 中的参数列表传入 -->
    <!-- 如果还需要事件对象, 那么就传入参数 $event, 名字是固定的 -->
    <div class="box" @click="action()"></div>
    <div class="box" @click="action(1, 2)"></div>
    <!-- $event  :  固定名字 , 不能更改 -->
    <div class="box" @click="action(1, $event, 2)"></div>
    <div class="box" @click="action(message, 1, $event, 2)"></div>
    <ul>
        <li v-for="(item, index) in arr" class="item">
            <span>{{item}}</span>
            <button @click="itemAction(index)">按钮</button>
        </li>
    </ul>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
<script>
    const app = new Vue({
        el: '#app',
        data: {
            message: 'hello world',
            arr: ['item1', 'item2', 'item3']
        },
        methods: {
            // action(...rest) {
            //     console.log(11)
            //     console.log(rest);
            // }
            action(...rest) {
                console.log('print:');
                console.log(...rest)
            },
            itemAction(i) {
                console.log('item 被点击了');
                console.log(i);
            }
        }
    });
/*  ... 是 展开运算符
// => 当这个符号书写在函数的形参位置的时候, 叫做合并运算符
function test(name, value, ...rest) {
// ...rest ( 剩余参数 ) ; 只要写 ... 就能接收到剩余的参数 , 将数据都放到这个数组当中 , 开发习惯命名为 rest , 表示接收剩余参数
    console.log(arguments); // 不是数组 , 是 类数组(伪数组)
    // console.log(argument[0]);
    console.log(rest); // rest 是数组
    // console.log(name, value);
}
test()
test(1)
test(1, 2)
test(1, 2, 3, 4) */
</script>

v-on 事件修饰符 :

<!DOCTYPE html>
<html lang="en">
<!-- 以前获取键盘事件需要兼容 , 现在的话不需要 , 因为 Vue 只在 IE8 以上的版本才支持 -->
<!-- Vue 不支持 IE8 及以下版本 , 因为 Vue 使用了 IE8 无法模拟的 ECMAScript 5 特性 -->
<!-- 面试挖坑 : 判断你有没有 Vue 的开发经验 -->
<!-- 会问你 : 你做过的 Vue 项目是怎么兼容 IE8 以下的版本啊?
答 : 我们不做 IE 浏览器的兼容 , IE8 以下的浏览器我们公司是不会考虑的 
我们做的项目是只给公司的供应商或者采购部门的人员使用的 , 我们做的项目是要求用户必须
使用谷歌浏览器才能打开的 , 不做其他浏览器的兼容
-->
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Vue _ 数据双向绑定</title>
    <style>
        .outer {
            padding: 50px;
            background-color: red;
        }
        .center {
            padding: 40px;
            background-color: green;
        }
        .inner {
            padding: 80px;
            background-color: skyblue;
        }
    </style>
</head>
<body>
    <div id="app">
        <!-- 
    v-on  指令的修饰符 :
    .stop  阻止事件冒泡
    .capture  事件进行捕获
    .prevent  阻止默认事件
    .once  事件只会执行一次
    .self  事件之作用给标签本身
-->
        <!-- <div class="outer" @click="outerAction">
            <span>Outer</span>
            <div class="center" @click="centerAction">
                <span>Center</span>
                <div class="inner" @click="innerAction">
                    <span>Inner</span>
                </div>
            </div>
        </div> -->
        <!-- 阻止 事件冒泡 -->
        <!-- <div class="outer" v-on:click.stop="outerAction">
            <span>Outer</span>
            <div class="center" @click.stop="centerAction">
                <span>Center</span>
                <div class="inner" v-on:click.stop="innerAction">
                    <span>Inner</span>
                </div>
            </div>
        </div> -->
        <!-- .capture  事件 进行 捕获 -->
        <div class="outer" v-on:click.capture="outerAction">
            <span>Outer</span>
            <div class="center" @click.capture="centerAction">
                <span>Center</span>
                <div class="inner" v-on:click.capture="innerAction">
                    <span>Inner</span>
                </div>
            </div>
        </div>
        <div class="inner" @contextmenu.prevent="innerAction"></div>
        <!-- <input type="text" @keydown="keydownAction"> -->
        <!-- .enter  表示你敲了 回车键 -->
<!-- 键盘按键修饰符 : 可以用按键的名字 , 也可以用按键的 keycode -->
        <input type="text" @keydown.enter="keydownAction" placeholder="回车键">
        <input type="text" @keydown.delete="keydownAction" placeholder="删除键">
        <input type="text" @keydown.up="keydownAction" placeholder="上键">
        <input type="text" @keydown.right="keydownAction" placeholder="右键">
        <input type="text" @keydown.down="keydownAction" placeholder="下键">
        <input type="text" @keydown.left="keydownAction" placeholder="左键">
        <input type="text" @keydown.middle="keydownAction" placeholder="中键">
        <input type="text" @keydown.control="keydownAction" placeholder="control键">
        <input type="text" @keydown.a="keydownAction" placeholder="a键">
        <input type="text" @keydown.89="keydownAction" placeholder="y键">
<!-- 鼠标的左右键修饰符 -->
        <div class="outer" @click.left="boxAction"></div>
        <hr>
        <!-- click.right  等价于  contextmenu -->
        <div class="outer" @click.right="boxAction"></div>
        <hr>
        <!-- 修饰符可以接连叠加书写使用的 , 并且不分先后顺序 -->
        <div class="outer" @click.right.prevent="boxAction"></div>
        <div class="outer" @click.prevent.right="boxAction"></div>
        <div class="center" @click.once="boxAction"></div>
        <div class="outer" @click="outerAction">
            <span>Outer</span>
            <div class="center" @click.self="centerAction">
                <span>Center</span>
                <div class="inner" @click="innerAction">
                    <span>Inner</span>
                </div>
            </div>
        </div>
        <!-- 浏览器需要等待内核线程执行到这个事件监听器才知道是否阻止默认事件 -->
        <div class="inner" @contextmenu="innerAction"></div>
        <hr>
        <!-- passive 修饰符直接告诉代码不能等了 , 就是没有阻止默认事件的方式去执行 -->
        <div class="center" @contextmenu="centerAction"></div>
    </div>
    <hr>
    <script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
    <script>
        const app = new Vue({
            el: '#app',
            // 配置 Vue 实例的方法
            methods: {
                outerAction() {
                    console.log('outer');
                },
                centerAction() {
                    console.log('center');
                },
                innerAction() {
                    console.log('inner');
                },
                keydownAction(ev) {
                    console.log(ev);
                    /* // 原生 JS 处理方式 :
                    if(ev.keycode === 13) {
                        // ......
                    } else {
                        return;
                    } */
                },
                boxAction() {
                    console.log('box action 触发了 ...');
                }
            }
        });
    </script>
</body>
</html>
  • 事件修饰符

用来处理事件的特定行为

<!-- 阻止冒泡 -->

<button @click.stop = "doThis"></button>

<!-- 阻止默认行为 -->

<a @click.prevent = "doThis"></a>

<!-- 只执行一次 -->

<div @click.once = "incr( )">自增一下</div>

<!-- 绑定的元素本身触发时才触发回调 -->

<ul @click.self = "incr( )">

<li>你好世界</li>

</ul>

<!--  串联修饰符 -->

<button @click.stop.prevent = "doThis"></button>

4.5、v-bind 指令

动态 地 绑定 一个或多个 属性  ( 简写  =>  :  )

<div id="app">
    <a v-bind:href="path">点击进入</a>
    <a :href="path">百度一下</a>
    <h1 :title="title">hello Vue</h1>
    <h1 v-bind:title="title">hello Vue</h1>
    <div class=""></div>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
<script>
    const app = new Vue({
        el: '#app',
        data: {
            path: 'http://www.baidu.com',
            title: '大前端'
        }
    });
</script>

v-bind 绑定 class

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>v-bind 绑定 class</title>
    <style>
        .box {
            width: 200px;
            height: 200px;
            border: 10px solid pink;
        }
        .one {
            background-color: red;
        }
        .two {
            background-color: skyblue;
        }
        .active {
            background-color: purple;
        }
    </style>
</head>
<body>
    <div id="app">
        <!-- class="box one"  class 会使用空格合并在一起-->
        <!-- 绑定 class 的方式 1 : 自己操作 class 的字符串 -->
        <div class="box" :class="value"></div>
<!-- 绑定 class 的方式 2 : 绑定的值为一个数组 , Vue 会将数组扁平化 , 把每一项合并给 class -->
        <div class="box" :class="arr"></div>
        <!-- 扁平化 , 与 box 进行 合并 -->
        <div class="box" :class="['one', 'two', ['three', 'four']]"></div>
        <!-- title="one" -->
        <div title="box" :title="value"></div>
        <!-- title="box" -->
        <div :title="value" title="box"></div>
<!-- 绑定 class 的方式 3 : 绑定一个对象 , 对象的属性为 true , 那么 key 就会被合并给 class -->
        <div class="box" :class="obj"></div>
        <hr>
        <!-- 对象和数组是可以混合在一起写的 -->
        <div class="box" :class="['one', 'two', {three:true, four:false}, ['five', {six: false, seven: true}]]"></div>
        <hr>
        <ul>
            <li v-for="(item, index) in 5" :class="{active: index === clickIndex}">
                {{item}}
                <button @click="itemAction(index)">按钮</button>
            </li>
        </ul>
    </div>
    <hr>
    <script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
    <script>
        const app = new Vue({
            el: '#app',
            data: {
                value: 'one',
                arr: ['one', 'two'],
                obj: {
                    one: true,
                    two: false
                },
                clickIndex: -1
            },
            methods: {
                itemAction(index) {
                    console.log(index, "被点击了");
                    this.clickIndex = index
                }
            }
        });
    </script>
</body>
</html>

2.6、v-model 指令

作用: 表单元素的绑定,实现了 双向数据绑定 ,通过表单项可以更改数据。

v-model 会忽略所有表单元素的 value、checked、selected 特性的 初始值 , 而总是将 Vue 实例 的数据作为数据来源,应该在 data 选项中声明 初始值 。

<div id="app">
<h3>{{msg}}</h3>
<!-- v-model就是它们语法糖 -->
<!-- <input type="text" :value='msg' @input='setValue'> -->
<input type="text" v-model="msg">
<hr>
<textarea v-model="body"></textarea>
</div>
<script>
// 实例化Vue
const vm = new Vue({
  el: '#app',
  data: {
	msg: '你好Vue',
  },
  methods: {
	setValue(ev) {
	  this.msg = ev.target.value.trim()
	}
  }
})
</script>

 

 

 

 

 

2.7、v-pre 指令

跳过这个元素和它的子元素的编译过程,跳过大量没有指令的节点会加快编译。

<span v-pre> 不需要编译,直接可以运行 </span>

<!-- 性能优化 的指令,此指令让 Vue 不去把 Dom 转为虚拟 Dom -->
<!-- this will not be compiled : 这将不会被编译 -->

2.8、v-cloak 指令

解决浏览器在加载页面时因存在时间差而产生的 “ 闪动 ” 问题

2.9、v-once 指令

只渲染元素和组件一次,之后元素和组件将失去响应式功能

<div id="app">
	<h3>{{message}}</h3>
	<hr>
    <!-- 只绑定一次,后续修改数据源不会更改视图 -->
	<!-- 动态修改message值,此绑定将不会发生改变 -->
	<div v-once>{{message}}</div>
</div>
<script src="./vue.js"></script>
<script>
  const vm = new Vue({
    el: '#app',
    data: {
      message: '你好世界'
    }
  })
</script>


样式绑定

1、class 样式处理

  • 数组语法

data: {

activeClass: 'active'

}

追加样式 : 

2、绑定 style


三、自定义指令

自定义指令 — Vue.js

除了核心功能 默认内置 的 指令,Vue 也允许 注册 自定义指令 。有的情况下,对普通 DOM 元素进行底层操作,这时候就会用到 自定义指令 绑定到元素上执行相关操作。

自定义指令分为:全局指令 和 局部指令,当全局指令 和 局部指令同名时以 局部指令 为准 。

自定义指令 常用 钩子函数

注:指令中不能直接操作 Vue 中的 data 数据 和 methods 方法 ,

也就是指令中的 this 不是指向 Vue 实例对象

  • bind        第一次 绑定 到元素时 调用
  • inserted  被 绑定元素 插入 父节点时 调用 ( 仅保证父节点存在,但不一定已被 插入 文档中 )
  • update    数据 更新 时 调用 ( 所在组件的 VNode 更新 时调用,但是可能发生在其子 VNode 更新 之前)
  • componentUpdated  指令所在组件的 VNode 及其子 VNode 全部 更新 后 调用 。
  • unbind     只调用一次,指令与元素 解绑 时 调用 。

 

<div id="app" v-if="flag">
  <h3 v-red>
    <input type="text" v-model='title'>
  </h3>
  <button @click="flag=false">隐藏</button>
</div>
<script>
  // 切面编程
  // 全局指令定义
  // 参数1:书写自定义指令的名称,不要加 v- 前缀
  // 参数2:对象(标准写法) | 函数(简写,它是 bind 和 update 合成体)
  Vue.directive('red', {
    // el 它就是绑定指令的 dom 对象
    bind(el) { // 第一次绑定到元素时调用
      // el.style.color = 'red'
      // el.style.cssText = 'color:blue;font-size:50px;'
      console.log('bind')
    },
    inserted(el) { // 被绑定元素插入父节点时调用
      console.log('inserted')
    },
    update(el) { // 数据更新时调用
      console.log('update')
    },
    componentUpdated(el) { // 指令所在组件的 VNode 及其子 VNode 全部更新后调用
      console.log('componentUpdated')
    },
    unbind(el){ // 只调用一次 , 指令与元素解绑时调用
      console.log('unbind')
    }
  })
  const vm = new Vue({
    el: '#app',
    data: {
      title: '你好世界',
      flag: true
    }
  })
</script>

在指令中 获取 和 操作 data 数据 :

 案例 : 使用自定义指令-表单项验证

<!-- 2.挂载点 -->
<div id="root">
	<h3 v-red>主题</h3>
	<input type="text" v-username v-model="username">
	<input type="text" v-phone v-model="phone">
</div>
<!-- 3.进行实例化操作 -->
<script>
	// 定义 全局指令
	// 参数1 : 自定义指令的 名称 , 不要 v-  前缀
	// 参数2 : object || 函数[它是 bind 和 update 钩子函数的简写]
	// el 它就是绑定指令的 DOM 对象
	// 写法相当于写了  bind / update
	Vue.directive('red', (el, bindings) => {
		el.style.cssText = 'color:blue'
	})
	Vue.directive('username', (el, bindings) => {
		// startsWith 它是 es6 提供的 字符串方法  以什么什么开头
		if (el.value.startsWith('a')) {
			el.style.cssText = 'color:red'
		} else {
			el.style.cssText = 'color:#000'
		}
	})
	Vue.directive('phone', (el, bindings) => {
		if (!/^1[3-9]\d{9}$/.test(el.value.trim())) {
			el.style.cssText = 'color:red'
		} else {
			el.style.cssText = 'color:#000'
		}
	})
	const vm = new Vue({
		el: '#root',
		data: {
			username: '',
			phone: ''
		},
		methods: {}
	})
</script>

<div id="app">
  <div>
    <label>
      账号:
      <input type="text" v-model='username' v-len>
    </label>
  </div>
</div>

<!-- 支持es6模块化 -->
<script type="module">
  import validator from './js/Validator.js'
  // 全局指令定义
  // 参数1:书写指令名称,不要加v-
  // 参数2:对象(标准写法) | 函数(简写,它是bind和update合成体)
  // 回调函数中的参数2,它就是用来获取指令参入的参数
  Vue.directive('len', validator.len)

  const vm = new Vue({
    el: '#app',
    data: {
      username: '',
      username_msg: ''
    },
    methods: {
      fn(msg) {
        this.username_msg = msg
      }
    }
  })
</script>
// 默认导出,一个文件只能默认导出一次
export default {
  len(el, binds) {
    el.style.color = el.value.trim().length > 3 ? 'red' : '#000'
    if (el.value.trim().length > 3) {
      if (el.parentNode.lastChild.nodeName != 'SPAN') {
        let span = document.createElement('span')
        span.innerHTML = '字数超长了'
        el.parentNode.appendChild(span)
      }
    } else {
      if (el.parentNode.lastChild.nodeName == 'SPAN') {
        el.parentNode.removeChild(el.parentNode.lastChild)
      }
    }
  }
}

自定义修饰符 :

 

使用修饰符实现验证器 : ( 验证手机号及最小字符 ) 

<div id="app">
  <input type="text" v-model="phone" v-validate.phone>
  <hr>
  <input type="text" v-model="username" v-validate="{min:2}">
</div>

<script type="module">
  import valid from './js/Valid.js'
  Vue.directive('validate', (el, binds) => {
    // map forEach
    Object.keys(binds.modifiers).forEach(fnName => valid[fnName](el, binds))
    // 只有前面操作有值时才进行循环  它有undefined可能   js 短语运算   ts 断言
    binds.value && Object.keys(binds.value).forEach(fnName => valid[fnName](el, binds))
    /* if(binds.value){
      Object.keys(binds.value).forEach(fnName => valid[fnName](el, binds))
    } */
    // 获取对象中的 value 值,返回一个数组
    // Object.values()
    // 获取地象中的 key 值,返回一个数组
    Object.keys()
    // es6 判断是否为数组 true/false
    // Array.isArray(变量)
  })

  const vm = new Vue({
    el: '#app',
    data: {
      phone: '',
      username: ''
    }
  })
</script>
export default {
  phone(el, binds) {
    if (!/^1[3-9]\d{9}$/.test(el.value)) {
      el.style.color = '#f00'
    } else {
      el.style.color = '#000'
    }
  },
  min(el, binds) {
    if (binds.value.min) {
      if (el.value.length <= binds.value.min) {
        el.style.color = '#f00'
      } else {
        el.style.color = '#000'
      }
    }
  }
}

按钮权限控制 :

inserted 被绑定元素 插入 父节点时调用 ( 仅保证父节点存在,但不一定已被插入文档中 ) 


图例 :


跳转链接 =>  Vue _ 教程版 01 基础

跳转链接 =>  Vue _ 教程版 03

跳转链接 =>  Vue _ 教程版 04 组件

跳转链接 =>  Vue _ 教程版 05


http://www.niftyadmin.cn/n/1498306.html

相关文章

Elasticsearch在windows上安装好了之后怎么使用?

windows 10上安装Elasticsearch过程记录一、安装和配置Java JDK1、下载&#xff1a;http://download.oracle.com/otn ... 4.exe2、设置环境变量&#xff1a;(1)点击【系统变量】下的【新建】按钮变量名&#xff1a; JAVA_HOME 变量值&#xff1a; C:\Program Files\Java\jdk1.8…

python中if的效率_python中关于if-else使用性能的一点感悟

今天做leetcode第7题关于数字倒序的问题&#xff0c;分别使用如下程序&#xff1a;(72ms) class Solution: def reverse(self, x): """ :type x: int :rtype: int """ #maxNum 2**31-1 #minNum -1*2**31 i 1 if(x<0): i,x -1,abs(x) x_s …

Vue 中的知识点

目录 Vue中的侦听器&#xff08;watch&#xff09; Vue中的过滤器&#xff08;filter&#xff09; Vue中的生命周期 Vue中的网络请求 ajax、axios、fetch的区别 axios 使用方法 axios 封装代码&#xff08;直接使用&#xff09; Vue中的组件 全局组件 局部组件 组件…

运维学习之find命令基础

文件查找1.locate filename ##在文件数据库中搜索filename信息&#xff0c;updatedb更新文件数据库2.findfind 查找位置 -条件 条件值 -exec 动作 {} \; -name-not 不包含**条件-user 用户-group 组-size 大小-perm 按文件权限--m…

HTML嵌入多媒体对象

【问题描述】如何在HTML中嵌入pdf、word&#xff0c;音频(如mp3)&#xff0c;视频(如mp4)&#xff0c;flash呢&#xff1f; 【分析】 1 嵌入pdf (1) 利用object <object classid"clsid:CA8A9780-280D-11CF-A24D-444553540000" width"1000" height"…

deque stack java_「集合系列」- 初探 java 集合框架图

实际开发中&#xff0c;经常用到 java 的集合框架&#xff0c;比如 ArrayList 、 LinkedList 、 HashMap 、 LinkedHashMap&#xff0c;几乎经常接触到&#xff0c;虽然用的多&#xff0c;但是对集合的整体框架&#xff0c;基础知识还是不够系统&#xff0c;今天想和大家一起来…

移动平均算法公式

MA/SMA/DMA/EMA移动平均算法公式1、简单移动平均MA用法:MA(X,N):X的N日简单移动平均算法(X1X2X3...Xn)/N2、移动平均SMA用法:SMA(X,N,M),求X的N日移动平均&#xff0c;M/N为给予观测值X的权重,N必须大于M。算法: 若YSMA(X,N,M)则 Y[M*X(N-M)*Y)]/NM/N*X (N-M) /N *Y),其中Y表示…

华为服务器显示H61,认清真相 市售H61为何有2/4插槽之分

谁都想要便宜量又足的货物&#xff0c;例如去超市碰到降价打折产品&#xff0c;又例如突然发现自己的很想买的一套衣服换季促销中&#xff0c;甚至看见网页上通过安装优化软件就能整理内存释放更多内存&#xff0c;都会让人冲动一阵子&#xff0c;兴奋一阵子。可实际上当你把超…