欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

vue学习篇--02内置指令 计算属性 侦听属性

程序员文章站 2022-05-17 10:10:44
...

18个指令

v-text

    html:
        <div id='app'>
            <!-- 显示结果一样 -->
            <div>{{message}}</div>
            <div v-text='message'></div>
            <!-- {{}}只能显示在文本当中,不能使用在属性当中 -->
            <div title='{{message}}'></div>
        </div>
    js:
        <script src='vue.js'></script>
        <script>
            var vm = new Vue({
                el:"#app",
                data:{
                    message:'hello'
                }
            })
        </script>

{{}}:差值表达式,只能显示在文本当中,不能使用在属性当中,因为{{}}相当于v-text的简写,
在v-text中,直接把{{}}当中innerText执行的而属性上是不能执行innerText的,应该使用v-bind。

v-html:

    html:
        <div id='app'>
            <!-- 插入一个dom结构 -->
            <div v-html="value"></div>
        </div>
    js:
        <script src='vue.js'></script>
        <script>
            var vm = new Vue({
                el:"#app",
                data:{
                    value:'<h1>hello</h2>'
                }
            })
        </script>

在2.0版本之前,v-html的简写为{{{}}},现在2.0的版本不支持
v-html在vue项目中很少使用,因为在页面中动态渲染dom结构很容易受到xss攻击,所以将简写方式去掉了

v-show:

    css:
        .box{width:100px;height:100px;background:red}
    html:
        <div id='app'>
            <div class='box'></div>
        </div>
    js:
        <script src='vue.js'></script>
        <script>
            var vm = new Vue({
                el:"#app",
                data:{
                    value:'<h1>hello</h2>'
                }
            })
        </script>

与v-if的区别是 渲染方式不同,
v-if通过控制标签是否存在文档中,来控制标签是否展示,为false时标签结构不存在文档中
v-show直接控制标签的行内样式style的display属性,为false时标签行内display属性为none

v-show有更高的初始化开销,因为v-show为false时,依然需要创建这个结构
v-if有更高的切换开销,因为v-if为false时需要销毁,为true时要创建

v-if:

    1. html:
        <div id='app'>
            <!-- 让h2和p都通过v-if控制显示隐藏 -->
            <h2 v-if='isExist'>hello</h2>
            <p v-if='isExist'>world</p>
            <!-- 一次控制多个,这人会多出一个不要的标签 -->
            <div v-if='isExist'>
                <h2>hello</h2>
                <p>world</p>
            </div>
            <!-- vue中有一个template组件可以当中一个空标签,最终不会被解析出来,不可以用v-show -->
            <template v-if='isExist'>
                <h2>hello</h2>
                <p>world</p>
            </template>
            <!-- v-else v-else-if必须跟随v-if使用,且中间不能有其他标签,else不是必须存在 -->
            <div v-if="flag === 'username'">
                用户名:<input text=type placeholder='请输入用户名' />
            </div>
            <div v-else-if="flag === 'tel'">
                手机号:<input text=type placeholder='请输入手机号码' />
            </div>
            <div v-else>
                邮箱:<input text=type placeholder='请输入邮箱' />
            </div>

        </div>
    2. js:
        <script src='vue.js'></script>
        <script>
            var vm = new Vue({
                el:"#app",
                data:{
                    isExist:true
                }
            })
        </script>

v-for: 可以遍历数组 对象 数字 字符串

  1. 遍历数组 对象 字符串 数字
      html:
         <!-- 遍历数组:vue变化时,数组变化,页面就发生变化,支持数组的操作方法有:
             push(数组最后添加值)  splice pop(数组后面删除)  shift(删除数组第一个值)  unshift(数组第一个插入值) 
             sort(排序)  reverse(数组反转) 
             重写整个数组:vm.arr = [...vm.arr,'test']
         -->
         <ul>
             <li v-for='(item,index) in arr'>
                 {{item--index}}
             </li>
         </ul>
         <!-- 遍历对象: 操作set 和 get 方法才可以让数据变化,操作dom结构跟着变化 
             Vue.set(vm.personInfo,'gender','男')  或者 vm.$set(vm.personInfo,'gender','男')
         -->
         <ul>
             <li v-for='(item,key,index) in personInfo'>
                 {{key}}--{{item}}--{{index}}
             </li>
         </ul>

     2. js:
         <script src='vue.js'></script>
         <script>
             var vm = new Vue({
                 el:'#app',
                 data:{
                     num:10,
                     str:"hello vue",
                     arr:['item1','item2','item3'],
                     personInfo:{
                         name:'ccc',
                         age:10,
                         height:170
                     }
                 }
             })
         </script>
  1. 同时含有v-for 和 v-if时:v-for优先级大于v-if
        1. html:
            <p v-for='item in list' v-if='item.gender == ""'>{{item.name}}</p>
        2. js:
            data:{
                ...,
                list:[
                    {"name":"ccc","gender":"男"},
                    {"name":"lll","gender":"男"},
                    {"name":"zzz","gender":"男"},
                    {"name":"clz","gender":"女"}
                ]
            }
  1. v-for和v-show同时使用:v-for优先级大于v-show
        1. html:
            <p v-for='item in list' v-show='item.gender === ""'>{{item.name}}</p>
  1. v-for需要和key属性一起使用,可以提高循环的性能:
    vue在渲染完成时,数据发生变化时需要重新渲染,则需要重新遍历循环一遍,
    如果重新遍历的标签已存在,则可以直接复用,不需要重新创建,根据key值来判断标签是否已存在。所以要求key值唯一性
           1. html:
               <!-- 设置key值为index,需要把index当中一个变量来解析,需要使用v-bind来解析,而不是当做index字符串
                   key值唯一性,不建议使用下标,如果数组进行反转,或发生其他变化,原来的下标所对应的值已经发生变化
                   一般使用数据id
               -->
               <ul>
                   <li v-for='(item,index) in arr' v-bind:key='index'>{{item}}</li>
               </ul>

v-bind: 解析属性:title src href type alt placeholder class style

用v-bind绑定的属性值与行内属性值优先级一样,哪个在后面就执行哪个, 简写是 冒号:
  1. 解析属性:title src href type alt placeholder
        1. html
            <div v-bind:title='message' title='啦啦啦'>百度<div>
            <div v-bind:src='imgPath' alt=''>图标</div>
            <a v-bind:href='link'>百度</a>
        2. js:
            <script src='vue.js'></script>
            <script>
                var vm = new Vue({
                    el:'#app',
                    data:{
                        message:'百度',
                        imgPath:'https://www.baidu.com/img/baidu_jgylogo3.gif',
                        link:'http://www.bindu.com'
                    }
                })
            </script>
  1. v-bind作用在class上
       1. css:
           .box{width:100px;height:100px;margin: 10px;background:cyan;}
           .red{background:red}
           .yellow{background:yellow}
           .green{background:green}
       2. html:
           <!-- class 字符串的表示方式 -->
           <div :class="'box' + 'bg'"></div>
           <div class='box' :class='bg'></div>
           <!-- class 数组的表示方式 -->
           <div class='box' :class='bgArr'></div>
           <!-- class 对象的表示方式 -->
           <div class='box' :class='bgObj'></div>
       3. js:
           <script src='vue.js'></script>
           <script>
               var vm = new Vue({
                   el:'#app',
                   data:{
                       bg:'red',
                       bgArr:['red','yellow','green'],
                       bgObj:{
                           red:true,
                           yellow:false,
                           green:false
                       }
                   }
               })
           </script>
  1. v-bind作用域style
       1. html
           <div class='box' style='width:100px;height:100px;backgrond:cyan'></div>
           <!-- 字符串方式 -->
           <div class='box' :style='styleStr'></div>
           <!-- 对象方式 -->
           <div :style='styleObj'></div>
           <!-- 数组方式 -->
           <div :style='[styleObj,{background:'red'}]'></div>

       2. js:
           <script src='vue.js'></script>
           <script>
               var vm = new Vue({
                   el:'#app',
                   data:{
                       styleStr:'width:100px;height:100px;backgrond:cyan',
                       styleObj:{
                           width:"100px",
                           height:"100px",
                           backgroung:'cyan',
                           'margin-top':'10px',
                           backgroundImage:"url(https://www.baidu.com/img/baidu_jgylogo3.gif)"
                       }
                   }
               })
           </script>

v-pre: 不需要表达式,不解析当前dom及其内部结构内所有的vue指令

    1. html:
        <div v-pre>
            <!-- 跳过这段dom,内部都不解析 -->
            <h3>在vue中,想显示message的值,应该写成{{message}}</h3>
            <ul>
                <li v-for="(s, index) in message" :key="index">
                    {{s}}
                </li>
            </ul>
            <!-- <button @click="btnAction">按钮</button> -->
        </div>
    2. js:
        <script src="vue.js"></script>
        <script>
        var vm = new Vue({
            el: '#app',
            data: {
                message: 'hello world'
            },
            methods: {
                btnAction: function(){
                    console.log('点击了');
                }
            }
        })
        </script>

v-cloak: 不需要表达式

    v-text和{{}}的区别是:在vue还未被加载时,{{}}可以被看见,而v-text的结构是看不见的
    使用v-cloak就可以不让{{}}被看见
    这个指令保持在元素上直到关联实例结束编译。和 CSS 规则如 [v-cloak] { display: none } 一起用时,这个指令可以隐藏未编译的 Mustache 标签直到实例准备完毕。
    1. css:
        [v-cloak]{display:none}
    2. html:
        <div id="app" v-cloak>
            <div >{{message}}</div>
            <div >{{message}}</div>
            <div >{{message}}</div>
            <div >{{message}}</div>
            <div v-text="message"></div>
        </div>
    3. js:
        <script src="vue.js"></script>
        <script>
        var vm = new Vue({
            el: '#app',
            data: {
                message: 'hello world'
            }
        })
        </script>

v-once: 不需要表达式,只解析一次

    1. html:
        <div v-once>{{message}}</div>
    2. js:
        <script src="vue.js"></script>
        <script>
        var vm = new Vue({
            el: '#app',
            data: {
                message: 'hello world'
            }
        })
        </script>

计算属性:

    1. html:
        <p>a:<input type='number' v-model.number='a' /></p>
        <p>b:<input type='number' v-model.number='b' /></p>
        <p>求和:{{a+b}}</p>
        <!-- 方法 -->
        <p>求和:{{count()}}</p>
        <!-- 计算属性 -->
        <p>求和:{{count}}</p>
    2. js:
        <script src="vue.js"></script>
        <script>
        var vm = new Vue({
            el: '#app',
            data: {
                a: 1,
                b: 2
            },
            computed:{
                count:function(){
                    return this.a + this.b
                }
            },
            methods:{
                count:function(){
                    return this.a + this.b
                }
            }
        })
        </script>

computed和methods的区别:
computed会根据依赖的其他属性值将结果会缓存,提供下一次访问调用,下一次直接访问缓存结果,
如果依赖的属性发送变化,需要重新计算,只计算一次,其他访问就使用缓存
methods方法则是调用多少次就执行多少次

计算属性的set和get方法:在set方法可以接收到对应方法的赋值

    1. html:
        <p>{{fullname}}</p>
    2. js:
        <script src="vue.js"></script>
        <script>
        var vm = new Vue({
            el: '#app',
            data: {
                firstname:'ccc',
                lastname:'lll'
            },
            computed: {
                 fullname:function(){
                    return this.firstname + this.lastname
                } 
                /* 完整写法,fullname重新赋值之后set方法会被调用 */
                fullname:{
                    get:function(){
                        return this.firstname +' '+ this.lastname
                    },
                    set:function(value){
                        /* 可以将firstname和Lastname重新赋值 */
                        var arr = value.split(' ');
                        this.firstname = arr[0]
                        this.lastname = arr[arr.length-1]
                    }
                }
            }
        })
        </script>

侦听器:侦听器可以获取更新后的值和更新前的值

    1. html:
        <p>{{fullname}}</p>
    2. js:
        <script src="vue.js"></script>
        <script>
        var vm = new Vue({
            el: '#app',
            data: {
                firstname:'ccc',
                lastname:'lll'
            },
            watch: {
                firstname:function(newVal,oldVal){
                    console.log('firstname变化了')
                    console.log('newVal:',newVal,'oldVal:',oldVal)
                },
                lastname:function(newVal,oldVal){
                    console.log('lastname变化了')
                    console.log('newVal:',newVal,'oldVal',oldVal)
                }
            }
        })
        </script>

侦听器侦听对象

只能侦听到引用是否发生变化,对内部的值的变化侦听不到
可以配置属性deep为true来侦听内部值的变化。

    1. html:
        <p>{{obj}}</p>
    2. js:
        <script src="vue.js"></script>
        <script>
            var vm = new Vue({
                el: '#app',
                data: {
                    obj:{
                        name:'ccc',
                        age:11
                    },
                    list:[1,2,3]
                },
                watch: {
                    /* 侦听对象只能侦听到引用是否发生变化,对内部的值的变化侦听不到 */
                    /* obj:function(newVal,oldVal){
                        console.log('obj变化了')
                        console.log('newval:',newVal,'old:',oldVal)
                    }, 
                    */
                    /* 侦听对象内部值的变化
                        如果是内部的值发生变化,则newVal oldVal都是新值
                        如果是引用变化,则newVal为新值,oldVal为旧值
                    */
                    obj:{
                        handler:function(){
                            console.log('obj变化了')
                            console.log('newval:',newVal,'old:',oldVal)
                        },
                        /* 监听对象内部值的变化 */
                        deep:true,
                        /* 一加载就执行 */
                        immediate:true
                    },
                    /* 只监听obj的其中属性,不需要配置监听方式deep */
                    "obj.name":function(newval,oldval){
                        console.log('obj.name变化')
                        console.log(newval,oldval)
                    },
                    /* 数组可以直接侦听内部变化和引用变化,只不过不用配置deep:true 
                        如果是内部的值发生变化,则newVal oldVal都是新值
                        如果是引用变化,则newVal为新值,oldVal为旧值
                    */
                    list:function(newval,oldval){
                        console.log('list变化了')
                        console.log(newval,oldval)
                    }
                    /* 多个侦听 */
                    message:[
                        function handler1(){
                            console.log('message handler1触发了')
                        },
                        function handler2(){
                            console.log('message handler2触发了')
                        }
                    ]
                }
            })
            /* 对vm实例上的属性进行监听
                参数1:需要监听的属性 key路径
                参数2:监听回调函数
                参数3:监听方式的配置
                返回值:一个函数,执行可以移除监听 
            */
            function addEventListenerVm(){
                var unwatch = vm.$watch('obj.name', function(newVal, oldVal){
                        console.log('obj变化了');
                        console.log('newVal:', newVal, 'oldVal:', oldVal);
                    },{
                        deep:true
                    });
            /* 移除监听 */
                // unwatch();
            }
        </script>

使用:

如果属性变化,导致其他数据也发生变化,那么这个数据就放在计算属性中进行计算
如果属性发生变化,需要进行事件操作,刷新dom,操作dom,请求数据等则用侦听器,
		监听属性的变化,从而对应的操作。