vue学习笔记-Vue核心(三)

176 阅读5分钟

10.绑定样式

提前定义好需要用的样式

<style>
    .basic{
        width: 400px;
        height: 100px;
        border: 1px solid black;
    }       
    .happy{
        border: 4px solid red;
        background-color: rgba(255, 255, 0, 0.644);
        background: linear-gradient(30deg,yellow,pink,orange,yellow);
    }
    .normal{
        background-color: skyblue;
    }
    .atguigu1{
        background-color: yellowgreen;
    }
    .atguigu2{
        font-size: 30px;
        text-shadow:2px 2px 10px red;
    }
    .atguigu3{
        border-radius: 20px;
    }
</style>

10.1class样式

字符串写法

适用于:样式的类名不确定,需要动态指定

<div class="basic" :class="mood" @click="changeMood">{{name}}</div>
new Vue({
    data:{
        name:'皓月',
        mood:'normal'
    }
    method:{
        //随机切换样式
        changeMood(){
            const arr = ['happy','sad','normal']
            //对随机数向下取整
            const index = Math.floor(Math.random()*3)
            this.mood = arr[index]
        }
    }
})

数组写法

适用于:要绑定的样式个数不确定、名字也不确定

//第一种写法,比较灵活,可以删掉数组中任意一个也可以修改数组中任意一个
<div class="basic" :class="classArr">{{name}}</div>
const vm = new Vue({
    data:{
        name:'皓月',
        classArr:['atguigu1','atguigu2','atguigu3']
    }
})
//删除atguigu1样式 结果classArr:['atguigu2','atguigu3']
vm.classArr.shift('atguigu1')
//添加happy样式  结果classArr:['atguigu2','atguigu3','happy']
vm.classArr.push('happy')
​
//第二种写法(不推荐)
<div class="basic" :class="['atguigu1','atguigu2','atguigu3']">{{name}}</div>//数据写死了
data:{
   name:'皓月',
}
//改进
<div class="basic" :class="[a,b,c]">{{name}}</div>
data:{
   name:'皓月',
   a:'atguigu1',
   b:'atguigu2',
   c:'atguigu3'
}

对象写法

适用于:要绑定的样式个数确定、名字也确定,但要动态决定用不用

//第一种写法
<div class="basic" :class="classObj">{{name}}
const vm = new Vue({
    data:{
        name:'皓月',
        classObj:{
            atguigu1:false,
            atguigu2:true,
        }
    }
})
//第二种写法(不推荐)
<div class="basic" :class="atguigu1:a,atguigu2:b,">{{name}}
data:{
    name:'皓月',
    classObj:{
        a:false,
        b:true,
    }
}

10.2style样式

对象写法

//第一种写法(不推荐)
<div class="basic" :style="{fontSize:fsize+'px'}">{{name}}</div>
data:{
    name:'皓月'
    fsize:40
}
​
//第二种写法(推荐)
<div class="basic" :style="styleObj">{{name}}</div> 
data:{
    name:'皓月',
    styleObj:{
        fontSize:'40px',
        color:'red'
    }
}

数组写法

//第一种写法
<div class="basic" :style="styleObj,styleObj2">{{name}}</div>
data:{
    name:'皓月',
    styleObj:{
        fontSize: '40px',
        color:'red',
    },
    styleObj2:{
        backgroundColor:'orange'
    }
}
//第二种写法
<div class="basic" :style="styleArr">{{name}}</div>
data:{
    name:'皓月',
    styleArr:[
        {
            fontSize: '40px',
            color:'blue',
        },
        {
            backgroundColor:'gray'
        }
    ]
}

11.条件渲染

11.1 v-show

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

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

适用于: 切换频率较高的场景。

实例:

<div>
    //可以通过改变vm.a的值(true/false)动态控制h2标签的显示与隐藏
    <h2 v-show='a'>欢迎{{name}}</h2>
    //表达式写法,值为真-显示
    <h2 v-show="1 === 1">欢迎来到{{name}}</h2>
</div>
const vm = new Vue({
    el:'#root',
    data:{
        name:'皓月',
        a:false
    }
})
​

11.2 v-if

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

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

适用于: 切换频率较低的场景。

实例:

<h2 v-if="false">欢迎来到{{name}}</h2>
<h2 v-if="1 === 1">欢迎来到{{name}}</h2>

11.3 v-else-if

写法: **v-else-if="表达式"**

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

示例:

<div v-if="n === 1">Angular</div>
<div v-else-if="n === 2">React</div>
//往下找不到if,结构被打断,后面的不会渲染
<div>@</div>
<div v-else-if="n === 3">Vue</div>
<div v-else>哈哈</div>

11.4 v-if和v-show的区别

共同点: 都是动态显示DOM元素

区别:

v-ifv-show
动态的向DOM树内添加或者删除DOM元素通过设置DOM元素的display样式属性来控制显示与隐藏
惰性的,如果初始条件为假,则什么也不做;只有在条件第一次变为真时才开始局部编译任何条件下(首次条件是否为真)都被编译,然后被缓存,而且 DOM 元素保留

12.列表渲染

12.1 v-for

  • 用于展示列表数据
  • 语法:v-for="(item, index) in xxx" :key="yyy"
  • 可遍历:数组、对象、字符串(用的很少)、指定次数(用的很少) 实例:

遍历数组(常用)

<h2>人员列表(遍历数组)</h2>
<ul>
    //有两个形参,p是遍历的每一项,index是索引值
    <li v-for="(p,index) in persons" :key="index">
        {{p.name}}-{{p.age}}
    </li>
</ul>
data:{
    persons:[
        {id:'001',name:'张三',age:18},
        {id:'002',name:'李四',age:19},
        {id:'003',name:'王五',age:20}
    ]
}

遍历对象

<ul>
    //第一个形参是value,第二个形参是key
    <li v-for="(value,k) in car" :key="k">
        {{k}}-{{value}}
    </li>
</ul>
data:{
    car:{
        name:'奥迪A8',
        price:'70万',
        color:'黑色'
    }
}

遍历字符串

<ul>
    //第一个形参是遍历的每个字符,第二个形参是索引值
    <li v-for="(char,index) in str" :key="index">
        {{char}}-{{index}}
    </li>
</ul>
data:{
    str:'hello'
}

遍历指定次数

<ul>
    //number为(1-5),index为(0-4)
    <li v-for="(number,index) of 5" :key="index">
        {{index}}-{{number}}
    </li>
</ul>

12.2 key的原理

key的作用:key是节点的唯一标识,能尽可能的复用DOM元素

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

1. 虚拟DOM中key的作用:

key是虚拟DOM对象的标识,当数据发生变化时,Vue会根据【新数据】生成【新的虚拟DOM】

随后Vue进行【新虚拟DOM】与【旧虚拟DOM】的差异比较,比较规则如下:

2.对比规则:

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

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

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

(2).旧虚拟DOM中未找到与新虚拟DOM相同的key

创建新的真实DOM,随后渲染到到页面。

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

06.png

  • 若对数据进行逆序添加、逆序删除等破坏顺序操作:会产生没有必要的真实DOM更新 ==> 界面效果没问题, 但效率低。
  • 如果结构中还包含输入类的DOM: 会产生错误DOM更新 ==> 界面有问题。
  • 如果没有手动绑定key,vue会默认把索引值index作为唯一标识 4.使用id作为key:

07.png

5.开发中如何选择key?

  • 最好使用每条数据的唯一标识作为key, 比如id、手机号、身份证号、学号等唯一值。
  • 如果不存在对数据的逆序添加、逆序删除等破坏顺序操作,仅用于渲染列表用于展示,使用index作为key是没有问题的。

12.3 列表过滤案例

<div id="root">
    <h2>人员列表</h2>
    <input type="text" placeholder="请输入名字" v-model="keyWord">
    <ul>
        <li v-for="(p,index) of filPerons" :key="index">
            {{p.name}}-{{p.age}}-{{p.sex}}
        </li>
    </ul>
</div>

用watch方法实现

new Vue({
    el:'#root',
    data:{
        keyWord:'',
        persons:[
            {id:'001',name:'马冬梅',age:19,sex:'女'},
            {id:'002',name:'周冬雨',age:20,sex:'女'},
            {id:'003',name:'周杰伦',age:21,sex:'男'},
            {id:'004',name:'温兆伦',age:22,sex:'男'}
        ],
        filPerons:[]
     },
    watch:{
        keyWord:{
            immediate:true,
            handler(val){
                //filter()方法:创建一个新的数组,新数组中的元素是通过查询指定数组中符合条件的所有元素。
                this.filPerons = this.persons.filter((p)=>{
                    //注意:indexOf()结果不存在返回-1,但查询一个空字符串返回结果为0不是-1
                    return p.name.indexOf(val) !== -1
                })
            }
        }
    }
})

用computed方法实现(更简洁)

new Vue({
    el:'#root',
    data:{
        keyWord:'',
        persons:[
            {id:'001',name:'马冬梅',age:19,sex:'女'},
            {id:'002',name:'周冬雨',age:20,sex:'女'},
            {id:'003',name:'周杰伦',age:21,sex:'男'},
            {id:'004',name:'温兆伦',age:22,sex:'男'}
        ],
     },
    computed:{
        filPerons(){
            //计算属性第一次读取时会执行一次 此时indexOf('')传入为空字符串,会渲染全部数据
            return this.persons.filter((p)=>{
                return p.name.indexOf(this.keyWord) !== -1
            })
        }
    }
})