Vuejs提高篇(二)

简介: Vuejs提高篇(二)

Vue方法、计算属性及监听器


在vue中处理复杂的逻辑的时候,我们经常使用计算属性、方法及监听器。


methods(方法):它们是挂载在Vue对象上的函数,通常用于做事件处理函数,或自己封装的自定义函数。

computed(计算属性):在Vue中,我们可以定义一个计算属性,这个计算属性的值,可以依赖于某个data中的数据。或者说:计算属性是对数据的再加工处理。

watch(监听器):如果我们想要在数据发生改变时做一些业务处理,或者响应某个特定的变化,我们就可以通过监听器,监听数据的变化,从而做出相应的反应。


methods 方法


在使用vue的时候,可能会用到很多的方法,它们可以将功能连接到事件的指令,甚至只是创建一个小的逻辑就像其他函数一样被重用。接下来我们用方法实现上面的字符串反转。


样例代码:


<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title></title>
  </head>
  <body>
    <div id="app" >
        <p>原数据: {{msg}} </p>
        <p>新数据: {{reversedMsg()}} </p>
    </div>
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <script>
        let vm = new Vue({
            el: '#app',
            data: {
                msg:'hello world!'
            },
            methods:{
                reversedMsg(){
                    return this.msg.split('').reverse().join('');
                }
            }
        });
    </script>
  </body>
</html>

效果截图:

1.png


computed 计算属性


计算属性是根据依赖关系进行缓存的计算,并且只在需要的时候进行更新。


样例代码:


<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title></title>
  </head>
  <body>
    <div id="app">
      <p>computed:</p>
      <p>原数据: {{msg}} </p>
      <p>新数据: {{reversedMsg}} </p>
    </div>
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <script>
      let vm = new Vue({
        el: '#app',
        data: {
          msg: 'Keafmd!'
        },
        computed: {
          reversedMsg() {
            return this.msg.split('').reverse().join('');
          }
        }
      });
    </script>
  </body>
</html>

效果截图:

1.png


虽然使用computed和methods方法来实现反转,两种方法得到的结果是相同的,但本质是不一样的。

计算属性是基于它们的依赖进行缓存的。计算属性只有在它的相关依赖发生改变的时候才会重新求值,这就意味着只要message还没有发生改变,多次访问reversedMessage计算属性立即返回的是之前计算的结果,而不会再次执行计算函数。

而对于methods方法,只要发生重新渲染,methods调用总会执行该函数。

如果某个computed需要的遍历一个极大的数组和做大量的计算,可以减小性能开销,如果不希望有缓存,则用methods。


一个案例:根据商品数量修改总价


样例代码:


<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title></title>
  </head>
  <body>
    <div id="app">
        <table width="100%" style="text-align: center;">
            <tr>
                <th>商品编号</th>
                <th>商品名称</th>
                <th>商品单价</th>
                <th>商品数量</th>
                <th>合计</th>
            </tr>
            <tr>
                <td>1</td>
                <td>小米10</td>
                <td>{{price}}</td>
                <td>
                    <button @click="subtract">-</button>
            {{quantity}}
                    <button @click="add">+</button>
                </td>
                <td>{{totalPrice}}</td>
            </tr>
        </table>
    </div>
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <script>
        let vm = new Vue({
            el: '#app',
            data: {
                price:1599,
                quantity:1
            },
            computed:{
                totalPrice(){
                    return this.price*this.quantity;
                }
            },
            methods:{
                add(){
                    this.quantity++;
                },
                subtract(){
                    this.quantity--;
                }
            }
        });
    </script>
  </body>
</html>

效果截图:

1.png


此时购物数量可以低于零。


watch 监听器


watch能够监听数据的改变。监听之后会调用一个回调函数。 此回调函数的参数有两个:


更新后的值(新值)

更新前的值(旧值)


监听基本数据类型


下面使用watch来监听商品数量的变化。如果商品数量小于1,就重置成上一个值。

样例代码:


<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title></title>
  </head>
  <body>
    <div id="app">
        <table width="100%" style="text-align: center;">
            <tr>
                <th>商品编号</th>
                <th>商品名称</th>
                <th>商品单价</th>
                <th>商品数量</th>
                <th>合计</th>
            </tr>
            <tr>
                <td>1</td>
                <td>小米10</td>
                <td>{{price}}</td>
                <td>
                    <button @click="subtract">-</button>
                  {{quantity}}
                    <button @click="add">+</button>
                </td>
                <td>{{totalPrice}}</td>
            </tr>
        </table>
    </div>
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <script>
        let vm = new Vue({
            el: '#app',
            data: {
                price: 2999,
                quantity: 1
            },
            computed: {
                totalPrice() {
                    return this.price * this.quantity;
                }
            },
            methods: {
                add() {
                    this.quantity++;
                },
                subtract() {
                    this.quantity--;
                }
            },
            watch:{
                quantity(newVal,oldVal){
                    console.log(newVal,oldVal);
                    this.quantity = newVal<=0?oldVal:newVal
                }
            }
        });
    </script>
  </body>
</html>

效果截图:

1.png


此时购物数量不能为负数。


深度监听


在上面的例子中,监听的简单的数据类型,数据改变很容易观察,但是当需要监听的数据变为对象类型的时候,上面的监听方法就失效了,因为上面的简单数据类型属于浅度监听,对应的对象类型就需要用到深度监听,只需要在上面的基础上加上deep: true就可以了。


样例代码:


<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8" />
        <title></title>
        <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    </head>
    <body>
        <div id="app">
            <table width="100%" style="text-align: center;">
                <tr>
                    <th>商品编号</th>
                    <th>商品名称</th>
                    <th>商品单价</th>
                    <th>商品数量</th>
                    <th>合计</th>
                </tr>
                <tr>
                    <td>1</td>
                    <td>小米10</td>
                    <td>{{goods.price}}</td>
                    <td>
                        <button @click="subtract">-</button>
              {{goods.quantity}}
                        <button @click="add">+</button>
                    </td>
          <td>{{totalPrice}}</td>
                </tr>
            </table>
        </div>
        <script>
            let vm = new Vue({
                el: '#app',
                data: {
                    price: 2999,
                    quantity: 1,
                    goods: {
                        price: 2999,
                        quantity: 1
                    }
                },
                computed: {
                    totalPrice() {
                        return this.goods.price * this.goods.quantity;
                    },
                    deepQuantity(){
                        return this.goods.quantity;
                    }
                },
                methods: {
                    add() {
                        this.goods.quantity++;
                    },
                    subtract() {
                        this.goods.quantity--;
                    }
                },
                watch: {
                    quantity(newVal, oldVal) {
                        // console.log(newVal, oldVal);
                        this.goods.quantity = newVal <= 0 ? 0 : newVal
                    },
                    goods: {
                        deep: true,
                        handler:(newVal, oldVal)=> {
                            //console.log(newVal, oldVal);
                        }
                    },
                    deepQuantity(newVal, oldVal){
                        console.log("侦听器=",newVal, oldVal);
            if(newVal<0)
            alert("购物数量不能为负数!")
            this.goods.quantity = newVal <= 0 ? 0 : newVal
                    }
                }
            });
        </script>
    </body>
</html>

效果截图:

1.png


Vue操作数组时的注意事项


由于 JavaScript 语言本身的限制,当我们对数组进行某些操作时,Vue 可能不会检测到数组元素的变化,那么进而视图也不会响应。比如:


样例代码:

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title></title>
  </head>
  <body>
    <div id="app">
        <p v-for="(item,index) in userArr">
            {{item.userId}}--{{item.userName}}--{{item.userSex}}
        </p>
        <button @click="clear">清空</button>
    </div>
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <script>
        let vm = new Vue({
            el: '#app',
            data: {
                userArr: [{
                    userId: 1,
                    userName: '张三',
                    userSex: '男'
                }, {
                    userId: 2,
                    userName: '李四',
                    userSex: '女'
                }, {
                    userId: 3,
                    userName: '王五',
                    userSex: '男'
                }]
            },
            methods: {
                clear() {
                    this.userArr.length = 0;
                    console.log(this.userArr.length);    //0
                }
            }
        });
    </script>
  </body>
</html>

效果截图:

1.png


上面实例中,将数组的长度设置为0后,数组确实被清空了。但是Vue却不能检测到数组的变化,所以页面视图也不会响应。


为了解决这个问题,Vue给我们提供了如下解决方案: Vue 提供一组观察数组的变异方法(就是这些方法会改变原始数组,所以才会被Vue检测到),使用它们就可以触发视图更新。 这些方法有7个:push()、pop()、shift()、unshift()、splice()、sort()、reverse()。


样例代码:


<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title></title>
  </head>
  <body>
    <div id="app">
        <p v-for="(item,index) in userArr">
            {{item.userId}}--{{item.userName}}--{{item.userSex}}
        </p>
        <button @click="clear">清空</button>
    </div>
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <script>
        let vm = new Vue({
            el: '#app',
            data: {
                userArr: [{
                    userId: 1,
                    userName: '张三',
                    userSex: '男'
                }, {
                    userId: 2,
                    userName: '李四',
                    userSex: '女'
                }, {
                    userId: 3,
                    userName: '王五',
                    userSex: '男'
                }]
            },
            methods: {
          clear() {
            //使用Vue中提供的变异方法
            this.userArr.splice(0,this.userArr.length);
          }
        }
        });
    </script>
  </body>
</html>

效果动图:

1.gif


这样就可以检测到数组的变化,同时页面视图会响应。


Vue的表单绑定


v-bind实现了数据的单向绑定,将vue实例中的数据同元素属性值进行绑定,接下来看一下vue中的数据双向绑定v-model。


v-mode实现表单绑定


样例代码:


<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title></title>
  </head>
  <body>
    <div id="app">
        <h3>注册</h3>
        <form>
            用户名:<input type="text" v-model="myForm.username"/><br>
            密码:<input type="password" v-model="myForm.password" /><br>
            确认密码:<input type="password" v-model="myForm.beginpassword" /><br>
            性别:<input type="radio" v-model="myForm.sex" value="0" />男
                 <input type="radio" v-model="myForm.sex" value="1" />女<br>
            爱好:<input type="checkbox" v-model="myForm.like" value="0" />读书
                 <input type="checkbox" v-model="myForm.like" value="1" />体育
                 <input type="checkbox" v-model="myForm.like" value="2" />旅游<br>
            国籍:<select v-model="myForm.nationality">
                    <option value="0">中国</option>
                    <option value="1">美国</option>
                    <option value="2">英国</option>
                 </select><br>
            个人简介:<textarea v-model="myForm.brief" rows="5" cols="30"></textarea><br>
                 <input type="button" value="提交" @click="handler" />
        </form>
    </div>
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <script>
        let vm = new Vue({
            el: '#app',
            data: {
                myForm: {
                    username: '',
                    password: '',
                    beginpassword: '',
                    sex: 0,
                    like: [0, 1, 2],
                    nationality: 0,
                    brief: '',
                    level: 0
                }
            },
            methods: {
                handler: function() {
                    console.log(this.myForm.username);
                    console.log(this.myForm.password);
                    console.log(this.myForm.beginpassword);
                    console.log(this.myForm.sex);
                    console.log(this.myForm.like);
                    console.log(this.myForm.nationality);
                    console.log(this.myForm.brief);
                }
            }
        });
    </script>
  </body>
</html>

效果截图:

1.png


v-model修饰符


v-model中还可以使用一些修饰符来实现某些功能:


v-model.lazy 只有在input输入框发生一个blur时才触发,也就是延迟同步到失去焦点时。

v-model.trim 将用户输入的前后的空格去掉。

v-model.number 将用户输入的字符串转换成number。

样例代码:


<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title></title>
  </head>
  <body>
    <div id="app">
        <!-- 输入数据会延迟到失去焦点时才绑定 -->
        输入数据1:<input type="text" v-model.lazy="lazyStr" /><br>
        <!-- 输入数据会自动转换为number,所以可以直接进行运算 -->
        输入数据2:<input type="text" v-model.number="numberStr" /><br>
        <!-- 输入数据会自动去除前后空格 -->
        输入数据3:<input type="text" v-model.trim="trimStr" /><br>
      <button @click="handler" >完成</button>
    </div>
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <script>
        let vm = new Vue({
            el: '#app',
            data: {
                lazyStr: '',
                numberStr:'',
                trimStr:''
            },
        methods: {
            handler: function() {
                console.log(this.lazyStr);
                console.log(this.numberStr);
                console.log(this.trimStr);
            }
        }
        });
    </script>
  </body>
</html>

输入数据123 456,前后都有空格,中间也有空格。


效果动图:

1.gif


过滤器


过滤器是对即将显示的数据做进一步的筛选处理,然后进行显示,值得注意的是过滤器并没有改变原来的数据,只是在原数据的基础上产生新的数据。

过滤器分全局过滤器和本地过滤器(局部过滤器)。


全局过滤器


下面定义一个全局过滤器,用于在数据前加上大写的VUE。需要注意的是,全局过滤器定义必须始终位于Vue实例之上,否则会报错。


样例代码:

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title></title>
  </head>
  <body>
    <div id="app">
        {{ message | toAdd  }}
    </div>
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <script>
        Vue.filter("toAdd", function(value) {
            return 'VUE' + value
        })
        var demo = new Vue({
            el: '#app',
            data: {
                message: '过滤器',
            }
        })
    </script>
  </body>
</html>

效果截图:

1.png


注意:


Vue.filter() 后有两个参数:过滤器名,过滤器处理函数。

过滤器处理函数也有一个参数:要过滤的数据。


本地过滤器


本地过滤器存储在vue组件中,作为filters属性中的函数,我们可以注册多个过滤器存储在其中。


样例代码:


<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title></title>
  </head>
  <body>
    <div id="app">
        <p> {{ message | Reverse }} </p>
        <p> {{ message | Length }} </p>
    </div>
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <script>
        var demo = new Vue({
            el: '#app',
            data: {
                message: '过滤器',
            },
            filters: {
                Reverse: function(value) {
                    if (!value){
                        return '';
                    } 
                    return value.toString().split('').reverse().join('');
                },
                Length: function(value) {
                    return value.length;
                },
            },
        })
    </script>
  </body>
</html>

效果截图:

1.png


过滤器传参


过滤器也是可以传递参数的。


样例代码:

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title></title>
  </head>
  <body>
    <div id="app">
        {{ msg1 | toDou (1,2) }}
        {{ msg2 | toDou (10,20) }}
    </div>
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <script>
        Vue.filter('toDou', function(value, param1, param2) {
            if (param2 < 10) {
                return value + param1;
            } else {
                return value + param2;
            }
        });
        new Vue({
            el: '#app',
            data: {
                msg1: 9,
                msg2: 12,
            }
        });
    </script>
  </body>
</html>

效果截图:

1.png


注意:过滤器处理函数的第一个参数,仍然是要过滤的数据。从第二个参数开始,才是过滤器本身要传递的参数。


串联过滤器


多个过滤器可以串联使用。


样例代码:

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title></title>
  </head>
  <body>
    <div id="app">
        {{ money | prefix | suffix }}
    </div>
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <script>
        Vue.filter("prefix", function(value) {
            return '¥' + value
        })
        Vue.filter("suffix", function(value) {
            return  value + '元'
        })
        var demo = new Vue({
            el: '#app',
            data: {
                money:10
            }
        })
    </script>
  </body>
</html>

效果截图:

1.png

相关文章
|
机器学习/深度学习 网络架构 计算机视觉
YOLOv5改进 | 检测头篇 | 利用DBB重参数化模块魔改检测头实现暴力涨点 (附代码 + 详细修改教程)
YOLOv5改进 | 检测头篇 | 利用DBB重参数化模块魔改检测头实现暴力涨点 (附代码 + 详细修改教程)
806 3
|
SQL 数据库
SQL UNION 操作符
SQL UNION 操作符
224 9
|
安全 Java API
Java 17新特性让你的代码起飞!
【10月更文挑战第4天】自Java 8发布以来,Java语言经历了多次重大更新,每一次都引入了令人兴奋的新特性,极大地提升了开发效率和代码质量。本文将带你从Java 8一路走到Java 17,探索那些能让你的代码起飞的关键特性。
400 1
|
人工智能 自然语言处理 搜索推荐
AI与心理健康:情感支持的新形式
【10月更文挑战第31天】在快节奏的现代生活中,心理健康问题日益突出。AI技术的发展为情感支持提供了新形式,包括心理评估、情感监测、危机干预和个性化咨询。本文探讨了AI在心理健康领域的应用及其对个人和社会的深远影响。
1487 0
|
SQL 自然语言处理 测试技术
NL2SQL进阶系列(4):ConvAI、DIN-SQL等16个业界开源应用实践详解[Text2SQL]
NL2SQL进阶系列(4):ConvAI、DIN-SQL等16个业界开源应用实践详解[Text2SQL]
NL2SQL进阶系列(4):ConvAI、DIN-SQL等16个业界开源应用实践详解[Text2SQL]
|
自然语言处理 Android开发 Windows
文本----搜狗如何使用日语输入法,日本本土使用人数最多输入法Simeji Japanese Input + Emoji,Windows10如何添加日语输入法,Windows + 空格选择语言,谷歌公
文本----搜狗如何使用日语输入法,日本本土使用人数最多输入法Simeji Japanese Input + Emoji,Windows10如何添加日语输入法,Windows + 空格选择语言,谷歌公
|
数据采集 SQL 数据可视化
数据分析的要求
数据分析的要求
403 3
|
分布式计算 Java 大数据
Flink - NoSuchMethodError: com.twitter.chill.java.Java8ClosureRegistrar.areOnJava8()Z
使用 Flink 1.13.1 + scala 2.11.12 的组合进行 Flink 本地测试是,报错.NoSuchMethodError: com.twitter.chill.java.Java8ClosureRegistrar.areOnJava8()Z,经过前面多次的 noSuchMethod 的折磨,现在已经轻车熟路,直接开始排查。...............
963 0
Flink - NoSuchMethodError: com.twitter.chill.java.Java8ClosureRegistrar.areOnJava8()Z
|
机器学习/深度学习 自然语言处理 算法
分词算法在自然语言处理中的基本原理与应用场景
分词算法在自然语言处理中的基本原理与应用场景
|
存储 运维 Kubernetes
CNStack 虚拟化服务:实现虚拟机和容器资源的共池管理
CNStack 虚拟化服务:实现虚拟机和容器资源的共池管理
CNStack 虚拟化服务:实现虚拟机和容器资源的共池管理