Vue 条件渲染、数据监测原理、收集表单数据、过滤器

180 阅读2分钟

条件渲染

  1. v-if
    • 写法:(1).v-if="表达式" (2).v-else-if="表达式"(3).v-else="表达式"
    • 适用于:切换频率较低的场景。
    • 特点:不展示的DOM元素直接被移除。
    • 注意:v-if可以和:v-else-if、v-else一起使用,但要求结构不能被“打断”。
  2. v-show
    • 写法:v-show="表达式"
    • 适用于:切换频率较高的场景。
    • 特点:不展示的DOM元素未被移除,仅仅是使用样式隐藏掉

备注:使用v-if的时,元素可能无法获取到,而使用v-show一定可以获取到。

<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>
	<!-- v-if与template的配合使用 -->
	<template v-if="n === 1">
		<h2>你好</h2>
		<h2>aaa</h2>
		<h2>北京</h2>
	</template>
</div>

Vue数据监测原理

  1. vue会监视data中所有层次的数据。
  2. 如何监测对象中的数据?
    • 通过setter实现监视,且要在new Vue时就传入要监测的数据。
    • 对象中后追加的属性,Vue默认不做响应式处理
    • 如需给后添加的属性做响应式,请使用这两个API:Vue.set(target,propertyName/index,value) vm.$set(target,propertyName/index,value)
  3. 如何监测数组中的数据?
    • 通过包裹数组更新元素的方法实现,本质就是做了两件事:
      • 调用原生对应的方法对数组进行更新。
      • 重新解析模板,进而更新页面。
  4. 在Vue修改数组中的某个元素一定要用如下方法:
    • 使用这些API:push()、pop()、shift()、unshift()、splice()、sort()、reverse()
    • Vue.set() 或 vm.$set()
    • 数组全部替换,比如用filter方法赋值

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

<body>
        <div id="root">
                <h1>学生信息</h1>
                <button @click="student.age++">年龄+1岁</button> <br />
                <button @click="addSex">添加性别属性,默认值:男</button> <br />
                <button @click="student.sex = '未知' ">修改性别</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(this.student,'sex','男')
                                this.$set(this.student, 'sex', '男')
                        },
                        addFriend() {
                                //整个加入的对象都会被监测
                                this.student.friends.unshift({ name: 'jack', age: 70 })
                        },
                        updateFirstFriendName() {
                                this.student.friends[0].name = '张三'
                        },
                        addHobby() {
                                this.student.hobby.push('学习')
                        },
                        updateHobby() {
                                // this.student.hobby.splice(0,1,'开车')
                                // Vue.set(this.student.hobby,0,'开车')
                                this.$set(this.student.hobby, 0, '开车')
                        },
                        removeSmoke() {
                                // 直接替换整个数组也可以
                                this.student.hobby = this.student.hobby.filter((h) => {
                                        return h !== '抽烟'
                                })
                        }
                }
        })
</script>

收集表单数据

  1. 若:<input type="text"/>,则v-model收集的是value值,用户输入的就是value值。
  2. 若:<input type="radio"/>,则v-model收集的是value值,且要给标签配置value值。
  3. 若:<input type="checkbox"/>
    • 没有配置input的value属性,那么收集的就是checked(勾选 or 未勾选,是布尔值)
    • 配置input的value属性: v-model的初始值是非数组,那么收集的就是checked(勾选 or 未勾选,是布尔值)。v-model的初始值是数组,那么收集的的就是value组成的数组

备注:v-model的三个修饰符: lazy:失去焦点再收集数据 number:输入字符串转为有效的数字 trim:输入首尾空格过滤

<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="male"><input type="radio" name="sex" v-model="userInfo.sex" value="female"> <br /><br />
                爱好:
                学习<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>

<script type="text/javascript">
	Vue.config.productionTip = false

	new Vue({
		el: '#root',
		data: {
			userInfo: {
				account: '',
				password: '',
				age: 18,
				sex: 'female',
				hobby: [],
				city: 'beijing',
				other: '',
				agree: ''
			}
		},
		methods: {
			demo() {
				console.log(JSON.stringify(this.userInfo))
			}
		}
	})
</script>

过滤器

  1. 定义:对要显示的数据进行特定格式化后再显示(适用于一些简单逻辑的处理)。
  2. 语法:注册过滤器:Vue.filter(name,callback)(全局)或 new Vue{filters:{}}(局部,换了Vue实例就不能用)。使用过滤器:{{ xxx | 过滤器名}}v-bind:属性 = "xxx | 过滤器名"

备注: 过滤器也可以接收额外参数、多个过滤器也可以串联。并没有改变原本的数据, 是产生新的对应的数据

<body>
	<div id="root">
		<h2>显示格式化后的时间</h2>
		<!-- 过滤器实现 -->
		<h3>现在是:{{time | timeFormater}}</h3>
		<!-- 默认传参数是time,timeFormater('YYYY_MM_DD')实际上的参数是time和'YYYY_MM_DD' -->
		<h3>现在是:{{time | timeFormater('YYYY_MM_DD') | mySlice}}</h3>
		<h3 :x="msg | mySlice">aaa</h3>
	</div>
	<div id="root2">
		<h2>{{msg | mySlice}}</h2>
	</div>
</body>
<script type="text/javascript">
	Vue.config.productionTip = false
	//全局过滤器
	Vue.filter('mySlice',function(value){
		return value.slice(0,4)
	})
	
	new Vue({
		el:'#root',
		data:{
			time:1621561377603, //时间戳
			msg:'你好'
		},
		//局部过滤器
		filters:{
			timeFormater(value,str='YYYY年MM月DD日 HH:mm:ss'){
				// console.log('@',value)
				return dayjs(value).format(str)
			}
		}
	})
	new Vue({
		el:'#root2',
		data:{
			msg:'hello!'
		}
	})
</script>