Vue的渲染原理

news2024/11/17 23:29:22

列表渲染

列表渲染

v-for指令写在循环项上:v-for=“(一个参数或者两个参数) in/of 要遍历的数组、对象、字符串、指定次数”

  • 遍历数组时参数分别是数组中元素(可以是一个对象)和元素所在下标(从0开始)
  • 遍历对象时参数分别是属性值和属性名
  • 遍历字符串时参数分别是单个字符和字符所在下标(从0开始)
  • 遍历次数时参数分别是当前遍历的次数和遍历次数所在的下标(从0开始)
<body>
    <div id="app">
        <h1>{{msg}}</h1>
        <h2>遍历数组</h2>
        <!-- 静态列表 -->
        <ul>
            <li>张三</li>
            <li>李四</li>
            <li>王五</li>
        </ul>
        <!--动态列表-->
        <ul>
            <li v-for="name of names">{{name}}</li>
        </ul>

        <ul>
            <li v-for="(name,index) of names"> {{name}}-{{index}}</li>
        </ul>
         <h2>遍历对象的属性</h2>
        <ul>
            <li v-for="(value, propertyName) of user">{{propertyName}},{{value}}</li>
        </ul>

        <h2>遍历字符串</h2>
        <ul>
            <li v-for="(c,index) of str">{{index}},{{c}}</li>
        </ul>

        <h2>遍历指定的次数</h2>
        <ul>
            <li v-for="(num,index) of counter">{{index}}, {{num}}</li>
        </ul>
        <!--遍历数组中的对象-->
        <table>
            <tr>
                <th>序号</th>
                <th>会员名</th>
                <th>年龄</th>
                <th>选择</th>
            </tr>
            <tr v-for="(vip,index) in vips">
                <td>{{index+1}}</td>
                <td>{{vip.name}}</td>
                <td>{{vip.age}}</td>
                <td><input type="checkbox"></td>
            </tr>
        </table>
    </div>
    <script>
        const vm = new Vue({
            el : '#app',
            data : {
                msg : '列表渲染',
                names : ['jack','lucy','james'],
                vips : [
                    {id:'111',name:'jack',age:20},
                    {id:'222',name:'lucy',age:30},
                    {id:'333',name:'james',age:40}
                ],
                user : {
                    id : '111',
                    name : '张三',
                    gender : '男'
                },
                str : '动力节点',
                counter : 10
            }
        })
    </script>

v-for的key的作用以及实现原理

Vue框架采用了虚拟Dom机制+diff算法来提高渲染效率, 只有真正改变的dom元素才会重新渲染

  • 虚拟dom就是在内存当中的dom对象
  • diff算法是一种能够快速的比较两个事物不同之处的算法

新的虚拟dom和旧的虚拟dom比较原则: 根据v-for指令所在的标签的key属性值(key存在于虚拟dom元素中是其的唯一标识)

  • 先拿key的属性值进行比较, 如果属性值相同则继续比较子元素(key属性是dom元素的唯一标识)
    • 子元素不同:直接将新的虚拟dom元素渲染到页面生成新的真实dom元素
    • 子元素相同:直接复用之前的真实dom
  • 如果key不同直接将新的虚拟dom元素渲染到页面生成新的真实dom元素

在这里插入图片描述

如果没有指定标签的key属性,会自动拿index作为key属性的值, 这种方式效率低复用性差, 另外操作数组当中的非末尾元素时容易发生错乱

  • 选中页面上全部的复选框, 此时的真实DOM就是选中时的状态,所以复用时添加的tom也是选中的状态

在这里插入图片描述

<body>
    <div id="app">
        <h1>{{msg}}</h1>
        <button @click="addFirst">在数组第一个位置添加 tom</button>
        <button @click="addLast">在数组最后位置添加 vue</button>
        <table>
            <tr>
                <th>序号</th>
                <th>姓名</th>
                <th>邮箱</th>
                <th>选择</th>
            </tr>
            <tr v-for="(vip,index) of vips" :key="index">
                <td>{{index + 1}}</td>
                <td>{{vip.name}}</td>
                <td>{{vip.email}}</td>
                <td><input type="checkbox"></td>
            </tr>
        </table>
    </div>
    <script>
        const vm = new Vue({
            el : '#app', 
            data : {
                msg : 'key原理(虚拟dom与diff算法)', 
                vips : [
                    {id:'100',name:'jack',email:'jack@123.com'}, 
                    {id:'200',name:'lucy',email:'lucy@123.com'}, 
                    {id:'300',name:'james',email:'james@123.com'}
                ]
            }, 
            methods : {
                addFirst(){
                    this.vips.unshift({id:'400',name:'tom',email:'tom@123.com'})
                }, 
                addLast(){
                    this.vips.push({id:'500',name:'vue',email:'vue@123.com'})
                }
            }
        })
    </script>
</body>

指定对象的id作为key属性的值 , 因为id是唯一的所以不会出现错乱问题

在这里插入图片描述

列表过滤和排序

列表过滤

监视文本框中输入的数据,根据用户输入的关键字对原数组进行过滤,将新数组渲染到页面

  • 使用watch配置项:需要定义一个数组用来接收过滤后的数组
  • 使用computed配置项:不需要定义数组,直接返回过滤后的数组就是计算属性的值
let arr = [1,2,3,4,5,6,7,8,9]
// filter不会破坏原数组的结构,会生成一个全新的数组
let newArr = arr.filter((num) => {
    //return 过滤规则
    return num < 5
})

console.log(newArr)
<body>
    <div id="app">
        <h1>{{msg}}</h1>
        <input type="text" placeholder="请输入搜索关键字" v-model="keyword">
        <table>
            <tr>
                <th>序号</th>
                <th>英雄</th>
                <th>能量值</th>
                <th>选择</th>
            </tr>
            <tr v-for="(hero,index) in filteredHeros" :key="hero.id">
                <td>{{index+1}}</td>
                <td>{{hero.name}}</td>
                <td>{{hero.power}}</td>
                <td><input type="checkbox"></td>
            </tr>
        </table>
    </div>
    <script>
        const vm = new Vue({
            el : '#app',
            data : {
                keyword : '',
                msg : '列表过滤',
                heros : [
                    {id:'101',name:'艾格文',power:10000},
                    {id:'102',name:'麦迪文',power:9000},
                    {id:'103',name:'古尔丹',power:8000},
                    {id:'104',name:'萨尔',power:6000}
                ],
                filteredHeros : []
            },
            watch : {
                // 页面初次加载时就调用handler函数
                keyword : {
                    immediate : true,
                    handler(val){
                        this.filteredHeros = this.heros.filter((hero) => {
                            // 执行过滤规则
                            return hero.name.indexOf(val) >= 0
                        })
                    }
                }
            }
            
             computed : {
                filteredHeros(){
                    // 返回数组作为计算属性的值
                    return this.heros.filter((hero) => {
                        // 执行过滤规则
                        return hero.name.indexOf(this.keyword) >= 0
                    })
                }
            }
        })
    </script>
</body>

列表排序

let arr = [8,9,5,4,1,2,3]
// sort方法排序之后,不会生成一个新的数组,是在原数组的基础之上进行排序,会影响原数组的结构
arr.sort((a, b) => {
    return b - a
})
console.log(arr)
<body>
    <div id="app">
        <h1>{{msg}}</h1>
        <input type="text" placeholder="请输入搜索关键字" v-model="keyword">
        <button @click="type = 1">升序</button>
        <button @click="type = 2">降序</button>
        <button @click="type = 0">原序</button>
        <table>
            <tr>
                <th>序号</th>
                <th>英雄</th>
                <th>能量值</th>
                <th>选择</th>
            </tr>
            <tr v-for="(hero,index) in filteredHeros" :key="hero.id">
                <td>{{index+1}}</td>
                <td>{{hero.name}}</td>
                <td>{{hero.power}}</td>
                <td><input type="checkbox"></td>
            </tr>
        </table>
    </div>
    <script>
        const vm = new Vue({
            el : '#app',
            data : {
                type : 0,
                keyword : '',
                msg : '列表排序',
                heros : [
                    {id:'101',name:'艾格文',power:10000},
                    {id:'102',name:'麦迪文',power:9000},
                    {id:'103',name:'古尔丹',power:8000},
                    {id:'104',name:'萨尔',power:11000}
                ]
            },
            computed : {
                filteredHeros(){
                    //  排序会影响原数组的结构
                    const arr = this.heros.filter((hero) => {
                        // 执行过滤规则
                        return hero.name.indexOf(this.keyword) >= 0
                    })
                    // 排序
                    if(this.type === 1){
                        // a和b是一个对象
                        arr.sort((a, b) => {
                            return a.power - b.power
                        })
                    }else if(this.type == 2){
                        arr.sort((a, b) => {
                            return b.power - a.power
                        })
                    }
                    // 返回新数组作为计算属性的值
                    return arr
                }
            }
        })
    </script>
</body>

收集表单数据

收集表单数据

阻止表单的默认提交行为的方式

  • 给form标签添加@submit.prevent
  • 给button按钮添加@click.prevent
<body>
    <div id="app">
        <h1>{{msg}}</h1>
        <!--阻止表单的默认提交行为-->
        <form @submit.prevent="send">
            <!--v-model.trim去除字符串的前后空白-->
            用户名:<input type="text" v-model.trim="user.username"><br><br>
            密码:<input type="password" v-model="user.password"><br><br>
            <!--v-model.number可以将收集到的字符串转化为数字保存-->
            年龄:<input type="number" v-model.number="user.age"><br><br>
            性别:
            	<!--同一组(name属性值相同)的单选按钮才只能选一个--><input type="radio" name="gender" value="1" v-model="user.gender"><input type="radio" name="gender" value="0" v-model="user.gender"><br><br>
            爱好:
            	<!--对于checkbox来说,如果没有手动指定value,那么会拿这个标签的checked属性的值作为value(选中为true,未选中为false)-->
                旅游<input type="checkbox" v-model="user.interest" value="travel">
                运动<input type="checkbox" v-model="user.interest" value="sport">
                唱歌<input type="checkbox" v-model="user.interest" value="sing"><br><br>
            学历:
                <select v-model="user.grade">
                    <option value="">请选择学历</option>
                    <option value="zk">专科</option>
                    <option value="bk">本科</option>
                    <option value="ss">硕士</option>
                </select><br><br>
            简介:
           		<!--标签体当中的内容就是文本域的value-->
            	<!--v-model.lazy失去焦点后才开始收集表单数据-->
                <textarea cols="50" rows="15" v-model.lazy="user.introduce"></textarea><br><br>
            	<input type="checkbox" v-model="user.accept">阅读并接受协议<br><br>
            	<!--<button @click.prevent="send">注册</button>-->
            	<button>注册</button>
        </form>
    </div>
    <script>
        const vm = new Vue({
            el : '#app',
            data : {
                user : {
                    username : '',
                    password : '',
                    age : '',
                    // 默认选中指定表单的value值
                    gender : '1',
                    // 复选框的value采用数组接收
                    interest : ['travel'],
                    grade : 'ss',
                    introduce : '',
                    accept : ''
                },
                msg : '表单数据的收集'
            },
            methods : {
                send(){
                    alert('ajax...!!!!')
                    // 将数据收集好,发送给服务器
                    console.log(JSON.stringify(this.user))
                }
            }
        })
    </script>
</body>

过滤器filters

过滤器filters

过滤器适用于简单的逻辑处理,可以进行全局配置或局部配置

  • 全局配置:在构建任何Vue实例之前使用Vue.filter(‘过滤器名称’, callback)进行配置,可以在任何一个容器中使用
  • 局部配置:在构建Vue实例的配置项中使用filters 进行局部配置,只能在当前绑定的容器中使用

过滤器可以用在插值语法和v-bind指令中,可以对一些数据进行格式化显示

  • 过滤器也可以接收额外的参数,但过滤器的第一个参数永远接收的都是前一个过滤器的返回值
  • 多个过滤器可以串联{{msg | filterA | filterB | filterC}}
  • 由于过滤器的功能完全可以使用methods,computed 来实现,在Vue3当中已经将过滤器语法废弃了
<body>
    <!--从服务器端返回一个商品的价格price,如果price的值是''、null、undefined页面上统一显示为 - , 反之显示真实的数字-->
    <div id="app">
        <h1>{{msg}}</h1>
        <h2>商品价格:{{formatPrice}}</h2>
        <h2>商品价格:{{formatPrice2()}}</h2>
        <h2>商品价格:{{price | filterA | filterB(3)}}</h2>
        <input type="text" :value="price | filterA | filterB(3)">
    </div>
    <!--在另一个容器中使用全局的过滤器-->
    <div id="app2">
        <h2>商品价格:{{price | filterA | filterB(3)}}</h2>
    </div>
    <script>
        // 配置全局的过滤器可以在另一个容器中使用
        Vue.filter('filterA', function(val){
            if(val === null || val === undefined || val === ''){
                return '-'
            }
            return val
        })
        Vue.filter('filterB', function(val, number){
            return val.toFixed(number)
        })

        const vm2 = new Vue({
            el : '#app2',
            data : {
                price : 20.3
            }
        })

        const vm = new Vue({
            el : '#app',
            data : {
                msg : '过滤器',
                price : 50.6
            },
            methods: {
                formatPrice2(){
                    if(this.price === '' || this.price === undefined || this.price === null){
                        return '-'
                    }
                    return this.price
                }
            },
            computed : {
                formatPrice(){
                    if(this.price === '' || this.price === undefined || this.price === null){
                        return '-'
                    }
                    return this.price
                }
            },
            // 局部过滤器
            filters : {
                filterA(val){
                    if(val === null || val === undefined || val === ''){
                        return '-'
                    }
                    return val
                },
                filterB(val, number){
                    // 确保传递过来的数据val,保留number位小数
                    return val.toFixed(number)
               }
            } 
        })
    </script>
</body>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1515160.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

基于SpringCache实现数据缓存

SpringCache SpringCache是一个框架实现了基本注解的缓存功能,只需要简单的添加一个EnableCaching 注解就能实现缓存功能 SpringCache框架只是提供了一层抽象,底层可以切换CacheManager接口的不同实现类即使用不同的缓存技术,默认的实现是ConcurrentMapCacheManagerConcurren…

Redisson分布式锁解决方案

官方地址 官网: https://redisson.org github: https://github.com/redisson/redisson 基于setnx实现的分布式锁存在的问题 redisson分布式锁原理 不可重入: 利用hash结构记录线程id和重入次数不可重试: 利用信号量和PubSub功能实现等待、唤醒, 获取锁失败的重试机制超时释放…

监听抖音直播间的评论并实现存储

监听抖音直播间评论&#xff0c;主要是动态监听dom元素的变化&#xff0c;如果评论是图片类型的&#xff0c;获取alt的值 主要采用的是MutationObserver&#xff1a;https://developer.mozilla.org/zh-CN/docs/Web/API/MutationObserver index.js如下所示:function getPL() {…

29网课交单平台源码最新修复全开源版本

去除论文编辑 去除强国接码 修复上级迁移 修复聚合登录 修复支付不回调 优化支付接口兼容码/易支付 优化MySQL表&#xff0c;提高网页加载速度 下载地址&#xff1a;https://pan.xunlei.com/s/VNstLrJaRtbvDyovPQ-CbISOA1?pwd622t#

数字人基础 | 3D手部参数化模型2017-2023

楔子: 2017年年底的泰国曼谷, SIGGRAPH Asia会议上, 来自马普所的 Javier Romero, Dimitrios Tzionas(两人都是 Michael J. Black的学生)发布了事实性的手部参数化模型标准: MANO [1]。 MANO的诞生意味着 Michael J. Black团队在继人体参数化模型 SMPL后, 事实性的将能够表达人…

【正则表达式】正则表达式里使用变量

码 const shuai No My Name Is ShuaiGe.match(new RegExp(shuai, gi)); //↑↑↑↑↑↑↑↑ //等同于 //↓↓↓↓↓↓↓↓ /No/.test(My Name Is ShuaiGe)用作领域 搜索的字符动态改变&#xff0c;例如↓模糊搜索例&#xff1a; 一个文本宽&#xff0c;输入文本模糊搜索用户…

【哈希映射】【 哈希集合】 381. O(1) 时间插入、删除和获取随机元素 - 允许重复

作者推荐 视频算法专题 本文涉及知识点 哈希映射 哈希集合 LeetCode 381. O(1) 时间插入、删除和获取随机元素 - 允许重复 RandomizedCollection 是一种包含数字集合(可能是重复的)的数据结构。它应该支持插入和删除特定元素&#xff0c;以及删除随机元素。 实现 Randomiz…

【漏洞复现】金和OA viewConTemplate.action RCE漏洞

免责声明&#xff1a;文章来源互联网收集整理&#xff0c;请勿利用文章内的相关技术从事非法测试&#xff0c;由于传播、利用此文所提供的信息或者工具而造成的任何直接或者间接的后果及损失&#xff0c;均由使用者本人负责&#xff0c;所产生的一切不良后果与文章作者无关。该…

XIAO ESP32S3部署Edge Impulse模型

在上一篇文章中我们介绍了如何使用edge impulse训练一个图片分类模型并导出arduino库文件。在这篇文章中我们将介绍如何在esp32s3中部署这个训练好的图片分类模型。 添加进Arduino库 有两种方法将下载的文件添加进Arduino库。 在Arduino IDE程序中&#xff0c;转到项目选项卡…

php apache 后台超时设置

最近在写一个thinkphp项目的时候&#xff0c;发现Ajax从后端请求数据时间比较长&#xff0c;大概需要45秒左右&#xff0c;但是一旦请求时间超过40s&#xff0c;页面就会超时500了&#xff0c;一开始以为是ajax请求时间不能太长&#xff0c;后来将Ajax请求改为同步且timeout设置…

景联文科技:提供行业垂直大模型训练数据

近年来&#xff0c;以大模型为代表的人工智能技术已成为国家科技实力竞争的焦点。其中垂直大模型作为重要方向&#xff0c;在相关政策引导及市场需求的驱动下&#xff0c;已展现出较强的发展活力。 行业垂直大模型是针对特定行业的需求和场景进行深度定制的。这意味着模型在训练…

软考高级:需求变更管理过程概念和例题

作者&#xff1a;明明如月学长&#xff0c; CSDN 博客专家&#xff0c;大厂高级 Java 工程师&#xff0c;《性能优化方法论》作者、《解锁大厂思维&#xff1a;剖析《阿里巴巴Java开发手册》》、《再学经典&#xff1a;《Effective Java》独家解析》专栏作者。 热门文章推荐&am…

【ARM】MDK在programming algorithm界面添加FLM

【更多软件使用问题请点击亿道电子官方网站查询】 1、 文档目标 解决在programming algorithm界面中无法添加想要的Flash编程算法的问题 2、 问题场景 在对于Debug进行Flash Download进行配置的时候&#xff0c;在programming algorithm界面中有对应的Flash编程算法。可以通过…

【python】anaconda安装过程

【运行环境】Windows11 文章目录 一、anaconda下载二、anaconda安装三、环境变量配置四、测试环境变量是否配置成功五、总结 一、anaconda下载 1、输入网址“https://www.anaconda.com”进入Anaconda官网。 2、找到【Free Download】点击进入&#xff1a; 3、点击对应系统的…

spring源码环境搭建问题解决

源码搭建需要提前准备的环境 jdk环境变量配置 gradle环境变量配置&#xff08;gradle安装配置详细教程(windows环境)_windows安装gradle-CSDN博客&#xff09; spring5.2.x jdk1.8 gradle5.6.4(源码对应的gradle版本查看路径&#xff0c;在源码中找对应文件配置&#xff1a…

leetcode一天一题-第1天

为了增加自己的代码实战能力&#xff0c;希望通过刷leetcode的题目&#xff0c;不断提高自己&#xff0c;增加对代码的理解&#xff0c;同时开拓自己的思维方面。 题目名称&#xff1a;两数之和 题目编号&#xff1a;1 题目介绍&#xff1a; 给定一个整数数组 nums 和一个整数…

基于恒功率PQ控制的三电平并网逆变器MATLAB仿真模型

微❤关注“电气仔推送”获得资料&#xff08;专享优惠&#xff09; 模型简介 三相 T 型三电平逆变器电路如图所示&#xff0c;逆变器主回路由三个单相 T 型逆变器组成。 直流侧输入电压为 UPV&#xff0c;直流侧中点电位 O 设为零电位&#xff0c;交流侧输出侧是三相三线制连…

【快速上手ProtoBuf】proto 3 语法详解

1 &#x1f351;字段规则&#x1f351; 消息的字段可以⽤下⾯⼏种规则来修饰&#xff1a; singular &#xff1a;消息中可以包含该字段零次或⼀次&#xff08;不超过⼀次&#xff09;。 proto3 语法中&#xff0c;字段默认使⽤该规则。repeated &#xff1a;消息中可以包含该…

【Java设计模式】十九、中介者模式

文章目录 1、中介者模式2、案例3、总结 1、中介者模式 如图&#xff1a; 同事类之间关联较多时&#xff0c;整体出现网状结构&#xff0c;耦合度极高。一个对象一变动&#xff0c;好多对象都得改。若变为右边的星形结构&#xff0c;则一个类的变动&#xff0c;只影响自身与中介…

滴滴 Flink 指标系统的架构设计与实践

毫不夸张地说&#xff0c;Flink 指标是洞察 Flink 任务健康状况的关键工具&#xff0c;它们如同 Flink 任务的眼睛一般至关重要。简而言之&#xff0c;这些指标可以被理解为滴滴数据开发平台实时运维系统的数据图谱。在实时计算领域&#xff0c;Flink 指标扮演着举足轻重的角色…