Vue3【1.v-if 和 v-show 、2.动态组件、 3.网页的渲染 、4.v-for】

文章目录

    • 1.v-if 和 v-show
    • 2.动态组件
    • 3.网页的渲染
    • 4.v-for
      • 4.1 v-for 与对象
      • 4.2 在 v-for 里使用范围值
      • 4.3 v-for 与 v-if
      • 4.4 通过 key 管理状态
    • 4.5 组件上使用 v-for


1.v-if 和 v-show

  • v-show 可以根据值来决定元素是否显示(通过display来切换元素的显示状态)

  • v-if 可以根据表达式的值来决定是否显示元素(会直接将元素删除)

  • v-show通过css来切换组件的显示与否,切换时不会涉及到组件的重新渲染切换的性能比较高。
    但是初始化时,需要对所有组件进行初始化(即使组件暂时不显示)
    所以它的初始化的性能要差一些!

  • v-if通过删除添加元素的方式来切换元素的显示,切换时反复的渲染组件,切换的性能比较差。

    • v-if只会初始化需要用到的组件,所以它的初始化性能比较好
    • v-if可以和 v-else-if 和 v-else结合使用
    • v-if可以配合template使用
<script setup>
import { ref } from "vue"

const isShow = ref(true)
script>
<template>
    <h1>App组件h1>
    <button @click="isShow = !isShow">切换button>

    
    

    <template v-if="isShow">
        <h2>我是一个h2h2>
        <h3>我是h3h3>
    template>
template>

2.动态组件

component 是一个动态组件

  • component最终以什么标签呈现由is属性决定
<script setup>
import { ref } from "vue"
import A from "./components/A.vue"
import B from "./components/B.vue"

const isShow = ref(true)
script>
<template>
    
    <button @click="isShow = !isShow">切换button>
    <component :is="isShow ? A : B">component>
template>

3.网页的渲染

  • 浏览器在渲染页面时,做了那些事:

    1. 加载页面的html和css(源码)
    2. html转换为DOM,css转换为CSSOM
    3. 将DOM和CSSOM构建成一课渲染树
    4. 对渲染树进行reflow(回流、重排)(计算元素的位置)
    5. 对网页进行绘制repaint(重绘)
  • 渲染树(Render Tree)

    • 从根元素开始检查那些元素可见,以及他们的样式
    • 忽略那些不可见的元素(display:none)
  • 重排、回流

    • 计算渲染树中元素的大小和位置
    • 当页面中的元素的大小或位置发生变化时,便会触发页面的重排(回流)
    • width、height、margin、font-size …
    • 注意:每次修改这类样式都会触发一次重排!所以如果分词修改多个样式会触发重排多次,而重排是非常耗费系统资源的操作(昂贵),重排次数过多后,会导致网页的显示性能变差,在开发时我们应该尽量的减少重排的次数
    • 在现代的前端框架中,这些东西都已经被框架优化过了!所以使用vue、react这些框架这些框架开发时,几乎不需要考虑这些问题,唯独需要注意的时,尽量减少在框架中直接操作DOM
  • 重绘

    • 绘制页面
    • 当页面发生变化时,浏览器就会对页面进行重新的绘制
  • 例子:

    DOCTYPE html>
    <html lang="zh">
        <head>
            <meta charset="UTF-8" />
            <meta http-equiv="X-UA-Compatible" content="IE=edge" />
            <meta name="viewport" content="width=device-width, initial-scale=1.0" />
            <title>Documenttitle>
            <style>
                .box1 {
                    width: 200px;
                    height: 200px;
                    background-color: orange;
                }
    
                .box2 {
                    background-color: tomato;
                }
    
                .box3 {
                    width: 300px;
                    height: 400px;
                    font-size: 20px;
                }
            style>
        head>
        <body>
            <button id="btn">点我一下button>
            <hr />
            <div id="box1" class="box1">div>
            <script>
                btn.onclick = () => {
                    // box1.classList.add("box2")
                    // 可以通过修改class来间接的影响样式,来减少重排的次数
    
                    //修改一次
                    // box1.style.width = "300px"
                    // box1.style.height = "400px"
                    // box1.style.fontSize = "20px"
                    // box1.classList.add("box3")
    
                    //修改两次 ,none和block修改,none之后不修改
                    // box1.style.display = "none"
                    // box1.style.width = "300px"
                    // box1.style.height = "400px"
                    // box1.style.fontSize = "20px"
                    // div.style.display = "block"
                }
            script>
        body>
    html>
    
    

4.v-for

我们可以使用 v-for 指令基于一个数组来渲染一个列表。v-for 指令的值需要使用 item in items 形式的特殊语法,其中 items 是源数据的数组,而 item 是迭代项的别名

const items = ref([{ message: 'Foo' }, { message: 'Bar' }])
data() {
  return {
    items: [{ message: 'Foo' }, { message: 'Bar' }]
  }
}
<li v-for="item in items">
  {{ item.message }}
li>

v-for 块中可以完整地访问父作用域内的属性和变量。v-for 也支持使用可选的第二个参数表示当前项的位置索引。

const parentMessage = ref('Parent')
const items = ref([{ message: 'Foo' }, { message: 'Bar' }])
data() {
  return {
    parentMessage: 'Parent',
    items: [{ message: 'Foo' }, { message: 'Bar' }]
  }
}
<li v-for="(item, index) in items">
  {{ parentMessage }} - {{ index }} - {{ item.message }}
li>

对于多层嵌套的 v-for,作用域的工作方式和函数的作用域很类似。每个 v-for 作用域都可以访问到父级作用域:

<li v-for="item in items">
  <span v-for="childItem in item.children">
    {{ item.message }} {{ childItem }}
  span>
li>

你也可以使用 of 作为分隔符来替代 in,这更接近 JavaScript 的迭代器语法:

<div v-for="item of items">div>

4.1 v-for 与对象

你也可以使用 v-for 来遍历一个对象的所有属性。遍历的顺序会基于对该对象调用 Object.keys() 的返回值来决定。

const myObject = reactive({
  title: 'How to do lists in Vue',
  author: 'Jane Doe',
  publishedAt: '2016-04-10'
})
<ul>
  <li v-for="value in myObject">
    {{ value }}
  li>
ul>

可以通过提供第二个参数表示属性名 (例如 key):

<li v-for="(value, key) in myObject">
  {{ key }}: {{ value }}
li>

第三个参数表示位置索引:

<li v-for="(value, key, index) in myObject">
  {{ index }}. {{ key }}: {{ value }}
li>
0.title: How to do lists in Vue
1.author: Jane Doe
2.publishedAt: 2016-04-10

4.2 在 v-for 里使用范围值

v-for 可以直接接受一个整数值。在这种用例中,会将该模板基于 1...n 的取值范围重复多次。

<span v-for="n in 10">{{ n }}span>

注意此处 n 的初值是从 1 开始而非 0

4.3 v-for 与 v-if

:::warning 注意
同时使用 v-ifv-for不推荐的,因为这样二者的优先级不明显。
:::

当它们同时存在于一个节点上时,v-ifv-for 的优先级更高。这意味着 v-if 的条件将无法访问到 v-for 作用域内定义的变量别名:


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

在外新包装一层