第三节:Vue3向下兼容2(v-for、数组方法、v-model、计算属性、监听器)

摘要:
2、 V-model1.基本用法和原理V-model指令可以在表单输入、文本区域和选择元素上创建双向数据绑定;它将根据控件类型自动选择正确的方法来更新元素;尽管有些神奇,但v-model本质上是一种语法糖。它负责监听用户输入事件以更新数据,并在某些极端情况下执行一些特殊处理相当于˂!

一. 基本指令

 1. v-for

数据准备

    data() {
                    return {
                        userInfo: { name: 'ypf', age: 18, school: '北大' },
                        movies: ["星际穿越", "盗梦空间", "大话西游", "教父", ],
                        userList: [
                            { name: 'ypf1', age: 18, school: '北大1' },
                            { name: 'ypf2', age: 19, school: '北大2' },
                            { name: 'ypf3', age: 20, school: '北大3' }
                        ]
                    }
             }

(1). 遍历对象

格式:

第三节:Vue3向下兼容2(v-for、数组方法、v-model、计算属性、监听器)第1张

            <h4>1.遍历对象</h4>
            <ul>
                <li v-for="(value,key,index) in userInfo" :key='index'>
                    {{index}}-{{key}}--{{value}}
                </li>
            </ul>

(2). 遍历数字

格式: item in 数字

            <h4>2.遍历数字</h4>
            <ul>
                <li v-for="value in 5">
                    {{value}}
                </li>
            </ul>

(3). 遍历数组【重点】

格式:item in 数组

           (item, index) in 数组

A. 普通数组

            <h5>3.1 普通数组</h5>
            <ul>
                <li v-for="(item,index) in movies" :key='index'>{{index}}-{{item}}</li>
            </ul>

B. 数组对象

            <h5>3.2 数组对象</h5>
            <ul>
                <li v-for="(item,index) in userList" :key='index'>
                    {{index}}-{{item.name}}-{{item.age}}-{{item.school}}
                </li>
            </ul>

补充:

  我们发现,每个v-for,我们都赋值了一个key属性,key属性里的内容建议用唯一值,这里涉及到diff算法,提高效率,后面章节重点剖析。

2. 数组方法

(1).变异方法:

  背景:在 Vue 中,直接修改对象属性的值无法触发响应式。当你直接修改了对象属性的值,你会发现,只有数据改了,但是页面内容并没有改变。所以:Vue中引入变异数组方法,即保持数组方法原有功能不变的前提下对其进行功能拓展,使其支持响应式。

常用方法:

  a. push: 往数组最后面添加一个元素,成功返回当前数组的长度。

  b. pop: 删除数组的最后一个元素,成功返回删除元素的值

  c. shift: 删除数组的第一个元素,成功返回删除元素的值

  d. unshift: 往数组最前面添加一个元素,成功返回当前数组的长度

  e. splice:  删除,有三个参数,第一个要删除元素的下标(必选),第二个要删除元素的个数(必选),第三个删除后想在原位置替换的值

  f. sort: 将数组按照字符编码从小到大排序,成功返回排序后的数组

  g. reverse: 将数组倒序排列,并返回倒叙后的数组

(2).替换数组

  含义: 不会影响原始的数组数据,而是形成一个新的数组.

常用方法:

  a. filter: 创建一个新的数组,新数组中的元素是通过检查指定数组中符合条件的所有元素。

  b. concat: 用于连接两个或多个数组,该方法不会改变现有的数组。

  c. slice: 从已有的数组中返回选定的元素。该方法并不会修改数组,而是返回一个子数组

  eg:从第0个开始,获取两个元素 this.list = this.list.slice(0, 2);

案例参考:

  https://www.cnblogs.com/yaopengfei/p/12315704.html  底部的图书管理代码。 

二. v-model

1. 基本使用和原理

 v-model指令可以在表单 input、textarea以及select元素上创建双向数据绑定;它会根据控件类型自动选取正确的方法来更新元素;尽管有些神奇,但 v-model 本质上不过是语法糖,它负责监听用户的输入事件来更新数据,并在某种极端场景下进行一些特殊处理;

<body>
        <div id="app"></div>
        <template id="myApp">
            <div>
                <input v-model="msg" />
                <h5>等价于</h5>
                <!-- 等价于 -->
                <input :value="msg" @input="change1">
            </div>
        </template>

        <script src="../js/vue3.js" ></script>
        <script>
            Vue.createApp({
                template: '#myApp',
                data() {
                    return {
                        msg: 'Hello Vue3!'
                    }
                },
                methods:{
                    change1(event){
                        this.msg=event.target.value;
                    }
                }
            }).mount('#app');
        </script>
    </body>

剖析本质:v-model的原理其实是背后有两个操作:

     (1). v-bind绑定value属性的值;

     (2). v-on绑定input事件监听到函数中,函数会获取最新的值赋值到绑定的属性中;

2. 绑定常用标签

 v-model还可以绑定:textarea、checkbox、radio、select。

代码分享:

第三节:Vue3向下兼容2(v-for、数组方法、v-model、计算属性、监听器)第2张第三节:Vue3向下兼容2(v-for、数组方法、v-model、计算属性、监听器)第3张
    <body>
        <div id="app"></div>
        <template id="myApp">
            <!-- 1.绑定textarea -->
            <label for="intro">
                自我介绍
                <textarea name="intro" id="intro" cols="30" rows="10" v-model="intro"></textarea>
            </label>
            <h2>intro: {{intro}}</h2>

            <!-- 2.checkbox -->
            <!-- 2.1.单选框 -->
            <label for="agree">
                <input id="agree" type="checkbox" v-model="isAgree"> 同意协议
            </label>
            <h2>isAgree: {{isAgree}}</h2>

            <!-- 2.2.多选框 -->
            <span>你的爱好: </span>
            <label for="basketball">
                <input id="basketball" type="checkbox" v-model="hobbies" value="basketball"> 篮球
            </label>
            <label for="football">
                <input id="football" type="checkbox" v-model="hobbies" value="football"> 足球
            </label>
            <label for="tennis">
                <input id="tennis" type="checkbox" v-model="hobbies" value="tennis"> 网 球
            </label>
            <h2>hobbies: {{hobbies}}</h2>

            <!-- 3.radio -->
            <span>你的爱好: </span>
            <label for="male">
                <input id="male" type="radio" v-model="gender" value="male"></label>
            <label for="female">
                <input id="female" type="radio" v-model="gender" value="female"></label>
            <h2>gender: {{gender}}</h2>

            <!-- 4.select -->
            <span>喜欢的水果: </span>
            <select v-model="fruit" multiple size="2">
                <option value="apple">苹果</option>
                <option value="orange">橘子</option>
                <option value="banana">香蕉</option>
            </select>
            <h2>fruit: {{fruit}}</h2>
        </template>

        <script src="../js/vue3.js"></script>
        <script>
            Vue.createApp({
                template: '#myApp',
                data() {
                    return {
                        intro: "Hello World",
                        isAgree: false,
                        hobbies: ["basketball", "football"],
                        gender: "",
                        fruit: "orange"
                    }
                }
            }).mount('#app');
        </script>
    </body>
View Code

3. 修饰符

 第三节:Vue3向下兼容2(v-for、数组方法、v-model、计算属性、监听器)第4张

lazy修饰符的作用:

 默认情况下,v-model在进行双向绑定时,绑定的是input事件,那么会在每次内容输入后就将最新的值和绑定的属性进行同步;

 如果我们在v-model后跟上lazy修饰符,那么会将绑定的事件切换为 change 事件,只有在提交时(比如回车)才会触发

number修饰符

第三节:Vue3向下兼容2(v-for、数组方法、v-model、计算属性、监听器)第5张

代码分享:

<body>
        <div id="app"></div>
        <template id="myApp">
            <!-- 1.lazy修饰符 敲击回车才有效-->
            <input type="text" v-model.lazy="message">
            <br>
            <!-- 2.number修饰符 -->
            <input type="text" v-model.number="message">
            <h2>{{message}}</h2>
            <button @click="showType">查看类型</button>

            <!-- 3.trim修饰符 -->
            <input type="text" v-model.trim="message">
            <button @click="showResult">查看结果</button>
        </template>

        <script src="../js/vue3.js"></script>
        <script>
            Vue.createApp({
                template: '#myApp',
                data() {
                    return {
                        message: "Hello World"
                    }
                },
                methods: {
                    showType() {
                        console.log(this.message, typeof this.message);
                    },
                    showResult() {
                        console.log(this.message);
                    }
                }
            }).mount('#app');
        </script>
    </body>

 

三. 计算属性computed

1. 什么时候用计算属性?

 对于任何包含响应式数据的复杂逻辑,你都应该使用计算属性;

 计算属性看起来像是一个函数,但是我们在使用的时候不需要加(),这个后面讲setter和getter时会讲到;

2. 基本用法

<body>
        <div id="app"></div>
        <template id="myApp">
            <div> {{fullName}} </div>
            <div> {{finalResult}} </div>
        </template>
        <script src="../js/vue3.js"></script>
        <script>
            Vue.createApp({
                template: '#myApp',
                data() {
                    return {
                        firstName: 'BBB',
                        lastName: 'AAA',
                        message: "Hello Vue3"
                    }
                },
                computed: {
                    fullName() {
                        return this.lastName + ' ' + this.firstName;
                    },
                    finalResult() {
                        return this.message.split(' ').reverse().join(' ');
                    }
                }
            }).mount('#app');
        </script>
    </body>

3. get 和 set方法

 计算属性在大多数情况下,只需要一个get方法即可,所以我们会将计算属性直接写成一个函数

    但是,如果我们确实想设置计算属性的值呢?这个时候我们也可以给计算属性设置一个set的方法

第三节:Vue3向下兼容2(v-for、数组方法、v-model、计算属性、监听器)第6张第三节:Vue3向下兼容2(v-for、数组方法、v-model、计算属性、监听器)第7张
    <body>
        <div id="app"></div>
        <template id="myApp">
            <div> {{fullName1}} </div>
            <div> {{fullName2}} </div>
        </template>
        <script src="../js/vue3.js"></script>
        <script>
            Vue.createApp({
                template: '#myApp',
                data() {
                    return {
                        firstName: 'BBB',
                        lastName: 'AAA',
                    }
                },
                computed: {
                    // 相当于get方法
                    fullName1() {
                        return this.lastName + ' ' + this.firstName;
                    },
                    fullName2: {
                        get() {
                            return this.lastName + ' ' + this.firstName;
                        },
                        set(newValue) {
                            this.firstName = newValue + this.firstName;
                        }
                    }
                }
            }).mount('#app');
            
        </script>
    </body>
View Code

4. 计算属性的缓存

 计算属性computed是有缓存的,计算属性会基于它们的依赖关系进行缓存;

 在数据不发生变化时,计算属性是不需要重新计算的;但是如果依赖的数据发生变化,在使用时,计算属性依然会重新进行计算

PS. 与method的本质区别:method每次调用都需要重新计算,没有缓存。

代码分享:

<body>
        <div id="app"></div>
        <template id="myApp">
            <!-- 1. 计算属性调用-->
            <div>{{getFullName1()}}</div>
            <div>{{getFullName1()}}</div>
            <div>{{getFullName1()}}</div>
            <!-- 2. 方法调用 -->
            <div>{{getFullName2}}</div>
            <div>{{getFullName2}}</div>
            <div>{{getFullName2}}</div>
            <!-- 3.修改数据内容 -->
            <input type="text" v-model='firstName' />
        </template>

        <script src="../js/vue3.js"></script>
        <script>
            Vue.createApp({
                template: '#myApp',
                data() {
                    return {
                        firstName: 'BBB',
                        lastName: 'AAA'
                    }
                },
                methods: {
                    getFullName1() {
                        console.log('我是方法调用');
                        return this.lastName + ' ' + this.firstName;
                    }
                },
                computed:{
                    getFullName2(){
                        console.log('我是计算属性调用');
                        return this.lastName + ' ' + this.firstName;
                    }
                }

            }).mount('#app');
        </script>
    </body>

运行结果:

 计算属性只调用了1次,方法调用了三次。

 第三节:Vue3向下兼容2(v-for、数组方法、v-model、计算属性、监听器)第8张

   修改数据值,计算属性再次被调用了1次,方法调用了3次。

 第三节:Vue3向下兼容2(v-for、数组方法、v-model、计算属性、监听器)第9张

 5. 扩展get和set的源码

  详见章节:https://www.cnblogs.com/yaopengfei/p/15251328.html

四. 监听器

1. 什么是监听器(侦听器)?

 第三节:Vue3向下兼容2(v-for、数组方法、v-model、计算属性、监听器)第10张

 PS: 可以监听data和computed中的数据。

2.  普通用法

    <body>
        <div id="app"></div>
        <template id="myApp">
            <h3>{{userInfo1.userName}}</h3>
            <div><button @click="Edit1">修改对象</button></div>
            <div><button @click="Edit2">修改userInfo1.userName</button></div>
        </template>
        <script src="../js/vue3.js"></script>
        <script>
            Vue.createApp({
                template: '#myApp',
                data() {
                    return {
                        userInfo1: { userName: 'test1', age: 20, },
                    }
                },
                watch: {
                    // 普通监听
                    // 默认情况下我们的侦听器只会针对监听的数据本身的改变(内部发生的改变是不能侦听)
                    userInfo1(newValue, oldValue) {
                        console.log(oldValue, newValue);
                    },
                },
                methods: {
                    Edit1() {
                        this.userInfo1 = { userName: 'test2' };
                    },
                    Edit2() {
                        this.userInfo1.userName = 'test2';
                    }
            }).mount('#app');
        </script>
    </body>

剖析:

 Edit1方法中直接修改了对象,则普通用法中能监听到,但像Edit2中的修改对象中的内容,是监听不到的!!!

3.  深度监听 和 立即执行

(1). 深度监听

 采用另一种写法,并且需要配置 deep: true ,就可以监听到对象内任何一个属性的修改了。 

<body>
        <div id="app"></div>
        <template id="myApp">
            <h3>{{userInfo2.userName}}</h3>
            <div><button @click="Edit3">修改对象</button></div>
            <div><button @click="Edit4">修改userInfo2.userName</button></div>
            <div><button @click="Edit5">修改userInfo2.childInfo.cName</button></div>
        </template>

        <script src="../js/vue3.js"></script>
        <script>
            Vue.createApp({
                template: '#myApp',
                data() {
                    return {
                        userInfo2: { userName: 'test1', age: 20, childInfo: { cName: 'ypf' } },
                    }
                },
                watch: {// 深度监听
                    // 内部发生的改变也侦听到
                    // 发现一问题:新对象和旧对象中的userName值是相同的,这是因为引用类型赋值的问题,都是指向同一个内存地址(详见后面的知识补充)
                    userInfo2: {
                        handler(newValue, oldValue) {
                            console.log(oldValue, newValue);
                        },
                        deep: true
                    },             
                },
                methods: {
                    Edit3() {
                        this.userInfo2 = { userName: 'test2' };
                    },
                    Edit4() {
                        this.userInfo2.userName = 'test2';
                    },
                    Edit5() {
                        this.userInfo2.childInfo.cName = 'lmr';
                    }

                }

            }).mount('#app');
        </script>
    </body>

剖析:

  无论是修改  userInfo2.userName 还是  userInfo2.childInfo.cName ,都可以监听到。

发现一问题:

  新对象和旧对象中的userName值是相同的,这是因为引用类型赋值的问题,都是指向同一个内存地址(详见后面的知识补充)

(2). 立即执行

  通过设置参数immediate: true,即不发生变化前,默认执行一次。

第三节:Vue3向下兼容2(v-for、数组方法、v-model、计算属性、监听器)第11张

4.  其它写法

(1). 直接监听对象中某个属性值

    watch: {
                    // 特殊的监听方式
                    // 直接监听userName的值
            'userInfo2.userName'(newValue, oldValue) {
                console.log(oldValue, newValue);
            }
    },

(2).  在created生命周期中进行监听

 第三节:Vue3向下兼容2(v-for、数组方法、v-model、计算属性、监听器)第12张

!

  • 作       者 : Yaopengfei(姚鹏飞)
  • 博客地址 : http://www.cnblogs.com/yaopengfei/
  • 声     明1 : 如有错误,欢迎讨论,请勿谩骂^_^。
  • 声     明2 : 原创博客请在转载时保留原文链接或在文章开头加上本人博客地址,否则保留追究法律责任的权利。
 

免责声明:文章转载自《第三节:Vue3向下兼容2(v-for、数组方法、v-model、计算属性、监听器)》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇php-configure错误解决NPOI操作word文档1下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

[C++ STL] vector使用详解

一、概述 vector(向量): 是一种序列式容器,事实上和数组差不多,但它比数组更优越。一般来说数组不能动态拓展,因此在程序运行的时候不是浪费内存,就是造成越界。而vector正好弥补了这个缺陷,它的特征是相当于可分配拓展的数组(动态数组),它的随机访问快,在中间插入和删除慢,但在末端插入和删除快。 二、定义及初始化 使用之前必须加相应容器的头文件: #...

java8使用parallelStream并行流造成数据丢失或下标越界异常解决方案

描述 我们先看一段使用了并行流的代码 @Test public void testStream() { List<Integer> list = new ArrayList<>(); for (int i = 0; i < 10000; i++) { li...

【转】 PostgreSQL数据类型

第六章数据类型 6.1概述 PostgreSQL提供了丰富的数据类型。用户可以使用CREATE TYPE命令在数据库中创建新的数据类型。PostgreSQL的数据类型被分为四种,分别是基本数据类型、复合数据类型、域和伪类型。 基本数据类型是数据库内置的数据类型,包括integer、char、varchar等数据类型。表6-1列出了PostgreSQL提供的...

js-对象使用

1、日期对象,Date 定义一个时间对象 : var Udate=new Date(); 注意:使用关键字new,Date()的首字母必须大写。  使 Udate 成为日期对象,并且已有初始值:当前时间(当前电脑系统时间)。 2、对象Date常用方法 Date对象中处理时间和日期的常用方法: 3、返回星期方法 getDay() 返回星期,返回的是0-6...

C# 数据类型

C#的数据类型可以分为3类:数值类型,引用类型,指针类型.指针类型仅在不安全代码中使用.值类型包括简单类型(如字符型,浮点型和整数型等),集合类型和结构型.引用类型包括类类型,接口类型,代表类型和数组类型.值类型和引用类型的不同之处是值类型的变量值直接包含数据,而引用类型的变量把它们的引用存储在对象中.对于引用类型的变量,完全有可能让两个不同的变量引用同一...

一篇文章教会你创建vue项目和使用vue.js实现数据增删改查

【一、项目背景】 在管理员的一些后台页面里,数据列表中都会对这些数据进行增删改查的操作,例如管理员添加商品、修改商品价格、删除商品、查询商品,我们应该关注这些数据的操作和处理。 【二、项目目标】 主要有以下5个目标: 1、如何创建vue项目。 2、数据添加方法:获取到id和name在data上面获取,组织一个对象,把对象通过数组的相关方法,添加到当前dat...