2.3Java全栈开发前端+后端(全栈工程师进阶之路)-前端框架VUE3-基础-Vue进阶

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

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

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

  2. computed:计算属性:在Vue中,我们可以定义一个计算属性,这个计算属性的值,可以依赖于某个data中

的数据。或者说:计算属性是对数据的再加工处理。

  1. watch:监听器:如果我们想要在数据发生改变时做一些业务处理,或者响应某个特定的变化,我们就可以通

过监听器,监听数据的变化,从而做出相应的反应。

computed 计算属性

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

<div id="app">
    原数据:{{msg}} <br>
    新数据:{{reversedMsg}}
</div>

<script src="../js/vue3.js"></script>
<script>
    Vue.createApp({
        data() {
            return {
                msg: 'hello world!'
            }
        },
        computed:{
            reversedMsg(){
            // 反转操作
                return this.msg.split('').reverse().join('');
            }
        }
    }).mount('#app');
</script>

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

<div id="app">
    商品名称:小米手机; 数量:
    <button @click="sub">-</button>{{quantity}}<button @click="add">+</button>
    <br>
    总价:{{total}}
</div>

<script src="../js/vue3.js"></script>
<script>
    Vue.createApp({
        data() {
            return {
                quantity: 1
            }
        },
        computed:{
            total(){
                return this.quantity*100;
            }
        },
        methods:{
            add(){
                this.quantity++;
            },
            sub(){
                this.quantity--;
            }
        }
    }).mount('#app');
</script>

另一个案例:对数据进行过滤处理。

<div id="app">
    {{newMoney}}
</div>

<script src="../js/vue3.js"></script>
<script>
    Vue.createApp({
        data() {
            return {
                money: 1000
            }
        },
        computed:{
            newMoney(){
                return this.money + '¥';
            }
        },
    }).mount('#app');
</script>

methods 方法

在使用vue的时候,可能会用到很多的方法,它们可以将功能连接到事件的指令,甚至只是创建一个小的逻辑就像

其他函数一样被重用。接下来我们用方法实现上面的字符串反转。

<div id="app">
    {{msg}} <br>
    {{reversedMsg()}}
</div>

<script src="../js/vue3.js"></script>
<script>
    Vue.createApp({
        data() {
            return {
                msg: 'hello world!'
            }
        },
        methods:{
            reversedMsg(){
                return this.msg.split('').reverse().join('');
            }
        }
    }).mount('#app');
</script>

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

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

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

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

watch 监听器

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

  1. 更新后的值(新值)

  2. 更新前的值(旧值)

监听基本数据类型

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

<div id="app">
    商品名称:小米手机; 数量:
    <button @click="sub">-</button>{{quantity}}<button @click="add">+</button>
    <br>
    总价:{{total}}
</div>

<script src="../js/vue3.js"></script>
<script>
    Vue.createApp({
        data() {
            return {
                quantity: 1
            }
        },
        computed:{
            total(){
                return this.quantity*100;
            }
        },
        methods:{
            add(){
                this.quantity++;
            },
            sub(){
                this.quantity--;
            }
        },
        watch:{
            quantity(newVal,oldVal){
                this.quantity = newVal<=0?oldVal:newVal;
            }
        }
    }).mount('#app');
</script>

深度监听

在上面的例子中,监听的简单的数据类型,数据改变很容易观察,但是当需要监听的数据变为对象类型的时候,上

面的监听方法就失效了,因为上面的简单数据类型属于浅度监听,对应的对象类型就需要用到深度监听,只需要在

上面的基础上加上deep: true就可以了。

<div id="app">
    商品名称:{{goods.name}}; 数量:
    <button @click="sub">-</button>{{goods.quantity}}<button @click="add">+</button>
    <br>
    总价:{{total}}
</div>

<script src="../js/vue3.js"></script>
<script>
    Vue.createApp({
        data() {
            return {
                goods:{
                    name: '小米手机',
                    quantity: 1
                }
            }
        },
        computed:{
            total(){
                return this.goods.quantity*100;
            }
        },
        methods:{
            add(){
                this.goods.quantity++;
            },
            sub(){
                this.goods.quantity--;
            }
        },
        watch:{
            goods:{
                handler(newVal,oldVal){
                     /** 
                    * 注意:虽然使用深度监听,可以监听到对象的改变。 
                    * 但是,由于是对象类型,所以newVal与oldVal都指向同一个对象。 
                    * 所以,newVal与oldVal中的quantity都是改变后的新值。 
                    */ 
                    console.log(newVal,oldVal)
                    this.goods.quantity = newVal.quantity<=0?oldVal.quantity:newVal.quantity;
                },
                deep: true
            }
        }
    }).mount('#app');
</script>

上面代码中,由于监听的是对象类型,所以newVal与oldVal都指向同一个对象。

所以,在深度监听对象时,是不能正确获取更新前的对象和更新后的对象的。

解决方案:利用计算属性将对象变成字符串后再监听。

<div id="app">
    商品名称:{{goods.name}}; 数量:
    <button @click="sub">-</button>{{goods.quantity}}<button @click="add">+</button>
    <br>
    总价:{{total}}
</div>
<script src="../js/vue3.js"></script>
<script>
    Vue.createApp({
        data() {
            return {
                goods:{
                    name: '小米手机',
                    quantity: 1
                }
            }
        },
        computed:{
            total(){
                return this.goods.quantity*100;
            },
            goodsStr(){
                return JSON.stringify(this.goods);
            }
        },
        methods:{
            add(){
                this.goods.quantity++;
            },
            sub(){
                this.goods.quantity--;
            }
        },
        watch:{
            goodsStr(newVal,oldVal){
                let newGoods = JSON.parse(newVal);
                let oldGoods = JSON.parse(oldVal);
                this.goods.quantity = newGoods.quantity<=0?oldGoods.quantity:newGoods.quantity;
            }
        }
    }).mount('#app');
</script>

Vue的表单绑定

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

v-mode实现表单绑定

<div id="app">
    <h3>注册</h3>
    <form>
        用户名:<input type="text" v-model="user.userName"><br>
        密码:<input type="password" v-model="user.password"><br>
        确认密码:<input type="password" v-model="user.beginPass"><br>
            <!-- 单选框 -->
        性别:<input type="radio" v-model="user.sex" value="0">男 
              <input type="radio" v-model="user.sex" value="1">女<br>
              <!-- 复选框 -->
        爱好:<input type="checkbox" v-model="user.like" value="0">读书
              <input type="checkbox" v-model="user.like" value="1">体育
              <input type="checkbox" v-model="user.like" value="2">旅游<br>
              <!-- 下拉选 -->
        国籍:<select v-model="user.nationality">
                  <option value="0">中国</option>
                  <option value="1">美国</option>
                  <option value="2">俄罗斯</option>
              </select><br>
           <!--   文本域 -->
        个人简介:<textarea cols="30" rows="5" v-model="user.brief"></textarea> <br>
        <!--  <button @click="reg">注册</button>-->
        <input type="button" @click="reg" value="注册">
    </form>
</div>
<script src="../js/vue3.js"></script>
<script>
    Vue.createApp({
        data() {
            return {
                user:{
                    userName:'',
                    password:'',
                    beginPass:'',
                    sex: 0,
                    like: [],
                    nationality: 0,
                    brief: ''
                }
            }
        },
        methods:{
            reg(){
                console.log(this.user);
            }
        }
    }).mount('#app');
</script>

v-model修饰符

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

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

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

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

<div id="app">
    {{num}} <input type="text" v-model.lazy="num"><br>
    <input type="text" v-model.trim="msg"><button @click="add">点击</button><br>
    {{num+1}} <input type="text" v-model.number="num"><br>
</div>
<script src="../js/vue3.js"></script>
<script>
    Vue.createApp({
        data() {
            return {
                num: '10',
                msg: 'hello'
            }
        },
        methods:{
            add(){
                console.log(this.msg)
            }
        }
    }).mount('#app');
</script>

上一篇:sklearn和torch计算的r2 score不一样


下一篇:B+树详解与实现-二、B+树的定义