要记着培养一个输出型爱好。绑定class和style样式,条件渲染和列表渲染。
绑定样式
绑定class样式
1.class样式
写法:class="xxx”
xxx可以是字符中、对象、数组
字符串写法适用于:类名不确定,要动态获取。
对象写法适用于:要绑定多个样式,个数不确定,名字也不确定。
数组写法适用于:要绑定多个样式,个数确定,名字也确定,但不确定用不用。
绑定style样式
2.style样式
:style="{fontSize:xxx}"其中xxx是动态值,
:style="[a,b]"其中a、b是样式对象。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>绑定样式</title>
<style>
.basic{
width: 300px;
height: 100px;
border: 2px solid blue;
}
.happy{
background-color: red;
}
.sad{background-color: gray;}
.normal{background-color: blue;}
.atguigu1{background-color: green;}
.atguigu2{text-align: center;}
.atguigu3{border-radius: 20%;}
</style>
<script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
<div id="root">
<div class="basic" :class= 'mood' @click="changemode" id="childroot">我的小猫:{{name}}</div> <br/>
<div class="basic" :class= 'classArr' @click="changemode" >我的小猫:{{name}}</div>
<br/>
<div class="basic" :class= 'classObj' @click="changemode" >我的小猫:{{name}}</div>
<br/>
<div class="basic" :style="{fontSize:fsize+'px'}" @click="changemode" >我的小猫:{{name}}</div><br/>
<div class="basic" :style="styleObj" @click="changemode" >我的小猫:{{name}}</div><br/>
<div class="basic" :style="styleArr" @click="changemode" >我的小猫:{{name}}</div>
</div>
<script type="text/javascript">
Vue.config.productionTip = false;
new Vue({
el:'#root',
data:{
name:'douzi',
address:'alsjjj',
mood:'normal',
classArr:['atguigu1','atguigu2','atguigu3'],
classObj:{
atguigu1:true,
atguigu2:false
},
fsize:40,
// 样式对象
styleObj:{
fontSize:'40px'
},
styleArr:[
{fontSize:'20px'},{backgroundColor:'orange'}
]
},
methods: {
changemode(){
const arr = ['happy','sad','normal']
const string = arr[Math.floor(Math.random()*3)]
this.mood = string
console.log(this.mood)
}
},
})
</script>
</body>
</html>
生成的页面
案例
1.在初始状态下,div 元素应用基础样式和正常样式。当用户点击该元素时,样式会切换为开心样式或悲伤样式。
思路:利用:class动态绑定mood类名,使得类名可以根据 mood
变量的值动态变化。然后在Vue 实例的 data
中定义 mood
变量,之后为 div
元素绑定一个事件方法,在方法内部修改 mood
的值
实现:当用户点击该元素时,样式会切换为开心样式,悲伤样式或者正常样式。
changemode(){
const arr = ['happy','sad','normal']
const string = arr[Math.floor(Math.random()*3)]
this.mood = string
}
技巧
技巧1:在 Vue 中,如果有大量样式需要管理,可以采用数组的形式进行存储。这种方式不仅方便初始化,还能在后续随意修改数组内容。由于数组由 Vue 进行管理,操作更加便捷和高效。
通过布尔值控制多个class样式的显示。可以修改true或者false,可以动态修改class样式。
<div class="basic" :class= 'classObj' @click="changemode" >我的小猫:{{name}}</div>
data:{classObj:{
atguigu1:true,
atguigu2:false
}}
技巧2:style样式的技巧
<div class="basic" :style="{fontSize:fsize+'px'}" @click="changemode" >我的小猫:{{name}}</div><br/>
:style="{fontSize:fsize+'px'}" 其中"{fontSize:fsize+'px'}"可以替换成为相同意义的对象和数组,比如
<div class="basic" :style="styleObj" @click="changemode" >我的小猫:{{name}}</div><br/>
<div class="basic" :style="styleArr" @click="changemode" >我的小猫:{{name}}</div>
styleObj:{
fontSize:'40px'
},
styleArr:[
{fontSize:'20px'},{backgroundColor:'orange'}
]
补充知识点
1.document.getElementById('childroot').className = 'basic happy' 手动修改结点,在vue中不推荐
2.在HTML和CSS中,class
属性可以包含多个样式类名,这些类名之间用空格分隔。当有两个class的时候,采用第一个class。
3.const 和 var 的区别
作用域:const
和 let
具有块级作用域,意味着它们只在声明它们的块或子块中有效。var
具有函数作用域,意味着它在整个函数内部都有效。
重复声明:var
允许在同一作用域内重复声明变量,而 const
和 let
不允许。
值的可变性:const
声明的变量必须立即初始化,且不能重新赋值。var
和 let
声明的变量可以重新赋值。
全局对象属性:在全局作用域中,var
声明的变量会成为全局对象的属性(如 window
对象),而 const
和 let
不会。
var j = 15;
console.log(window.j); // 15
const k = 16;
console.log(window.k); // undefined
变量提升:var
声明的变量会被提升到其作用域的顶部,即使赋值操作在声明之后。const
和 let
不会被提升,且在声明之前访问会导致 ReferenceError
。
console.log(c); // undefined
var c = 3;
console.log(d); // ReferenceError: Cannot access 'd' before initialization
const d = 4;
4. Math.random 是包含0,但是不包含1,所以乘以3就无限接近于3,然后floor,是向下取整,就可以取到0,1,2
条件渲染:v-show,v-if和v-for
v-show的底层实现就是display:none,可以见到节点
v-if看不到节点
1.v-if
写法:
(1).v-if="表达式”
(2).v-else-if="表达式”
(3)v-elses"="表达式”
适用于:切换频率较低的场最
特点:不展示的DOM元素直接移出
注意:v-if可以和:v-else-if、v-else一起使用,但要求结构不被“打断”
2.v-show
写法:v-show="表达式”
适用于:切换频率较高的场景。
特点:不展示的DOM元素未被移除,仅仅是使用样式隐藏掉
3.备注:使用v-if的时,元素(结点)可能无法获取到,而使用v-show一定可以获取到。
undefined不呈现在页面上
列表渲染:
v-for指令
1.用于展示列表数据
2.语法:v-for="(item,index)in xxx" :key="yyy"
3.可遍历:数组、对象、字符中(用的很少)、指定次数(用的很少)
列表渲染
遍历数组,:key="p.id" ,让每一个li都有标识。key不能重复
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>基本列表</title>
<script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
<div id="root">
<h2>人员列表</h2>
遍历数组
只用一个参数遍历
<ul>
<li v-for="p in personArr" :key="p.id">
{{p.name}}-{{p.age}}
</li>
</ul>
</div>
<script type="text/javascript">
Vue.config.productionTip = false;
new Vue({
el:'#root',
data:{
personArr:[
{id:'001',name:'小粉',age:20},
{id:'001',name:'小红',age:30},
{id:'001',name:'小绿',age:25}
]
}
})
</script>
</body>
</html>
可遍历:数组、对象、字符中(用的很少)、指定次数(用的很少)
用两个参数遍历
<ul>
<li v-for="(p,index) in personArr" :key="index" >
{{p.name}}-{{p.age}}--{{index}}
</li>
</ul>
api of
<ul>
<li v-for="(p,index) of personArr" :key="index" >
{{p.name}}-{{p.age}}--{{index}}
</li>
</ul>
遍历对象
<ul>
<li v-for="(value,key) of carmessage" :key="key" >
{{value}}-{{key}}
</li>
</ul>
遍历字符串
<ul>
<li v-for="(char,index) of str" :key="index" >
{{char}}-{{index}}
</li>
</ul>
遍历指定次数
<ul>
<li v-for="(a,b) of 5" >
{{a}}-{{b}}
</li>
</ul>
案例:在数组第一个元素添加一个变量(unshift)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>基本列表</title>
<script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
<div id="root">
<h2>人员列表</h2>
<button @click="add">添加一个用户</button>
用两个参数遍历
<ul>
<li v-for="(p,index) in personArr" :key="index" >
{{p.name}}-{{p.age}}--{{index}}
</li>
</ul>
:key是被vue征用的。因为打开真实dom发现key并不在页面上。
</div>
<script type="text/javascript">
Vue.config.productionTip = false;
new Vue({
el:'#root',
data:{
personArr:[
{id:'001',name:'小粉',age:20},
{id:'001',name:'小红',age:30},
{id:'001',name:'小绿',age:25}
]
},
methods:{
add(){
const p = {id:'004',name:'小liu',age:25}
this.personArr.unshift(p)
}
}
})
</script>
</body>
</html>
接着,给每一个li添加一个输入框。点击添加用户,发现输入框和用户姓名发生了错乱
解决办法
用key绑定用户标识id,涉及到的就是key的基本原理和虚拟dom的对比算法。
虚拟dom更新
以下是以 index
作为 key
时,虚拟 DOM 更新过程的描述:
图中展示了在添加“老刘”这一数据项前后,旧数据和新数据生成虚拟 DOM,并将虚拟 DOM 转换为真实 DOM 的过程。
在初始状态下,旧数据会生成对应的虚拟 DOM。这些虚拟 DOM 以 key
的值(这里 key
为 index
)作为索引,存储在内存中(虚拟 DOM 是抽象概念,无法直接看到)。而此时生成的真实 DOM 节点本身并不携带 key
属性。
当添加“老刘”这一新数据项后,新数据同样会生成新的虚拟 DOM。接下来,React(或其他相关框架)会将这些新生成的虚拟 DOM 与旧的虚拟 DOM 进行对比,判断节点是否发生改变。如果检测到节点有变化,就会将新数据对应的虚拟 DOM 节点转换为真实 DOM 节点;如果节点未发生变化,则会复用旧数据对应的真实 DOM 节点。比如,key相等,但是老刘节点和张三节点不同,所以会生成真实dom节点。两个input节点相等,复用旧数据对应的真实dom节点。
以下是以 id
作为 key
时,虚拟 DOM 更新过程的描述:
因为id是每一组数据都有的,所以可以避免索引值的问题,提升dom的复用率。
面试题:react、Ivue中的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可能会引发的问题:
1.若对数据进行:逆序添加、逆序副除等破坏顺序操作:会产生没有必要的真实DOM更新==>界面效果没问题,但效低
2.如果结构中还包含输入类的DOM:会产生错误DOM更新 ==>界面有问题
4.开发中如何选择key?:
1.最好使用每条数据的唯一标识作为key,比如id、手机号、身份证号、学号等唯一值。
2.如果不存在对数据的逆序添加、逆序删除等破坏顺序操作,仅用于渲染列表用于展示,使用index作为key是没有问题的。