• Vue的渲染原理


    列表渲染

    列表渲染

    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>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69

    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也是选中的状态

    在这里插入图片描述

    
        

    {{msg}}

    序号 姓名 邮箱 选择
    {{index + 1}} {{vip.name}} {{vip.email}}
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42

    指定对象的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)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    <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>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58

    列表排序

    let arr = [8,9,5,4,1,2,3]
    // sort方法排序之后,不会生成一个新的数组,是在原数组的基础之上进行排序,会影响原数组的结构
    arr.sort((a, b) => {
        return b - a
    })
    console.log(arr)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    <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>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61

    收集表单数据

    收集表单数据

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

    • 给form标签添加@submit.prevent
    • 给button按钮添加@click.prevent
    <body>
        <div id="app">
            <h1>{{msg}}h1>
            
            <form @submit.prevent="send">
                
                用户名:<input type="text" v-model.trim="user.username"><br><br>
                密码:<input type="password" v-model="user.password"><br><br>
                
                年龄:<input type="number" v-model.number="user.age"><br><br>
                性别:
                	<input type="radio" name="gender" value="1" v-model="user.gender"><input type="radio" name="gender" value="0" v-model="user.gender"><br><br>
                爱好:
                	
                    旅游<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>
                简介:
               		
                	
                    <textarea cols="50" rows="15" v-model.lazy="user.introduce">textarea><br><br>
                	<input type="checkbox" v-model="user.accept">阅读并接受协议<br><br>
                	
                	<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>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63

    过滤器filters

    过滤器filters

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

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

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

    • 过滤器也可以接收额外的参数,但过滤器的第一个参数永远接收的都是前一个过滤器的返回值
    • 多个过滤器可以串联{{msg | filterA | filterB | filterC}}
    • 由于过滤器的功能完全可以使用methods,computed 来实现,在Vue3当中已经将过滤器语法废弃了
    <body>
        
        <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>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
  • 相关阅读:
    【牛客网-公司真题-前端入门篇】——奇安信春招笔试-前端-卷2
    springboot+vue+nodejs企业公司财务员工工资管理系统java
    k8s(三): 基本概念-ReplicaSet与Deployment
    【Springboot】Springboot如何优雅停机?K8S中Pod如何优雅停机?
    Go gRPC 入门
    数字孪生在工厂领域的应用和优势
    C#运算符重载
    Matlab:脚本和函数
    数据分析第十三讲:数据可视化入门(二)
    高频react面试题自检
  • 原文地址:https://blog.csdn.net/qq_57005976/article/details/136667147