Vue(三):样式绑定、条件渲染、列表渲染、列表过滤与列表排序

一、样式绑定

1、绑定class样式

写法:class="xxx" xxx可以是字符串、对象、数组。

字符串写法适用于:要绑定的样式类名不确定,要动态获取。

数组写法适用于:要绑定的样式不确定,个数也不确定

对象写法适用于:要绑定得样式确定,个数确定,但是要动态决定要不要。

html 复制代码
<!-- 准备好一个容器 -->
    <div id="root">
        <!-- 绑定class样式 字符串写法 适用于样式的类名不确定 动态绑定-->
        <div class="basic" :class="mood" @click="changeMood">{{name}}</div>
        <!-- 绑定class样式 数组写法 要绑定的样式不确定,个数不确定-->
        <div class="basic" :class="classArr">{{name}}</div>
        <!-- 绑定class样式 对象写法 要绑定的样式确定,个数也确定 但需要动态决定用不用-->
        <div class="basic" :class="classObj">{{name}}</div>
    </div>
    <script>
        new Vue ({
            el:'#root',
            data:{
                name:'椰果',
                mood:'normal',
                classArr:['apple1','apple2','apple3'],
                classObj:{
                    apple1:true,
                    apple2:false
                }
            },
            methods: {
                changeMood(){
                    // this.mood = 'happy'
                    // 随机生成happy sad normal
                    const arr = ['happy','sad','normal']
                    const index = Math.floor(Math.random()*3)
                    //Math.random只能取0-2但不包括2,所以*3之后再取整
                    this.mood = arr[index]
                }
            }
        })
    </script>

2、绑定style样式(不常用)

:style="{fontSize: xxx + 'px'}"其中xxx是动态值。
:style="[a,b]"其中a、b是样式对象

html 复制代码
<!--    绑定style样式--对象写法-->
<div class="basic" :class="classArr" :style="styleObj" >{{name}}</div><br>
<!--    绑定style样式--数组写法(非常不常用)-->
<div class="basic" :class="classArr" :style="[styleObj,styleObj2]" >{{name}}</div>
<script>
new Vue({
    el:'#root',
    data: {
        name: 'zzy',
        styleObj:{
        	//驼峰命名法
            fontSize:'50px',
            color:'red'
        },
        styleObj2:{
     	   //驼峰命名法
            backgroundColor:'green'
        }
   }
})
</script>

3、总结

绑定样式:

1.class样式写法:class="xxx"xxx可以是字符串、对象、数组。

字符串写法适用于:类名不确定,要动态获取。

对象写法适用于:要绑定多个样式,个数不确定,名字也不确定。

数组写法适用于:要绑定多个样式,个数确定,名字也确定,但不确定用不用。

2.style样式:

style="{fontSize:xxx}"其中xxx是动态值。

:style="[a,b]"其中a、b是样式对象。

二、条件渲染

1、v-if与v-else

写法:

(1).v-if="表达式"

(2).v-else-if="表达式"

(3).v-else="表达式"

适用于:切换频率较低的场景。(因为会动DOM树,节点删来删去不太好)

特点:不展示的DOM元素直接被移除。

注意:v-if可以和:v-else-if、v-else一起使用,但要求结构不能被"打断"。

2、v-show

写法:v-show="表达式"

适用于:切换频率较高的场景。(不会动DOM树,只是隐藏,相当于添加display:none)

特点:不展示的DOM元素未被移除,仅仅是使用样式隐藏掉

备注:使用v-if的时,元素可能无法获取到,而使用v-show一定可以获取到。这是因为v-if会一不小心把标签直接从页面上干掉,而v-show不会干掉,只会隐藏

html 复制代码
    <div id="root">
    <h2>当前的n值是:{{n}}</h2>
    <button @click="n++">点我n+1</button>
    <!--使用v-show做条件渲染-->
    <!--<h2 v-show="false">欢迎来到{{name}}</h2>-->
    <!--<h2 v-show="1===1">欢迎来到{{name}}</h2>-->

    <!--使用v-if做条件渲染-->
    <!--<h2 v-if="false">欢迎来到{{name}}</h2>-->
    <!--<h2 v-if="1===1">欢迎来到{{name}}</h2>-->

    <!-- v-else和v-else-if -->
    <!-- <div v-if = "n === 1">Angular</div>
    <div v-else-if = "n === 2">React</div>
    <div v-else-if = "n === 3">Vue</div>
    <div v-else>哈哈</div> -->

    <template v-if = "n === 1">
        <!-- template不影响结构 只能与v-if使用 -->
        <h2>你好</h2>
        <h2>中文</h2>
        <h2>吃饭</h2>
    </template>
    </div>
    <script>
        new Vue({
            el: '#root',
            data: {
                n:0
            }
        })
    </script>

3、总结

三、列表渲染

1、v-for

1、用于展示列表数据

2、语法:v-for="(item, index) in xxx" :key="yyy",其中xxx是遍历的目标,yyy是唯一的索引,用于区分每个嘎达

3、可遍历:数组、对象、字符串(用的很少)、指定次数(用的很少)

4、遍历数组的话,index是索引值(唯一),p是数组每个元素

5、遍历对象的话,index就是属性名(唯一),p是属性值

html 复制代码
    <div id="root">
    <!-- 遍历数组 -->
    <h2>人员列表(用的多)</h2>
    <ul>
        <li v-for="(p, index) of persons" :key="index">
            {{p.name}}----{{p.age}}
        </li>
    </ul>
    <!-- 遍历对象 -->
    <h2>汽车信息</h2>
<ul>
    <li v-for="(value,k) of car" :key="k">
        {{k}}----{{value}}
    </li>
</ul>
    <!-- 遍历字符串 -->
    <h2>测试遍历字符串(用得少)</h2>
<ul>
    <li v-for="(char,index) of str" :key="index">
        {{char}}----{{index}}
    </li>
</ul>
    <!-- 遍历指定次数 -->
    <h2>测试遍历字符串(用得少)</h2>
<ul>
    <li v-for="(number,index) of 5" :key="index">
        {{number}}----{{index}}
    </li>
</ul>
    </div>
    <script>
        new Vue({
            el: '#root',
            data: {
                persons:[
                    { id: '001', name: '张三', age: '18'},
                    { id: '002', name: '李四', age: '19'},
                    { id: '003', name: '王五', age: '20'}
                ],
                car:{
                    name:'奥迪a8',
                    price:'800000',
                    color:'black'
                },
                str:'cgp'
            }
        })
    </script>

2、key作用与原理

key可以有三种情况:写唯一标识、写index、不写。其中唯一标识最合适,如果不写会默认是写index

面试题:react、vue中的key有什么作用?(key的内部原理)

1、 虚拟DOM中key的作用:

key是虚拟DOM对象的标识,当数据发生变化时,Vue会根据【新数据】生成【新的虚拟DOM】, 随后Vue进行【新虚拟DOM】与【旧虚拟DOM】的差异比较(diff算法),比较规则如下:

2、对比规则:

(1)旧虚拟DOM中找到了与新虚拟DOM相同的key:

① 若虚拟DOM中内容没变, 直接使用之前的真实DOM!

② 若虚拟DOM中内容变了, 则生成新的真实DOM,随后替换掉页面中之前的真实DOM。

(2)旧虚拟DOM中未找到与新虚拟DOM相同的key,创建新的真实DOM,随后渲染到到页面。

3、 用index作为key可能会引发的问题:

(1)若对数据进行:逆序添加、逆序删除等破坏顺序操作:

会产生没有必要的真实DOM更新 => 界面效果没问题, 但效率低。

(2) 如果结构中还包含输入类的DOM:

会产生错误DOM更新 => 界面有问题。

4、 开发中如何选择key?:

(1)最好使用每条数据的唯一标识作为key, 比如id、手机号、身份证号、学号等唯一值。

(2)如果不存在对数据的逆序添加、逆序删除等破坏顺序操作,仅用于渲染列表用于展示,使用index作为key是没有问题的。

例如:给一个数组的最上面添加一组数据

html 复制代码
   <!-- 准备好一个容器 -->
    <div id="root">
        <h1>人员列表</h1>
        <button @click="add">点击添加老刘</button>
        <ul>
            <li v-for="(p,index) in persons" :key="p.id">
                <!-- 遍历数组的话,index是索引值,p是数组每个元素 -->
                {{p.name}}----{{p.age}}----{{index}}
                <input type="text">
            </li>
        </ul>
    </div>

    <script>
        const vm = new Vue({
            el: '#root',
            data: {
                persons: [
                    { id: 001, name: '张三', age: 23 },
                    { id: 002, name: '李四', age: 18 },
                    { id: 003, name: '王五', age: 10 }
                ]
            },
            methods: {
                add() {
                    const p = { id: 004, name: '老刘', age: 90 };
                    this.persons.unshift(p);
                }
            },
        })
    </script>

遍历列表时key的作用(index作为key):

遍历列表时key的作用(唯一标识作为key):

四、列表过滤

1.使用methods粗略实现

这是我一开始自己琢磨出来的一个办法,给input绑定事件,按下回车键后执行search方法。定义一个newPersons来保证搜索不会越搜越少。但是这种写法会有几个问题:

1、页面上来是没有任何东西的,因为newPersons是空数组,还没有执行search方法进行过滤赋值

2、即使不输入内容,按下回车也不能初始化,因为数组里不包含空字符串(字符串包含空字符串,数组不包含)

javascript 复制代码
<!-- 准备好一个容器 -->
<div id="root">
    <h1>人员列表</h1>
     <input type="text" placeholder="请输入关键字" v-model="keyword" @keyup.enter="search"> 
    <ul>
        <li v-for="(p,index) in newPersons" :key="p.id">
            {{p.name}}----{{p.age}}----{{p.sex}}
        </li>
    </ul>
</div>

<script>
        const vm = new Vue({
            el: '#root',
            data: {
                keyword: '',
                persons: [
                    { id: 001, name: '冯万宁儿', age: 23, sex: '男' },
                    { id: 002, name: '屁及万儿', age: 18, sex: '男' },
                    { id: 003, name: '及丽热巴', age: 10, sex: '女' },
                    { id: 004, name: '冯小刚儿', age: 60, sex: '男' }
                ],
                 newPersons: []
            },
            methods: {
                search() {
                    this.newPersons = this.persons.filter((ele, index) => {
                        const arr = ele.name.split('');    //先把每个对象的name分割为数组
                        //数组里是不包含空字符串的,所以这样如果keyword=''是筛不出来东西的
                        const flag = arr.includes(this.keyword);   //判断数组中是否包含当前vue中的keyword
                        return flag;   //筛选出来包含keyword的对象,组成一个新数组
                    })
                }
            },

        })
</script>

2.使用watch瑕疵实现

使用watch就可以避免上述问题,上面的筛选算法正确写法应该是用includs或者indexOf来判断当前keyword的值是否在name字符串中,这样就可以避免输入框为空值也不显示所有信息的问题。

但是有个瑕疵:handler函数必须在keyword被改变时才执行,也就是说页面上来还是没有信息的,必须手动输入个东西再删掉(手动改变keyword),才能执行handler函数,才能显示所有人物的信息,所以必须加个属性immediate: true,才能默认初始化先调用handler,这样就能实现上来就显示所有人物的信息(最开始keyword='')

javascript 复制代码
<!-- 准备好一个容器 -->
<div id="root">
    <h1>人员列表</h1>
       <!-- <input type="text" placeholder="请输入关键字" v-model="keyword" @keyup.enter="search"> -->
       <input type="text" placeholder="请输入关键字" v-model="keyword">
    <ul>
        <li v-for="(p,index) in newPersons" :key="p.id">
            {{p.name}}----{{p.age}}----{{p.sex}}
        </li>
    </ul>
</div>

<script>
        const vm = new Vue({
            el: '#root',
            data: {
                keyword: '',
                persons: [
                    { id: 001, name: '冯万宁儿', age: 23, sex: '男' },
                    { id: 002, name: '屁及万儿', age: 18, sex: '男' },
                    { id: 003, name: '及丽热巴', age: 10, sex: '女' },
                    { id: 004, name: '冯小刚儿', age: 60, sex: '男' }
                ],
                 newPersons: []
            },
            watch: {
                keyword: {
                    //页面上来由于newPersons是空,不会显示数据,想要让页面初始化就显示所有人,就要加个immediate: true
                    //这样就可以让handler函数初始化时先调用一次,由于开始keyword=''
                    // 而字符串里都包含空字符串,就可以先筛选出来,初始化所有人物信息
                    immediate: true,
                    handler(newVal, oldVal) {
                        this.newPersons = this.persons.filter((ele) => {
                            //判断keyword变化后的新值在不在每个对象的name中,并返回一个新的数组
                            return ele.name.includes(newVal);
                            //有个点要注意,字符串里面是有空字符串的
                        });
                    }
                }

        })
</script>

3.使用computed完美实现

使用计算属性可以解决watch中的一些繁琐写法,也不用在data中再新定义一个空数组newPersons。

计算属性和监视属性最大的区别就是handler函数是被监视的属性更改时执行,而get是属性被读取时就执行,所以页面加载时newPersons被读取直接就调用get函数返回了一个被筛选后的新数组(条件是name包含空字符串),之后每次keyword改动都会导致Vue模板重新解析,get重新调用,不错

javascript 复制代码
<!-- 准备好一个容器 -->
<div id="root">
    <h1>人员列表</h1>
    <!-- <input type="text" placeholder="请输入关键字" v-model="keyword" @keyup.enter="search"> -->
    <input type="text" placeholder="请输入关键字" v-model="keyword">
    <ul>
        <li v-for="(p,index) in newPersons" :key="p.id">
            {{p.name}}----{{p.age}}----{{p.sex}}
        </li>
    </ul>
</div>

<script>
    const vm = new Vue({
        el: '#root',
        data: {
            keyword: '',
            persons: [
                { id: 001, name: '冯万宁儿', age: 23, sex: '男' },
                { id: 002, name: '屁及万儿', age: 18, sex: '男' },
                { id: 003, name: '及丽热巴', age: 10, sex: '女' },
                { id: 004, name: '冯小刚儿', age: 60, sex: '男' }
            ],
            //newPersons: []
        },
        computed: {
            newPersons: {
                get() {
                    return this.persons.filter((ele) => {
                        return ele.name.includes(this.keyword);
                    })
                }
            }
        }
    })
</script>

五、列表排序

先过滤,再排序

首先定义一个sortType属性来判断排序的种类,然后在计算属性里做一个判断。

注意这里仔细理解理解数组的sort方法,很奇怪。

这个案例再次体现出计算属性的强大之处,只要get里用到的数据(keyword,sortType)发生改变,get都会重新执行,模板都会重新解析,这个业务逻辑就实现了

javascript 复制代码
<!-- 准备好一个容器 -->
<div id="root">
    <h1>人员列表</h1>
    <input type="text" placeholder="请输入关键字" v-model="keyword">
    <button @click="sortType = 0">原顺序</button>
    <button @click="sortType = 1">年龄降序</button>
    <button @click="sortType = 2">年龄升序</button>
    <ul>
        <li v-for="(p,index) in newPersons" :key="p.id">
            {{p.name}}----{{p.age}}----{{p.sex}}
        </li>
    </ul>
</div>

<script>
    const vm = new Vue({
        el: '#root',
        data: {
            sortType: 0,   //0原顺序,1年龄降序,2年龄升序
            keyword: '',
            persons: [
                { id: 001, name: '冯万宁儿', age: 23, sex: '男' },
                { id: 002, name: '屁及万儿', age: 18, sex: '男' },
                { id: 003, name: '及丽热巴', age: 10, sex: '女' },
                { id: 004, name: '冯小刚儿', age: 60, sex: '男' }
            ],
        },
        computed: {
            newPersons() {
                //先过滤,再排序
                const arr = this.persons.filter((ele) => {
                    return ele.name.includes(this.keyword);
                });

                // 或者if(this.sortType)
                if (this.sortType !== 0) {
                    arr.sort((a, b) => this.sortType === 1 ? b.age - a.age : a.age - b.age);
                }
                return arr;
            }
        }
    })
</script>

(看完视频之后多加练习在敲一遍)

相关推荐
hongkid5 分钟前
React Native 如何打包正式apk
javascript·react native·react.js
李少兄8 分钟前
简单讲讲 SVG:前端开发中的矢量图形
前端·svg
前端小万9 分钟前
告别 CJS 库加载兼容坑
前端·前端工程化
恋猫de小郭9 分钟前
Flutter 3.38.1 之后,因为某些框架低级错误导致提交 Store 被拒
android·前端·flutter
JarvanMo13 分钟前
Flutter 需要 Hooks 吗?
前端
光影少年23 分钟前
前端如何虚拟列表优化?
前端·react native·react.js
Moment25 分钟前
一杯茶时间带你基于 Yjs 和 reactflow 构建协同流程图编辑器 😍😍😍
前端·后端·面试
菩提祖师_39 分钟前
量子机器学习在时间序列预测中的应用
开发语言·javascript·爬虫·flutter
invicinble43 分钟前
对于前端数据的生命周期的认识
前端
PieroPc1 小时前
用FastAPI 后端 和 HTML/CSS/JavaScript 前端写一个博客系统 例
前端·html·fastapi