目录

一、指令

二、Vue中的常用内置指令

        1)v-show

         2)v-if

         3)v-if,v-else

        4)v-if-else-if

        5)v-for

        6)v-on

        7)v-html(解析html标签)

        8)v-cloak和v-text(即使遇到标签,也原样输出)

         9)v-once

         10)v-pre

 三、自定义指令

四、ref索引


一、指令

        Vue中什么是指令?

        在表现形式上,就是带有’v-'前缀的属性。v-属性名=‘具体表达式’。当表达式对应的值发生变化后,将响应式的作用于Dom,从而影响视图层。更为具体的说,指令结合属性作为暗号,框架会根据按照对应的不同的值来进行Dom操作的绑定。因此,帮我们在实际开发中做了减法。

二、Vue中的常用内置指令

1)v-show

元素的显示或隐藏时,都用v-show。

原理:只要new Vue()扫描到v-show,就会先计算=右边的判断条件的值,如果=右边的判断条件值为true,则当前元素默认正常显示,如果=右边的判断条件值为false,则v-show自动被翻译为style="display:none",表示当前元素隐藏

<body>
    <div id="app">
        <button @click='show=false'>隐藏</button>
        <button @click='show=true'>显示</button>
        <button @click='show=!show'>切换</button>
        <h1 v-show='show'>Hello Vue!</h1>
    </div>
    <script>
        new Vue({
            el: '#app',
            data: { show: true },
        })
    </script>
</body>

     2)v-if

        专门控制两个元素二选一显示,当要在两个元素之间选择一个时,就用v-if和v-else。

        原理:当new Vue()扫描到v-if时,先计算=右边条件变量或表达式的值,如果v-if等号右边的条件为true,则new Vue()会保留v-if所在元素,删除v-else所在元素;如果v-if等号右边条件为false,则new Vue()会先删除v-if所在的元素,保留v-else所在的元素。根据条件来加载元素

<body>
    <div id="app">
        <button @click='add=false'>删除</button>
        <button @click='add=true'>添加</button>
        <!-- v-if指令:根据条件来加载元素 -->
        <h1 v-if='add'>灰太狼来了!</h1>
    </div>
    <script>
        new Vue({
            el: '#app',
            data: { add: true }
        })
    </script>
</body>

小结:Vue中隐藏元素的方式有哪些?他们有什么区别?分别有什么用途?(面试题)
        1)Vue中 v-show 和 v-if 都能实现元素的隐藏操作;

差异:

                v-show:利用css的display='none'实现隐藏

vue试用shutdown指令 vue所有指令_vue.js

                v-if:利用 DOM 元素的移除,实现隐藏

vue试用shutdown指令 vue所有指令_vue.js_02

    3)用途:

                v-show:适合频繁切换显示的场景

                v-if:移除/增加 DOM,消耗高,会降低页面的性能,适合一次性使用的场景

eg:之后我们的数据都来源于网络,假设发送请求需要1s,则 在请求完毕前,先隐藏一部分页面,请求完成后再显示。

      3)v-if,v-else

        也是用来控制元素的显示与消失,需要注意的是:当使用了v-if=‘true’的元素显示时,则使用v-else的元素不会显示;当使用了v-if=‘false’的元素不显示时,则使用了v-else的元素会显示

        通过一个模拟请求数据的案例,来说明:

vue试用shutdown指令 vue所有指令_vue试用shutdown指令_03

vue试用shutdown指令 vue所有指令_前端_04

<body>
    <div id="app">
        <button @click='getData'>请求数据....</button>
        <!-- skills是null,则页面显示加载中 -->
        <div v-if='skills==null'>加载中...</div>
        <!-- 否则 不显示 -->
        <div v-else>
            <h1>请求数据已到达...显示中....</h1>
            <div>{{skills}}</div>
        </div>
    </div>
    <script>
        new Vue({
            el: '#app',
            data: {
                skills: null
            },
            methods: {
                getData() {
                    //模拟请求数据 需要1s
                    console.log('请求数据....');
                    setTimeout(() => {
                        console.log('数据请求完毕..');
                        this.skills = 'html-css-js'
                    }, 1000);
                }
            },
        })
    </script>
</body>

4)v-if-else-if

多个元素选择一个显示隐藏时,都用v-else-if

<body>
    <div id="app">
        <!-- 怒气值>=100 显示 揍灰太狼!! -->
        <!-- 怒气值>=70 显示 骂灰太狼! -->
        <!-- 怒气值>=30 显示 抓羊! -->
        <!-- 否则 显示 给灰太狼做饭! -->
        <div>红太狼的怒气值:{{score}}</div>
        <button @click='score-=10'>-10</button>
        <button @click='score+=10'>+10</button>
        <p v-if='score>=100'>揍灰太狼!!</p>
        <p v-else-if='score>=70'>骂灰太狼!</p>
        <p v-else-if='score>=30'>抓羊!</p>
        <p v-else>给灰太狼做饭</p>
    </div>
    <script>
        new Vue({
            el: '#app',
            data: {
                score: 50
            }
        })
    </script>
</body>

 原理:当new Vue()扫描到v-if时,先计算v-if后的条件,如果v-if条件为true,则保留v-if所在元素,删除其余v-else-if、v-else元素;如果v-if条件为false,则先删除v-if所在元素,然后,继续计算每个v-else-if后的条件;如果任意一个v-else-if的条件为true,则只保留着一个v-else-if所在元素,删除其余v-if、v-else-if和v-else元素;如果所有v-if和v-else-if的条件都不满足,则只保留v-else,删除其余v-if和v-else-if的元素。

5)v-for

        专门在网页中根据一个数组或对象的成员,连续生成多个结构相同,内容不同的一组html元素的特殊指令,只要连续生成一组结构相同,但是内容不同的HTML元素时,都用v-for批量生成

<body>
    <div id="app">
        <!--在 v-for中 of和in效果相同,随意写 -->
        <button v-for='value of names'>{{value}}</button>
        <button v-for='a in names'>{{a}}</button>
    </div>
    <script>
        new Vue({
            el: '#app',
            data: { names: ['喜羊羊', '懒羊羊', '沸羊羊', '慢羊羊', '美羊羊'] }
        })
    </script>
</body>

原理:每当new Vue()扫描到v-for时,先遍历数组或对象中每个成员;每遍历一个成员,取出当前成员的属性名和属性值,将属性值交给of前的()中第一个变量,将属性名/下标交给of前的()中第二个变量;同时会自动创建当前v-for所在元素的一个新副本,数组或对象包含几个成员v-for就会反复创建几个HTML元素副本。

<要反复生成的元素  v-for="(元素值, 下标) of 数组">
<要反复生成的元素  v-for="(属性值, 属性名) of 对象">

注意:

  • v-for只需一个元素当模板
  • v-for统一了js中的for in和for of的功能
  • vue中的v-for既可以遍历索引数组,又可以遍历对象
  • 在 v-for 中,下标和属性名可以省略不写,但是如果需要序号或者属性名时,可以加上

        of前的两个变量,虽然没有在new Vue()的data中的定义,但可以在v-for所在元素及其子元素范围内用于绑定语法和指令。

下面是一个通过v-for向页面中遍历数组的案例:

<body>
    <div id="app">
        <!--在 v-for中 of和in效果相同,随意写 -->
        <button v-for='value of names'>{{value}}</button>
        <button v-for='a in names'>{{a}}</button>
    </div>
    <script>
        new Vue({
            el: '#app',
            data: { names: ['喜羊羊', '懒羊羊', '沸羊羊', '慢羊羊', '美羊羊'] }
        })
    </script>
</body>

         v-for本身也存在一些问题, 即使只修改了数组或对象中一个成员的值,v-for默认也会删除所有元素副本,重新遍历和创建创建HTML元素副本,这样效率极低。

        这是因为v-for生成的多个HTML元素副本,除了内容不同之外,元素本身没有任何差别,所以v-for每次只能删除所有HTML副本,再重建整个列表。

        解决:只要使用v-for都必须同时绑定一个专门的属性: :key="不重复的值"

        拥有key值之后,v-for就可以通过key属性值来鉴别每个HTML元素副本不同,修改时只要修改某一个key的元素即可,不用重建整个列表。

v-for为什么必须加 :key(面试题)

        a.为每个元素添加唯一标识;

        b.避免重建整个列表;

        c.提高修改的效率。

 拓展1:

遍历数字的语法(在 in/of 后面直接写一个数字,可以直接遍历并使用它)。

vue试用shutdown指令 vue所有指令_Vue_05

<button v-for='n in 5'>鲁班{{n}}号</button>

拓展2:如何解决v-for中:key的静态报错问题?

        出现的原因:由于我们使用的VScode能够快捷生成v-for的基本结构,其中会自带 :key这个属性,但是如果你不写值,VScode会自动解析代码,它会认为你的代码是错误的,从而产生静态报错,但是不会影响程序的执行。

        解决方法:

        1)如果不需要使用 :key 这个属性,直接删掉这个属性就可以了,但是需要每次都删掉它,比较麻烦;

2)“设置”- > 搜索 vetur.validation.template 把勾选去掉(之后VScode就不因为 :key 的问题误报了)  

6)v-on

        v-on是Vue1中常用的绑定事件的指令,只要在vue中要给元素绑定事件处理函数,都用v-on,在Vue2中,直接用@代替。

<元素 v-on:事件名="事件处理函数(实参值,...)"
 
//简写:
//所有v-on,都可简写@: 
<元素 @事件名="事件处理函数(实参值,...)"
 
//如果事件处理函数不需要传实参值,则可以省略()
<元素 @事件名="事件处理函数"
 
//传参: vue中事件处理函数,可以传实参值:
<元素 @事件名="事件处理函数(实参值1, 实参值2,...)"
 
   methods:{
    事件处理函数(形参1, 形参2, ...){ 
      }
    }

      在vue中获得事件对象e:

<元素 @事件名="事件处理函数" //一定不要加()
 
    methods:{
      事件处理函数(e){ } //e指代event
    }

        如果既想传实参值,又想获得事件对象,就要借助于vue中的一个关键字$event,专门在vue中提前获得事件对象。

<元素 @事件名="事件处理函数($event, 其它实参, ...)"
 
     methods:{
       事件处理函数(e, 形参,...){
         e->event //结果是一样的
       }
     }

        在事件触发时,$event关键字会提前获得事件对象event,再由vue框架代为转交给事件处理函数对应的形参变量;只要使用$event关键字获得事件对象,则参数顺序无所谓,只要形参和实参可以对应即可。

        7)v-html(解析html标签)

要绑定的内容是一段包含HTML内容的代码片段时,都用用v-html

innerHTML,会先将HTML片段交给浏览器解析,将解析后文本显示到页面。

<元素 v-html="变量或表达式"></元素>

还要注意:v-html不能将写死的部分字符串和变化的变量轻易拼接,必须使用js中的模板字符串才能拼接。

<body>
    <div id="app">
        <h3>这本书是: {{msg}}</h3>
        <h3 v-html="`这本书是:${msg}`"></h3>
    </div>
    <script>
        new Vue({
            el: "#app",
            data: { msg: `这本书是<a href="#"><<喜羊羊与灰太狼>></a>` }
        })
    </script>
</body>

vue试用shutdown指令 vue所有指令_vue.js_06

8)v-cloak和v-text(即使遇到标签,也原样输出)

         当网速慢时,new Vue()有可能延迟加载,用户就有可能短暂看到页面上的{{ }}语法。这个时候就可以用到v-cloakv-text

        (1)v-cloak

在new Vue()加载之前,暂时隐藏部分元素的特殊指令,如果希望在new Vue()加载完之前,暂时隐藏部分元素,避免用户短暂看到{{ }},都可以用v-cloak。

1、在css中用属性选择器,选择所有带有v-cloak属性的元素,使用display:none,手工隐藏这些元素

2、用法:<要暂时隐藏的元素 v-cloak>

         原理:在new Vue()加载完之前,v-cloak和css中的属性选择器[v-cloak]联合发挥作用,隐藏部分元素,当new Vue()加载完之后,会自动查找页面中所有v-cloak的元素,自动删除所有v-cloak属性。

        (2)v-text

        专门代替{{ }}绑定元素内容的特殊指令,只要不想让用户短暂看到{{ }},都可用v-text代替{{ }}。        

用法:<要隐藏的元素 v-text="变量或表达式"></要隐藏的元素>

注意如果v-text的内容由需要部分写死的文本和变化的内容拼接而成,必须用模板字符串 。 

小结:对比v-cloak和v-text: 

  • 只需在父元素上添加v-cloak,就可以批量隐藏元素
  • 使用v-text时如果需要隐藏的元素过多则需重复使用;所以推荐使用v-cloak。

9)v-once

不会自动更新页面;如果一个元素的内容,只会在首次加载时绑定一次,之后几乎不会改变时,都用v-once标记。

<元素 v-once>{{...}}</元素>

 原理:凡是标有v-once的元素,new Vue()只在首次挂载时,动态更新元素的内容,但不会将v-once的元素加入到虚拟DOM树中,所以将来就算变量值发生变化,也无法通知到这个元素。

不会加入虚拟DOM树中,所以减少了虚拟DOM树中的元素的个数,虚拟DOM树遍历更快,效率更高。

举个栗子:

<body>
    <div id="app">
        <!-- data中的数据在变更时会自动更新DOM -- 默认设定  -->
        <button @click='num++'>{{num}}</button>
        <!-- 特殊设定: 显示完毕后 不要随着数据变化 -- 一次性 -->
        <p v-once>{{num}}</p>
    </div>
    <script>
        new Vue({
            el: '#app',
            data: { num: 1 },
        })
    </script>
</body>

效果如下:

v-once 的标签,数据不会发生变化。

vue试用shutdown指令 vue所有指令_前端_07

10)v-pre

不希望被vue编译的{{ }}时,采用v-pre保护。原样输出,包括{{}}

举个栗子:

<body>
    <div id="app">
        <div v-pre>{{msg}}</div>
    </div>
    <script>
        new Vue({
            el: '#app',
            data: { msg: 'Hello!' }
        })
    </script>
</body>

效果如下:

vue试用shutdown指令 vue所有指令_前端_08

 三、自定义指令

        如果希望在开始时就能对HTML元素执行一些初始化DOM操作(如自动获得焦点),但是vue中没有提供对应功能的指令。这时就可以自定义指令。

创建自定义指令

1、directives属性:用来存储自定义指令

2、在使用自定义指令是,用 ”v-“ 开头

3、在创建自定义指令时,不用写 v- 

4、在创建自定义指令时,有两个固定的参数:

    (1)el:指的是指令所在的元素(能够用来快速找到元素)

    (2)binding:与此指令绑定的相关值(传的值)

指令的本质:代替DOM的选择器,可以快速查找到元素,然后自动触发。

<body>
    <div id="app">
        <!---使用自定义属性-->
        <div v-green>喜羊羊</div>
        <!--- 指令的值是 JS代码,一定要加 引号 !!!-->
        <div v-color="'red'">喜羊羊</div>
        <!--- 页面刷新后输入框获取焦点 -->
        <input v-focus type="text" />
    </div>
    <script>
        new Vue({
            el: '#app',
            //创建自定义属性
            directives: {
                // 传一个参数
                green(el) { el.style.color = 'green' },
                // 传两个参数
                color(el,binding) { 
                    console.log(binding.value)  //red
                    el.style.color = binding.value
                },
    // 因为在输入框获取焦点的时候,要在页面元素挂在完成后,再触发,所以涉及一个元素生命周期的问题
                focus(el){
                    bind(el){
                      console.log('bind:在元素创建时触发')
                    },
                    inserted(el){
                      console.log('inserted:在元素挂载完之后触发')
                      el.focus()
                    }
                },
            },
        })
    </script>
</body>

注意:自定义指令写在HTML中,而HTML只认识小写字母,所以不能使用驼峰命名法,如果包含多个单词,可以用”-“隔开。

原理:Vue.directive()是创建一个自定义指令对象,保存在Vue类型的内存中备用。new Vue()扫描时,发现v-开头的自定义指令,就去Vue内存中找同名的自定义指令,找到同名的自定义指令,就自动执行自定义指令对象中的inserted()函数,并将当前扫描到的带有自定义指令的元素对象传给inserted()的形参变量;在inserted()函数内,可对当前传入的带有自定义指令的DOM元素应用原生的DOM操作。

自定义属性传值

        为了便于我们使用,可以使用一个同样的自定义指令,通过改变属性值,来快速操作DOM元素。

<body>
    <div id="app">
        <!---注意:传递的属性值必须是 字符串,也就是说,必须是双层引号--->
        <div v-color="'pink'">美羊羊</div>
        <div v-color="'red'">美羊羊</div>
        <div v-color="'black'">美羊羊</div>
    </div>
    <script>
        new Vue({
            el: '#app',
            directives: {
                color(el, binding) {
                    // el指令所在元素
                    // binding:与此指令绑定的相关值
                    el.style.color = binding.value 
                },
            },
        })
    </script>
</body>

四、ref索引

          ref:索引,代替DOM查找器,快速找到指定的DOM元素。 

ref:是将dom元素绑定到Vue身上的refs上,里面包含了这个元素所有的属性,后期我们也能通过这中方式进行组件间的传参

ref与自定义指令的差异:

     自定义指令是 自动 触发的;ref是 手动 触发的。

     自定义指令的方法需要专门写在 directives 中;ref的方法是需要写在 methods 中即可。

案例:通过点击按钮,输入框获取焦点

<body>
    <div id="app">
        <button @click='doFocus'>点我试试</button>
        <br>
        <!-- ref属性可以绑定一个变量到 当前元素上(变量名不能一样) -->
        <input type="text" ref="inp" />
        <br>
        <input type="text" ref="inp2" />
    </div>
    <script src="../vue.js"></script>
    <script>
        new Vue({
            el: '#app',
            methods: {
                doFocus() {
                    // 查看结果中的ref属性
                    console.log("获得焦点", this)
                        // 利用ref绑定的变量,存储在$refs属性中
                    this.$refs.inp.focus()
                }
            },
        })
    </script>
</body>