VUE2学习(class和style绑定、列表的渲染、表单收集)-day03

1-class的绑定

绑定样式:  字符串,数组,对象的三种绑定方式
1。class样式写法:class="xxx”xxx可以是字符串、对象、数组。

  • 字符串写法适用于:类名不确定,要动态获取。
  • 对象写法适用于:要绑定多个样式,个数不确定,名字也不确定。
  • 数组写法适用于:要绑定多个样式,个数确定,名字也确定,但不确定用不用。

2.style样式
:style="{fontsize: xxx}"其中xxx是动态值

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

2-2

<!DOCTYPE html>
<html>

<head>
    <mate charset="UTF-8"></mate>
    <title> 初识VUE</title>
    <style>
        .basic {
            width: 300px;
            height: 60px;
            margin: 10px;
            border: 1px solid black;
        }
        .happy {
            background-color: pink;
            border: 1px solid black;
        }
        .sad {
            background-color: rgb(70, 67, 68);
            border: 1px solid black;
        }
        .wu {
            background-color: rgb(236, 3, 42);
            border: 1px solid black;
        }
        .at1 {
            background-color: green;
            border: 4px solid black;
        }
        .at2 {
            background-color: green;
            border: 4px dashed black;
        }
        .at3 {
            background-color: green;
            border: 4px solid blue;
        }
    </style>
    <script type="text/javascript" src="../js/vue.js"></script>
</head>

<body>
    <div id="root">
        <!-- 绑定class样式--字符串写法,适用于:样式的类名不确定,需要动态指定 -->
        <div class="basic" :class="classStr" @click="changeClass1">{{name}}</div>
        <!-- 绑定class样式--数组写法,适用于:要绑定的样式个数不确定、名字也不确定 -->
        <div class="basic" :class="classArr">{{name}}</div>
        <!-- 绑定class样式--对象写法,适用于:要绑定的样式个数确定、名字也确定,但要动态决定用不用 -->
        <div class="basic" :class="classObj">{{name}}</div>

        <!--绑定style样式 内联样式 作为了解-->
        <!-- 内联样式 对象写法-->
        <div class="basic" :style="styleObj">{{name}}</div>
          <!-- 内联样式 对数组写法-->
          <div class="basic" :style="styleArr">{{name}}</div>
    </div>
    <script type="text/javascript">
        Vue.config.productionTip = false; //设置为 false 以阻止 vue 在启动时生成生产提示。
        const vm = new Vue({
            el: "#root",
            data: {
                name: "test",
                classStr: "happy",
                classArr: ['at1', 'at2', 'at3'],
                classObj: {
                    at1: true,
                    at2: false
                },
                styleObj:{
                    fontSize:'40px',
                    background:'red'
                },
                styleArr: [
                    {fontSize:'40px'},
                    {background:'blue'}
                    ]
            },methods: {
                //改变样式方法
                changeClass1(){
                    //生成[0,3) 的随机数,
                    const num = Math.floor(Math.random()*3);
                    var arr = ['happpy','sad','wu'];
                    this.classStr = arr[num];
                    console.log('当前颜色',this.classStr)
                }
            },
        })

    </script>
</body>

</html>

2- 条件渲染

写法:

1-   v-if=“表达式”

  • v-else-if=“表达式”

  • v-else 适用于:切换频率较低的场景 特点:不展示的DOM元素直接被删除 注意:v-if可以和v-else-if、v-else一起使用,但要求结构不能被打断

        <template v-if="isShow"> 如下:<template> 解析时候会被删除掉,不影响页面结构

2-  v-show=“表达式”

适用于:切换频率较高的场景 特点:不展示的DOM元素未被移除,仅仅是使用样式隐藏掉了

总结对比:

 v-show=“表达式” 适用于:切换频率较高的场景 特点:不展示的DOM元素未被移除,仅仅是使用样式隐藏掉了

<!DOCTYPE html>
<html>

<head>
    <mate charset="UTF-8"></mate>
    <title> 初识VUE</title>
    <script type="text/javascript" src="../js/vue.js"></script>
</head>

<body>
    <div id="root">
        <!-- v-show 语法 条件渲染-->
        <H1 v-show="isShow">原神4.1, {{name}}, 来送福利拉</H1>
        
        <button @click="changeShow">点我v-show使用,display =none隐藏节点(适用频繁操作场景)</button>
        </br>
        </br>
        </br>
        <!-- v-if 语法 条件渲染-->
        <H1 v-if="num === 1">v-if 原神4.1, {{name}}, 来送福利拉</H1>
        <H1 v-else-if="num === 2">v-else-if  原神4.1, {{name}}, 来送福利拉</H1>
        <H1 v-else-if="num === 3">v-else-if  原神4.1, {{name}}, 来送福利拉</H1>
        <H1 v-else>v-else  原神4.1, {{name}}, 来送福利拉</H1>

        <button @click="deleteEl">点我v-if使用,添加删除节点</button>

        <!--template 只能配合 v-if 适用 -->
        <template v-if="isShow">
            <H1 >v-template 原神4.1, {{name}}, 来送福利拉</H1>
        </template>

        <button @click="changeShow">点我template 配合 v-if使用,添加删除节点</button>

    </div>
    <script type="text/javascript">

        const vm = new Vue({
            el: '#root',
            data() {
                return {
                    name: '米哈游',
                    isShow: true,
                    num:1
                }
            },
            methods: {
                changeShow() {
                    this.isShow = !this.isShow
                },
                deleteEl() {
                    let newNum = this.num + 1;
                   this.num =  newNum;
                   console.log("打印当前num值",this.num)
                }
            },
        })
    </script>
</body>

</html>

 3-列表渲染

        3-1 v-for 指令渲染基本列表

语法:

<li v-for="(item, index) in xxx" :key="yyy">,其中key可以是index,也可以是遍历对象的唯一标识

作用:

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

<!DOCTYPE html>
<html>

<head>
    <mate charset="UTF-8"></mate>
    <title> 初识VUE</title>
    <script type="text/javascript" src="../js/vue.js"></script>
</head>

<body>
    <div id="root">
        <!--1- v-for 遍历数组 -->
        <ul>
            <li v-for="(person, index) in personList" :key="person.id">
                索引:{{index}}
            </br>
                数据:{{person.id}}-{{person.name}}-{{person.age}}
            </li>
        </ul>

        <!--2- v-for 遍历对象 -->
        <ul>
            <li v-for="(val, key) in car" :key="key">
                key :{{key}}
            </br>
                数据:{{val}}
            </li>
        </ul>

        <!--3- v-for 遍历字符串 用的少 -->
        <ul>
            <li v-for="(val, index) in str" :key="index">
                key :{{index}}
            </br>
                数据:{{val}}
            </li>
        </ul>

        <!--4- v-for 遍历指定的次数 用得少-->
        <ul>
            <li v-for="(val, index) in 3" :key="index">
                key :{{index}}
            </br>
                数据:{{val}}
            </li>
        </ul>

    </div>
    <script type="text/javascript">
        new Vue({
            el: '#root',
            data() {
                return {
                    personList: [
                        { id: '001', name: '怀标', age: 28 },
                        { id: '002', name: '欢子', age: 28 },
                        { id: '003', name: '叶飞', age: 28 }

                    ],
                    car: {
                        brand: '奥迪',
                        price: '40万',
                        color: '黑色'
                    },
                    str: 'java'
                }
            },
        })

    </script>
</body>

</html>
        3-2 key的原理

3-2-1 key为index的情况

如图:模拟添加人员,在列表前面追加

添加后input输入框数据出现错位,

 情况分析:

vue在生成虚拟DOM时候,用key作为对比,认为现在老刘就是之前张三

解决:
我们将列表遍历的key,从下标index 换为 id唯一标识,就可以解决

<!DOCTYPE html>
<html>

<head>
    <mate charset="UTF-8"></mate>
    <title> 初识VUE</title>
    <script type="text/javascript" src="../js/vue.js"></script>
</head>

<body>
    <div id="root">
        <!--1- v-for 遍历数组 -->
        <button @click.once="add">添加人员</button>
        <ul>
            <li v-for="(person, index) in personList" :key="person.id">
                索引:{{index}} ---- 数据:{{person.id}}-{{person.name}}-{{person.age}}
                <input type="text">
            </li>
        </ul>
    </div>
    <script type="text/javascript">
        new Vue({
            el: '#root',
            data() {
                return {
                    personList: [
                        { id: '001', name: '张三', age: 18 },
                        { id: '002', name: '李四', age: 19 },
                        { id: '003', name: '王五', age: 20 }

                    ]
                }
            }, methods: {
                add() {
                    const p = { id: '004', name: '老刘', age: 21 };
                    this.personList.unshift(p);
                }

            },
        })

    </script>
</body>

</html>

key的对比总结 

对比规则:

一、旧虚拟DOM中找到了与新虚拟DOM相同的key:

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

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

二、旧虚拟DOM中未找到与新虚拟DOM相同的key:

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

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

        1-若对数据进行逆序添加、逆序删除等破坏顺序操作:会产生没有必要的真实DOM更新 ==> 界面效果没问题, 但效率低

         2-若结构中还包含输入类的DOM:会产生错误DOM更新 ==> 界面有问题

开发中如何选择key?

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

4-列表过滤

下面对上面人员列表实现过滤效果,添加搜索框进行搜索

代码如下:

监视属性实现,利用输入框 keyWord变化过滤数据,赋值给新的数组渲染,

计算属性则更直接,keyWord变化时,直接返回列表过滤数据

<!DOCTYPE html>
<html>

<head>
    <mate charset="UTF-8"></mate>
    <title> 初识VUE</title>
    <script type="text/javascript" src="../js/vue.js"></script>
</head>

<body>
    <div id="root">
        <!--1- 监视属性过滤文档 -->
        <h1>利用监视属性 watch 过滤数据</h1>
        人员姓名(监视属性写法): <input type="text" placeholder="请输入姓名" v-model="keyWord1"></input>
        <ul>
            <li v-for="(person, index) in personListWatch" :key="person.id">
                索引:{{index}} ---- 数据:{{person.id}}-{{person.name}}-{{person.age}}
            </li>
        </ul>


        <!--2 - 计算属性写法  -->
        <h1>利用计算属性 computed  过滤数据</h1>
        人员姓名(计算属性写法): <input type="text" placeholder="请输入姓名" v-model="keyWord2"></input>
        <ul>
            <li v-for="(person, index) in personListComputed" :key="person.id">
                索引:{{index}} ---- 数据:{{person.id}}-{{person.name}}-{{person.age}}
            </li>
        </ul>
    </div>
    <script type="text/javascript">
        new Vue({
            el: '#root',
            data() {
                return {
                    keyWord1: '',
                    keyWord2: '',
                    personList: [
                        { id: '001', name: '周杰伦', age: 40 },
                        { id: '002', name: '林俊杰', age: 41 },
                        { id: '003', name: '王力宏', age: 42 },
                        { id: '004', name: '吕建忠', age: 43 }

                    ],
                    personListWatch:[]
                }
            }, methods: {


            },
            watch: {
                keyWord1: {
                    immediate: true,//初始化调用一次handler
                    handler(val) {
                        this.personListWatch = this.personList.filter((p)=>{
                            return p.name.indexOf(this.keyWord1) != -1;
                        })
                    }
                }

            },
            computed: {
                personListComputed() {
                    return this.personList.filter((p) => {
                        return p.name.indexOf(this.keyWord2) !== -1;
                    })
                }
            }
        })

    </script>
</body>

</html>

 5-列表排序

计算属性所依赖的属性发生变化真个计算属性都会发生变化

<!DOCTYPE html>
<html>

<head>
    <mate charset="UTF-8"></mate>
    <title> 初识VUE</title>
    <script type="text/javascript" src="../js/vue.js"></script>
</head>

<body>
    <div id="root">

        <!--2 - 计算属性写法  -->
        <h1>利用计算属性 computed  过滤数据</h1>
        人员姓名(计算属性写法): <input type="text" placeholder="请输入姓名" v-model="keyWord2"></input>
        <button @click="sortType = 2">年龄升序</button>
        <button @click="sortType = 1">年龄降序</button>
        <button @click="sortType = 0">原顺序</button>
        <ul>
            <li v-for="(person, index) in personListComputed" :key="person.id">
                索引:{{index}} ---- 数据:{{person.id}}-{{person.name}}-{{person.age}}
            </li>
        </ul>
    </div>
    <script type="text/javascript">
        new Vue({
            el: '#root',
            data() {
                return {
                    keyWord2: '',
                    sortType: 0,
                    personList: [
                        { id: '001', name: '周杰伦', age: 30 },
                        { id: '002', name: '林俊杰', age: 10 },
                        { id: '003', name: '王力宏', age: 20 },
                        { id: '004', name: '吕建忠', age: 50 }
                    ]
                }
            }, 
            computed: {
                //计算属性用到的属性发生变化,整个属性都会重新计算
                personListComputed() {
                    const arr =  this.personList.filter((p) => {
                        return p.name.indexOf(this.keyWord2) !== -1;
                    });
                    //计算属性排序
                    if(this.sortType){
                        console.log("当前排序", this.sortType)
                        arr.sort((a, b)=>{
                            return this.sortType  === 1 ?  b.age - a.age : a.age - b.age
                        })
                    }

                    return arr;

                }
            }
        })

    </script>
</body>

</html>

7- vue 检测数据的原理

2、监测数据的原理
①Vue会监测data中所有层次的数据,就是即使对象中的对象的属性也能递归监测

如何监测对象中的数据 通过setter实现监测,且要在new Vue时就传入要监测的数据

(1)对象中后追加的属性,Vue默认不做响应式处理

(2)如需要给后添加的属性做响应式,请使用如下API:Vue.set(target,propertyName/index,value) 或 vm.$set(target,propertyName/index,value)

③如何监测数组中的数据 通过包裹数组更新的方法实现,本质就是做了两件事:

(1)调用原生对应的方法对数组进行更新

(2)重写解析模板,进行更新页面

④在Vue修改数组中的某一个元素不能直接赋值,即不能直接带下标赋值,Vue监测不到,就像上面的问题一样,一定要用如下方法:

(1)使用数组的一些API:push()/pop()/shift()/unshift()/splice()/sort()/reverse()

(2)Vue.set()或vm.$set()

当然可以直接改变整个数组。

特别注意:Vue.set()和vm.$set()不能给vm或vm根数据对象 添加属性
 

如下图是vue2官网对数组给出的操作

代码DEMO展示

<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8" />
		<title>Vue数据监视</title>
		<style>
			button{
				margin-top: 10px;
			}
		</style>
		<script type="text/javascript" src="../js/vue.js"></script>
	</head>
	<body>
		<div id="root">
			<h1>学生信息</h1>
			<button @click="student.age++">年龄+1岁</button><br/>
			<button @click="addSex">添加性别属性,默认值:男</button> <br/>
			<button @click="addFriend">在列表首位添加一个朋友</button> <br/>
			<button @click="updateFirstFriendName">修改第一个朋友的名字为:张三</button><br/>
			<button @click="addHobby">添加一个爱好</button> <br/>
			<button @click="updateHobby">修改第一个爱好为:开车</button><br/>
			<button @click="removeSmoke">过滤掉爱好中的抽烟</button> <br/>
			<h3>姓名:{{student.name}}</h3>
			<h3>年龄:{{student.age}}</h3>
			<h3 v-if="student.sex">性别:{{student.sex}}</h3>
			<h3>爱好:</h3>
			<ul>
				<li v-for="(h,index) in student.hobby" :key="index">
					{{h}}
				</li>
			</ul>
			<h3>朋友们:</h3>
			<ul>
				<li v-for="(f,index) in student.friends" :key="index">
					{{f.name}}--{{f.age}}
				</li>
			</ul>
		</div>
	</body>
 
	<script type="text/javascript">
		Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。
 
		const vm = new Vue({
			el:'#root',
			data:{
				student:{
					name:'tom',
					age:18,
					hobby:['抽烟','喝酒','烫头'],
					friends:[
						{name:'jerry',age:35},
						{name:'tony',age:36}
					]
				}
			},
			methods: {
				addSex(){
                    //vue 的set方法绑定数据  不能直接在vm身上(data或者 _data)直接添加
					//Vue.set(this.student,'sex','男')
					this.$set(this.student,'sex','男')
				},
				addFriend(){
                    //在首位添加元素
					this.student.friends.unshift({name:'jack',age:70}) 
				},
				updateFirstFriendName(){
                    //对象 有get set 方法就可以调用
					this.student.friends[0].name = '张三'
				},
				addHobby(){
                    //在尾部追加
					this.student.hobby.push('学习')
				},
				updateHobby(){
                    //更新元素
					this.student.hobby.splice(0,1,'开车')
                    //this.$set(this.student.hobby, 0, '开车')
                    //Vue.set(this.student.hobby, 0, '开车')
				},
				removeSmoke(){
					this.student.hobby = this.student.hobby.filter((h)=>{
						return h !== '抽烟'
					})
				}
			}
		})
	</script>
</html>

8-表单收集

总结:

收集表单数据:

若:<input type="text"/>,则v-model收集的是value值,用户输入的内容就是value值

若:<input type="radio"/>,则v-model收集的是value值,且要给标签配置value属性

若:<input type="checkbox"/>

没有配置value属性,那么收集的是checked属性(勾选 or 未勾选,是布尔值)

配置了value属性:

v-model的初始值是非数组,那么收集的就是checked(勾选 or 未勾选,是布尔值)

v-model的初始值 是数组,那么收集的就是value组成的数组

v-model的三个修饰符:

lazy:失去焦点后再收集数据

number:输入字符串转为有效的数字

trim:输入首尾空格过滤
 

<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8" />
		<title>收集表单数据</title>
		<script type="text/javascript" src="../js/vue.js"></script>
	</head>
	<body>
		<div id="root">
			<form @submit.prevent="demo">
				账号:<input type="text" v-model.trim="userInfo.account"> <br/><br/>
				密码:<input type="password" v-model="userInfo.password"> <br/><br/>
				年龄:<input type="number" v-model.number="userInfo.age"> <br/><br/>
				性别:
				女<input type="radio" name="sex" v-model="userInfo.sex" value="female"> <br/><br/>
				男<input type="radio" name="sex" v-model="userInfo.sex" value="male">
				爱好:
				学习<input type="checkbox" v-model="userInfo.hobby" value="study">
				打游戏<input type="checkbox" v-model="userInfo.hobby" value="game">
				吃饭<input type="checkbox" v-model="userInfo.hobby" value="eat">
				<br/><br/>
				所属校区:
				<select v-model="userInfo.city">
					<option value="">请选择校区</option>
					<option value="beijing">北京</option>
					<option value="shanghai">上海</option>
					<option value="shenzhen">深圳</option>
					<option value="wuhan">武汉</option>
				</select>
				<br/><br/>
				其他信息:
				<textarea v-model.lazy="userInfo.other"></textarea> <br/><br/>
				<input type="checkbox" v-model="userInfo.agree">阅读并接受<a href="http://www.atguigu.com">《用户协议》</a>
				<button>提交</button>
			</form>
		</div>
	</body>
 
	<script type="text/javascript">
		Vue.config.productionTip = false
 
		new Vue({
			el:'#root',
			data:{
				userInfo:{
					account:'',
					password:'',
					age:0,
					sex:'female',
					hobby:[],
					city:'beijing',
					other:'',
					agree:''
				}
			},
			methods: {
				demo(){
					console.log(JSON.stringify(this.userInfo))
				}
			}
		})
	</script>
</html>

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值