Vue3--条件与循环

Vue主要通过v-if和v-for两个指令来控制DOM元素的生成、移除和批量展示。

v-if

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

<h1 v-if="awesome">Vue is awesome!</h1>
//当awesome是假值时,h1标签将被移除

用 v-else 添加“else 块”:

<h1 v-if="awesome">Vue is awesome!</h1>
<h1 v-else>Oh no </h1>

集合 template

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

那么如果想用一个v-if同时控制多个元素呢?

可以用一个 元素当做外部包裹元素,将多个需要被控制的元素包裹起来,并在上面使用 v-if。

我们知道,HTML5版本中带来的标签,实际上是一个不会被渲染的标签,所以最终的结果将不包含 元素。

<template v-if="ok"><h1>Title</h1><p>Paragraph 1</p><p>Paragraph 2</p>
</template>

v-else

使用 v-else 指令来表示 v-if 的“else 块”:

<div v-if="Math.random() > 0.5">Now you see me
</div>
<div v-else>Now you don't
</div>

v-else 元素必须紧跟在带 v-if 或者 v-else-if 的元素的后面,否则它将不会被识别。

v-else-if

v-else-if,顾名思义,充当 v-if 的“else-if 块”,并且可以连续使用:

<div v-if="type === 'A'">A
</div>
<div v-else-if="type === 'B'">B
</div>
<div v-else-if="type === 'C'">C
</div>
<div v-else>Not A/B/C
</div>

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

v-show

除了v-if,还有一个用于条件性展示元素的指令: v-show 。用法大致一样:

<h1 v-show="ok">Hello!</h1>

不同的是带有 v-show 的元素始终会被渲染并保留在 DOM 中。v-show 只是简单地切换元素的 CSS属性display。

v-if 与v-show的区别

  1. v-if 是“真正”的条件渲染,因为它会确保在切换过程中,条件块内的事件监听器和子组件恰当地被销毁和重建。(通俗地说,就是DOM会被真正地创建和删除)
  2. v-if 也是惰性的:如果在初始渲染时条件为假,则什么也不做——直到条件第一次变为真时,才会开始渲染条件块。(也就是说,如果一开始为假,v-if根本不创建DOM)
  3. v-show 不管初始条件是什么,元素总是会被渲染,并且只是简单地基于 CSS 进行切换。(不管开始是真是假,DOM都会被创建,只是有可能隐藏起来而已)
  4. 一般来说,v-if 有更高的切换开销,而 v-show 有更高的初始渲染开销。因此,如果需要非常频繁地切换,则使用 v-show 较好;如果在运行时条件很少改变,则使用 v-if 较好。
  5. 另外,v-show 不支持 元素,也不支持 v-else。

v-for

  v-for用于将一个数据数组循环渲染成一组同样的DOM元素。循环的是数组,生成的是HTML元素。

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

<ulid="list"><liv-for="item in items">{{item.message}}</li>
</ul>
 const app = Vue.createApp({data(){return {items: [{message: "foo"},{message: "bar"},]}}})app.mount("#list")

在 v-for 块中,我们可以访问所有父作用域的属性。

v-for 还支持一个可选的第二个参数,即当前元素项的索引。

<ulid="list"><liv-for="(item, index) in items">{{parentMessage}}-{{index}}-{{item.message}}</li>
</ul>
  const app = Vue.createApp({data(){return {parentMessage: 'Parent',items: [{message: "foo"},{message: 'bar'},]}}
})app.mount("#list")

在 v-for 里使用对象

代码实例

<ul id="app"><liv-for="value in MyObject">{{value}}</li><p>-------------------------------------------------------------</p><liv-for="(value, key) in MyObject">{{key}}: {{value}}</li><p>-------------------------------------------------------------</p><liv-for="(value, key, index) in MyObject">{{index}} - {{key}} : {{value}}</li></ul>
const app = Vue.createApp({data(){return {MyObject: {title: "How to do lists in Vue",author: "Jane",publishedAt: "2013-10-2"}}}
})app.mount("#app")

渲染效果
在这里插入图片描述

维护列表各项的统一性

   当 Vue 准备更新一个使用 v-for 指令渲染出来的的元素列表时,它默认使用“就地更新”的策略。
   也就是说如果列表项的顺序被改变,Vue 却不会移动 DOM 元素来匹配新的顺序,而是就地更新每个元素,并且确保它们在每个索引位置正确渲染。
  这个默认的策略是出于高效刷新DOM的目的,但只适用于不依赖子组件状态或临时 DOM 状态 (例如:表单输入值) 的列表渲染输出(也就是列表各项没有什么差别)。
  但大多数情况下,我们还是要区别列表中的各个项的,不能直接复用。

为了给 Vue 一个提示,以便它能跟踪每个节点的身份,从而重用和重新排序现有元素,我们可以为每项提供一个唯一 的key 属性(要绑定):

<div v-for="item in items" :key="item.id"><!-- content -->
</div>

  实际上,Vue官方将唯一状态设定为默认状态不香吗?高效刷新固然重要,但列表项几乎都是不同的,需要id唯一识别。

  key属性是 Vue 识别节点的一个通用机制,并不仅仅用于 v-for ,它还具有其它用途。
  不要使用,对象或数组之类的可变数据类型,作为 v-for 的 key,请用字符串或数值之类的不可变类型。

数组更新检测

v-for不仅仅是用于循环生成列表,同时监测数据来源的变化。如果数据数据发生了变化,列表项的内容也会跟着变化。

变更方法

如果你对数组型数据执行了下面的方法,使用v-for生成的列表项也会跟着变化:

  1. puhs()
  2. pop()
  3. shift()
  4. unshift()
  5. splice()
  6. sort()
  7. reverse()

  我们可以打开控制台,然后对前面例子中的 items 数组尝试调用变更方法。比如 example1.items.push({ message: ‘Baz’ }),可以同步观测到视图DOM元素也发生了变化。

替换数组

  上面的变更方法,顾名思义,是会变更调用了这些方法的原始数组。
  与之相对,数组这种JS数据类型,也有非变更方法,例如 filter()、concat() 和 slice()。它们不会变更原始数组,而总是返回一个新数组。
  当使用非变更方法时,可以用新数组替换旧数组:

example1.items = example1.items.filter(item => item.message.match(/Foo/))

  你可能认为这将导致 Vue 丢弃现有 DOM 并重新渲染整个列表。幸运的是,事实并非如此。Vue 为了使得 DOM 元素得到最大范围的重用而实现了一些智能的启发式方法,所以用一个含有相同元素的数组去替换原来的数组是非常高效的操作。

显示过滤/排序后的结果

  有时,我们想要显示一个数组经过过滤或排序后的结果,同时不实际变更或重置原始数据。
  在这种情况下,可以创建一个计算属性,来返回过滤或排序后的数组。

代码实例:

<divid="app"><li v-for="n in evenNumbers" :key="n">{{ n }}</li>
</div>
const app = Vue.createApp({data(){return {numbers: [1, 2, 3, 4, 5, 6]}},computed: {evenNumbers(){return this.numbers.filter(number=>number%2 === 0)}}
})app.mount("#app")

渲染效果
在这里插入图片描述

在计算属性不适用的情况下 (例如,在嵌套 v-for 循环中),可以使用methods方法:

<divid="app"><ulv-for="numbers in sets"><liv-for="n in even(numbers)":key="n">{{n}}</li></ul>
</div>
 const app = Vue.createApp({data(){return {sets: [[1, 2, 3, 4, 5],[6, 7, 8, 9, 10],]}},methods: {even(numbers){return numbers.filter(number => number % 2 === 0)}}})app.mount("#app")

在这里插入图片描述

在 v-for 里使用值的范围

作为语法糖,v-for 也可以接受整数。在这种情况下,它会把模板重复对应次数。

<div id="app" class="demo"><li v-for="n in 10" :key="n">{{ n }} </li>
</div>
const app = Vue.createApp({})app.mount("#app")

渲染效果
在这里插入图片描述
注意: 此处从 1 开始 并且包括 10 !!!

在 <template> 中使用 v-for

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

<divid="app"><ul><template v-for="item in items" :key="item.msg"><li>{{ item.msg }}</li></template></ul>
</div>
const app = Vue.createApp({data(){return {items: [{msg: "Hello World1"},{msg: "Hello World2"},{msg: "Hello World3"},{msg: "Hello World4"},{msg: "Hello World5"},]}}
})app.mount("#app")

渲染效果
在这里插入图片描述

v-for 与 v-if 一同使用

注意Vue官方不推荐在同一元素上同时使用 v-if 和 v-for.
当它们处于同一节点,v-if 的优先级比 v-for 更高,这意味着 v-if 将没有权限访问 v-for 里的变量:

<!-- 下面的代码将抛出一个异常,因为v-if无法访问todo变量 --><li v-for="todo in todos" v-if="!todo.isComplete">{{ todo.name }}
</li>

可以把 v-for 移动到 <template> 标签中来修改这个bug:

<template v-for="todo in todos" :key="todo.name"><li v-if="!todo.isComplete">{{ todo.name }}</li>
</template>

在组件上使用 v-for

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

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

然而,默认情况下,Vue不会自动把数据传递到组件里,因为组件有自己独立的作用域.
为了把迭代数据传递到组件里,我们需要在组件中声明并使用 props:

<my-componentv-for="(item, index) in items":item="item":index="index":key="item.id"
></my-component>

不自动将 item 注入到组件里的原因是,这会使得组件与 v-for 的运作紧密耦合。明确组件数据的来源能够使组件在其他场合重复使用。

下面是一个简单的 todo 列表的完整例子:

<divid="app"><formv-on:submit.prevent="addNewToDo"><labelfor="new-todo">add a todo</label><inputv-model="newToDoText"id="new-todo"placeholder="E.g. Feed the cat"><button>Add</button></form><ul><todo-itemv-for="(todo, index) in todos":key="todo.id":title="todo.title"@remove="todos.splice(index, 1)"></todo-item></ul>
</div>
const app = Vue.createApp({data(){return {newToDoText: '',todos: [{id: 1, title: 'Hello World 1'},{id: 2, title: 'Hello World 2'},{id: 3, title: 'Hello World 3'},{id: 4, title: 'Hello World 4'},{id: 5, title: 'Hello World 5'},],nextTodoId: 5,}},methods: {addNewToDo(){this.todos.push({id: this.nextTodoId++,title: this.newToDoText})this.newToDoText = ''}},})app.component('todo-item', {template: `<li>{{ title }}<button @click="$emit('remove')">Remove</button></li>`,props: ['title'],emits: ['remove']})app.mount("#app")

渲染效果

在这里插入图片描述
这里可以在输入框中输入内容, 待办内容可以添加到下面, 可以通过 Remove 按钮来移除内容.

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/543278.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

01背包 与 emo题目背景(周超人的遗憾) 的爱恨情仇

本题背景有意思&#xff0c;大家当乐子看&#xff0c;目前没有找到题目原题&#xff0c;也没有写过完全是01背包模板的题目&#xff0c;该篇文章大家注意其01背包一维写法的模板就好&#xff0c;注意各个关键点 ✨欢迎来到脑子不好的小菜鸟的文章✨ &#x1f388;创作不易&…

算力,承载AI无限可能

年后不久&#xff0c;美国人工智能研究公司OpenAI推出的Sora模型引起了广泛关注&#xff0c;对于人工智能发展之快的感慨还未过去&#xff0c;3月初&#xff0c;Anthropic丢出一颗“王炸”Claude3&#xff0c;其中Claude 3 Opus宣称在基准测试中优于OpenAI的GPT-4和Google的Gem…

MyBatis Plus(代码生成器)

一、安装 安装MyBatisPlus插件 二、配置 1、 在生成代码之前首先需要配置所要连接的数据库 下面所对应的分别是&#xff1a; 所要连接的数据库 数据库驱动 用户名 密码 2、 点击Other->Code Generator 开始配置所需选项

VMWare虚拟机使用openmediavault搭建NAS服务器完整步聚

下载: gopenmediavault - The open network attached storage solution 下载好openmediavault的ISO镜像后,打开虚拟机并安装 系统类型选择Debian 启动虚拟机并安装openmediavault 选择中文 地区选中国 键盘配置选汉语 开始安装 配置网络信息 配置root密码 确认密码 系统安装中…

【算法刷题 | 栈】3.16(有效的括号、删除字符串中的所有相邻重复项、逆波兰表达式求值)

文章目录 1.有效的括号1.1题目1.2解法&#xff1a;栈 2.删除字符串中的所有相邻重复项2.1题目2.2解法&#xff1a;栈 3.逆波兰表达式求值3.1题目3.2解法&#xff1a;栈 1.有效的括号 1.1题目 给定一个只包括 (&#xff0c;)&#xff0c;{&#xff0c;}&#xff0c;[&#xff…

每日学习笔记:C++ STL 的map、multimap

定义 特点 操作函数 意思就是&#xff0c;使用tuple中的元素来初始化pair&#xff0c;即string(“hello”)、complex(3.4,7.8) 元素的移除讨论

jS 正则

概念 正则表达式是用于匹配字符串中字符组合的模式。在 JavaScript中&#xff0c;正则表达式也是对象。这些模式被用于 RegExp 的 exec 和 test 方法, 以及 String 的 match、matchAll、replace、search 和 split 方法。 创建正则表达式 两种方法&#xff1a;字面量方式、构造…

HTML5+CSS3+JS小实例:全屏范围滑块

实例:全屏范围滑块 技术栈:HTML+CSS+JS 效果: 源码: 【HTML】 <!DOCTYPE html> <html lang="zh-CN"> <head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale…

PHP 生成图片

1.先确认是否有GD库 echo phpinfo(); // 创建一个真彩色图像 $image imagecreatetruecolor(120, 50);// 分配颜色 $bgColor imagecolorallocate($image, 255, 255, 255); // 白色背景 $textColor imagecolorallocate($image, 230, 230, 230); // 黑色文字// 填充背景 image…

【AcWing】蓝桥杯集训每日一题Day5|归并排序|离散化|二分|逆序数对|505.火柴排队(C++)

火柴排队 505. 火柴排队 - AcWing题库难度&#xff1a;中等时/空限制&#xff1a;1s / 128MB总通过数&#xff1a;2058总尝试数&#xff1a;4484来源&#xff1a;NOIP2013提高组算法标签贪心离散化树状数组归并排序 题目内容 涵涵有两盒火柴&#xff0c;每盒装有 n 根火柴…

57、服务攻防——应用协议RsyncSSHRDP漏洞批扫口令猜解

文章目录 口令猜解——Hydra-FTP&RDP&SSH配置不当——未授权访问—Rsync文件备份协议漏洞——应用软件-FTP&Proftpd搭建 口令猜解——Hydra-FTP&RDP&SSH FTP&#xff1a;文本传输协议&#xff0c;端口21&#xff1b;RDP&#xff1a;windows上远程终端协议…

Docker 中 MySQL 的部署与管理

目录 一、Docker 中部署 MySQL1.1 部署 MySQL1.2 进入容器并创建数据库1.3 Navicat 可视化工具连接 二、可能存在的问题2.1 1130 - Host ‘172.17.0.1‘ is not allowed to connect to this MySQL server 参考资料 一、Docker 中部署 MySQL 1.1 部署 MySQL 首先&#xff0c;从…