写点什么

uni-app 跨端开发 H5、小程序、IOS、Android(七):uni-app 渲染

用户头像
黑马腾云
关注
发布于: 2021 年 03 月 23 日
uni-app跨端开发H5、小程序、IOS、Android(七):uni-app渲染

上一篇:

uni-app 跨端开发 H5、小程序、IOS、Android(六):uni-app 事件绑定


大家好,我是黑马腾云。


这是一个原创系列连载文章,基于企业真实项目案例分享经验,带你快速入门 uni-app 开发!欢迎点击头像关注,避免迷路!


前文讲解了 uni-app 事件绑定,本文讨论下条件渲染和列表渲染。


条件渲染主要指令:v-if 和 v-show,列表渲染指令:v-for。


一、条件渲染


1、指令:v-if


v-if 指令用于条件性地渲染一块内容。这块内容只会在指令的表达式返回 truthy 值的时候被渲染。


在 JavaScript 中,truthy(真值)指的是在布尔值上下文中,转换后的值为真的值。

所有值都是真值,除非它们被定义为 假值(即除 false、0、""、null、undefined 和 NaN 以外皆为真值)。


示例:

<template>	<view>		<view v-if="show">能看到</view>	</view></template>
<script> export default { data() { return { show: true, //只有其值为:false、0、""、null、undefined 和 NaN为false,其它值都为ture //show: 10 //照样会显示 } }, onLoad() {}, methods: {} }</script>
<style>
</style>
复制代码


示例中定义变量 show,只有当值为:false、0、""、null、undefined 和 NaN 时才不会渲染,其它值都会渲染。


当然,v-if 中也支持三元运算

<template>	<view>		<view v-if="age>=18? true:false">已成年</view>	</view></template>
<script> export default { data() { return { age: 18, } }, onLoad() {}, methods: {} }</script>
<style>
</style>
复制代码


2、指令:v-else


v-if 与 v-else 组合使用

<template>	<view>		<view v-if="show">能看到</view>		<view v-else>看不到</view>	</view></template>
<script> export default { data() { return { show: false, } }, onLoad() {}, methods: {} }</script>
<style>
</style>
复制代码


示例中,根据变量 show 的值动态渲染不同的内容。


3、指令:v-else-if


类似于 v-else ,v-else-if 也必须紧跟在带 v-if 或者 v-else-if 的元素之后。

<template>	<view>		<view v-if="age<18">未成年</view>		<view v-else-if="age<=60">努力工作</view>		<view v-else-if="age<=120">安享晚年</view>		<view v-else>妖怪</view>	</view></template>
<script> export default { data() { return { age: 18, //未成年:小于18;努力工作:[18-60];安享晚年:(60-120];妖怪:120岁以上 } }, onLoad() {}, methods: {} }</script>
<style>
</style>
复制代码


示例中可以看到,可以包含多个 v-else-if 指令。


4、条件渲染分组


因为 v-if 是一个指令,所以必须将它添加到一个元素上。


但是如果想切换多个元素呢?此时可以把一个 template 元素当做不可见的包裹元素,并在上面使用 v-if。最终的渲染结果将不包含 template 元素。

<template>	<view>  <!--所有元素必须放在view包裹-->		<template v-if="show">  <!--不会渲染包裹对象,渲染内部的内容-->			<view>标题</view>			<view>内容:我的外层不会渲染</view>		</template>				<view v-if="show">  <!--会渲染出view,包裹里边的内容-->			<view>标题</view>			<view>内容:我的外层会渲染</view>		</view>	</view>
</template>
<script> export default { data() { return { show: true, } }, onLoad() {}, methods: {} }</script>
<style>
</style>
复制代码


示例所谓:<template>标签将不会渲染出来,读者自行拷贝代码运行侯,在浏览器中通过源码视图查看对比。


5、指令:v-show


v-show 是一个根据条件展示元素选项的指令 。用法大致和 v-if 一样:


<view v-show="show">显示</view>
复制代码


不同的是带有 v-show 的元素始终会被渲染并保留在 DOM 中。


v-show 只是简单地切换元素的 CSS 属性的 display 。


注意,v-show 不支持 template 元素,也不支持 v-else。


6、v-if 与 v-show 区别


示例:

<template>	<view>		<view v-if="show">v-if</view>		<view v-show="show">v-show</view>	</view>
</template>
<script> export default { data() { return { show: false, } }, onLoad() {}, methods: {} }</script>
<style>
</style>
复制代码


以上示例,因为 show 为 false,所以页面上不会有显示。


但是打开浏览器查看源文件,发现 v-show 对应的 view 渲染出来了,只是 css 对应的 display:none 没有显示而已,实际 dom 已经渲染了。


v-if 是“真正”的条件渲染,因为它会确保在切换过程中条件块内的事件监听器和子组件适当地被销毁和重建。


v-if 也是惰性的:如果在初始渲染时条件为假,则什么也不做,直到条件第一次变为真时,才会开始渲染条件块。


相比之下,v-show 就简单得多,不管初始条件是什么,元素总是会被渲染,并且只是简单地基于 CSS 进行切换,来控制元素的显示和隐藏。


根据应用场景选择 v-if 有更高的切换开销,如果在运行时条件很少改变,则使用 v-if 较好。v-show 有更高的初始渲染开销。如果需要非常频繁地切换,则使用 v-show 较好。


注意:


不推荐同时使用 v-if 和 v-for。​ 当 v-if 与 v-for 一起使用时,v-for 具有比 v-if 更高的优先级。


二、列表渲染


列表渲染采用指令:v-for


1、在数组里使用 v-for


v-for 指令可以实现基于一个数组来渲染一个列表。


v-for 指令需要使用 item in items 形式的特殊语法,其中 items 是源数据数组,而 item 则是被迭代的数组元素的别名。


第一个参数 item 则是被迭代的数组元素的别名。第二个参数,即当前项的索引 index ,是可选的。


基本示例如下:

<template>	<view>		<view v-for="(friend,index) in friends">			{{index}}--{{friend}}		</view>	</view></template><script>	export default {		data() {			return {				friends: ["lucy","lily"] //朋友数组			}		}	}</script>
复制代码


示例中 friends 是一个字符串数组,通过 v-for 遍历并输出数组中的朋友。


当然第二个参数 index 索引是可以选的,所以在一般情况下也可以不写:

<template>	<view>		<view v-for="friend in friends">			{{friend}}		</view>	</view></template><script>	export default {		data() {			return {				friends: ["lucy","lily"] //朋友数组			}		}	}</script>
复制代码


2、在 v-for 里使用对象


你也可以用 v-for 来遍历一个对象的 property。 第一个参数 value 是被迭代的数组元素的别名。 第二个参数为 property 名称 (也就是键名)。 第三个参数作为索引。

<template>	<view>		<view v-for="(value, name, index) in book">			{{ index }}. {{ name }}: {{ value }}		</view>	</view></template><script>	export default {		data() {			return {				book: {					title: 'mysql删除到跑路',					author: 'heima',					publisheAt: "2021-1-1"				}			}		}	}</script>
复制代码


注意,如果要缺省参数,那么参数只能从右边开始减少。


前边演示的数组元素也可以是对象,如下实例:

<template>	<view>		<view v-for="friend in friends">			{{friend.name}}--{{friend.age}}		</view>	</view></template><script>	export default {		data() {			return {				friends: [					{						name:"lucy",						age:"18"					},{						name:"lily",						age:"18"					}					] 			}		}	}</script>
复制代码


注意,在一些特殊情况下(比如多重循环),如果不写 index,将导致一些意想不到的 bug,见第 6 点。


3、列表渲染分组


类似于 v-if,你也可以利用带有 v-for 的 template 来循环渲染一段包含多个元素的内容。比如:

<template>	<view>		<template v-for="(friend,index) in friends">			<view>{{friend.name}}</view>			<view>{{friend.age}}</view>		</template>	</view></template><script>	export default {		data() {			return {				friends: [{					name: "lucy",					age: "18"				}, {					name: "lily",					age: "18"				}]			}		}	}</script>
复制代码


4、在组件上使用 v-for


在自定义组件上,你可以像在任何普通元素上一样使用 v-for 。


 <my-component v-for="item in items" :key="item.id"></my-component>
复制代码

当在组件上使用 v-for 时,key 是必须的。


5、v-for 中的 key


当 Vue 正在更新使用 v-for 渲染的元素列表时,它默认使用“就地更新”的策略。如果数据项的顺序被改变,Vue 将不会移动 DOM 元素来匹配数据项的顺序,而是就地更新每个元素,并且确保它们在每个索引位置正确渲染。


如果列表中项目的位置会动态改变或者有新的项目添加到列表中,并且希望列表中的项目保持自己的特征和状态(如 input 中的输入内容,switch 的选中状态),需要使用 :key 来指定列表中项目的唯一的标识符。


:key 的值以两种形式提供


使用 v-for 循环 array 中 item 的某个 property,该 property 的值需要是列表中唯一的字符串或数字,且不能动态改变。​ 使用 v-for 循环中 item 本身,这时需要 item 本身是一个唯一的字符串或者数字

<template>	<view>		<!-- array 中 item 的某个 property -->		<view v-for="(item,index) in objectArray" :key="item.id">			{{index +':'+ item.name}}		</view>		<!-- item 本身是一个唯一的字符串或者数字时,可以使用 item 本身 -->		<view v-for="(item,index) in stringArray" :key="item">			{{index +':'+ item}}		</view>	</view></template><script>	export default {		data() {			return {				objectArray: [{					id: 0,					name: 'li ming'				}, {					id: 1,					name: 'wang peng'				}],				stringArray: ['a', 'b', 'c']			}		}	}</script>s
复制代码


当数据改变触发渲染层重新渲染的时候,会校正带有 key 的组件,框架会确保他们被重新排序,而不是重新创建,以确保使组件保持自身的状态,并且提高列表渲染时的效率。


如不提供 :key,会报一个 warning, 如果明确知道该列表是静态,或者不必关注其顺序,可以选择忽略。

警告内容为:component lists rendered with v-for should have explicit keys.


当要关注顺序的情况下,如果不提供 key,看看会发生什么?

<template>	<view>		<view v-for="friend in friends" ><!--:key="friend.id"-->			<checkbox>{{friend.name}}</checkbox>		</view>		<button @click="addSkill">新交朋友</button>	</view></template><script>	export default {		data() {			return {				friends: [{					id: 0,					name: "lucy",				},{					id: 1,					name: "lili",				},{					id: 2,					name: "lisa",				} ]			}		},		methods: {			addSkill() {				var arr=this.friends;				var newId=arr.length+1;				var newFriend={					id:newId,					name:"新朋友"+newId				}				// this.friends.push(newFriend); //在数组尾部新加项				this.friends.unshift(newFriend); //在数组头部添加项			}		}	}</script>
复制代码


上边示例很简单,页面维护了一个朋友列表,点击按钮将向按钮头部添加新朋友。


看看运行后的效果:



看到问题了吧?


初始时选择的好朋友是 lisa,但是每当新认识一个人的时候都会改变我之前选择的值。


这是不对的,无论添加多少人,都不应该改变用户原来的选择。


怎么解决呢?相信你理解了 key 的作用,一定能知道怎么修复,如果还不清楚,欢迎下边留言区讨论。


6、v-for 中的索引 index


在以前的版本中多重循环需要显示指定不同的索引 index,如果没指定,在浏览器浏览没问题,但是在编译小程序是会报错。

<template>	<view>		<view v-for="friend in friends" >			<view>{{friend.name}}--{{friend.age}}--</view>			<view>			<block v-for="skill in friend.skill" > 				{{skill}},			</block>			</view>		</view>	</view></template><script>	export default {		data() {			return {				friends: [					{						name:"lucy",						age:"18",						skill:["c++","java"]					},{						name:"lily",						age:"18",						skill:["uni-app","react"]					}					] 			}		}	}</script>
复制代码


笔者目前使用的 HBuilderX3.0.7 版本已经不报错了,应该是工具已经做了修复。但是在微信开发者工具可以看到仍然有警告信息,建议加上:key 提高渲染性能。


实际开发中建议写的规范一些,把 index 和 key 都加上

<template>	<view>		<view v-for="(friend,index) in friends" :key=friend.id>			<view>{{friend.name}}--{{friend.age}}--</view>			<view>			<block v-for="(skill,subindex) in friend.skill" :key=skill> 				{{skill}},			</block>			</view>		</view>	</view></template><script>	export default {		data() {			return {				friends: [					{						id:0,						name:"lucy",						age:"18",						skill:["c++","java"]					},{						id:1,						name:"lily",						age:"18",						skill:["uni-app","react"]					}					] 			}		}	}</script>
复制代码


下一篇文章一起来研究下 uni-app 页面及应用的生命周期,欢迎持续关注。


讨论时间:


1、以上示例中使用了 block,没有用 view。那么 view 和 block 在渲染输出时有什么区别?


view 每次循环都会渲染一个 uni-vew 包裹元素,会换行。block 则无任何包裹元素输出。


2、第 5 点中的顺序变化问题如何解决?


只需要添加:key="friend.id"


作者介绍:


黑马腾云,码农、创业者、终身学习者!


乐于分享技术、创业、人生思考。关注我,一起为人生喝彩!


上一篇:

uni-app 跨端开发 H5、小程序、IOS、Android(六):uni-app 事件绑定


发布于: 2021 年 03 月 23 日阅读数: 23
用户头像

黑马腾云

关注

程序员、终身学习者、创业者。 2020.06.22 加入

“自学帮”公众号主。

评论

发布
暂无评论
uni-app跨端开发H5、小程序、IOS、Android(七):uni-app渲染