Vue基础集合

Vue

1、渐进式框架

Vue是一个框架,也是一个生态。其功能覆盖了大部分前端开发需求

  • 无需构建步骤,渐进式增强静态的HTML
  • 在任何页面中作为Web Components嵌入
  • 单页应用(SPA)
  • 渲染
  • jamstack\静态站点生成(SSG)
  • 开发桌面端、移动端、webGL,甚至是命令行终端的页面

2、Vue API 风格

Vue的组件可以按照两种不同的风格书写:选项式API(Vue2写法)和组合式API(Vue3写法)

大部分的核心概念在这两种风格之间都是相通的。

选项式API
import { createApp } from 'vue'

createApp({
  data() {
    return {
      count: 0
    }
  }
}).mount('#app')
组合式API
import { createApp, ref } from 'vue'

createApp({
  setup() {
    return {
      count: ref(0)
    }
  }
}).mount('#app')
选择哪一种书写?
在生产项目中:
  • 当你不需要使用构建工具,或者打算主要在低复杂度的场景下使用Vue,采用选项式API
  • 当你打算用Vue构建完整的单页应用,推荐采用组合式API+单文件组件

3、Vue开发前的准备

构建工具让我们能使用Vue单文件组件(SFC)。Vue官方的构建流程是基于Vite的,一个现代轻量的构建工具

安装15.0或更高版本的Node.js

创建Vue项目
npm init vue@latest
# 在cmd下运行

这一指令会安装和执行create-vue,它是Vue官方的项目脚本架工具。你会开看到一些可选功能提示

Need to install the following packages:
  create-vue@3.7.3
Ok to proceed? (y) y

Vue.js - The Progressive JavaScript Framework

√ Project name: ... vue-1  #项目名称不要大写
√ Add TypeScript? ... No / Yes
√ Add JSX Support? ... No / Yes
√ Add Vue Router for Single Page Application development? ... No / Yes
√ Add Pinia for state management? ... No / Yes
√ Add Vitest for Unit Testing? ... No / Yes
√ Add an End-to-End Testing Solution? » No
√ Add ESLint for code quality? ... No / Yes

创建后按照提示安装依赖并打开服务器

cd <your-project-name>
npm install
npm run dev
问:创建Vue项目的命令是什么?
  • npm create-vue project
  • npm create vue project
  • npm create-react project
  • npm init vue@latest

4、模板语法

Vue使用一种基于HTML的模板语法,使我们能够声明式的将其组件实例的数据绑定到出现的DOM上。所有的Vue模板都是语法层面合法的HTML,可以被符合规范的浏览器和HTML解析器解析。

文本插值

最基本的数据绑定形式使文本插值,它使用的是“Mustache”语法(双大括号)

<span>Message: {{ msg }}</span>
使用JS表达式

每个绑定仅支持单一表达式,也是一段能被求值的JS代码。一个简单的判断方法是是否可以合法的写在return后面

{{ number + 1 }}

{{ ok ? 'YES' : 'NO' }}

{{ message.split('').reverse().join('') }}

<div :id="`list-${id}`"></div>

因此,下面的例子都是无效的:

<!-- 这是一个语句,而非表达式 -->
{{ var a = 1 }}

<!-- 条件控制也不支持,请使用三元表达式 -->
{{ if (ok) { return message } }}
原始 HTML

双大括号会将数据解释为纯文本,而不是 HTML。若想插入 HTML,你需要使用 v-html 指令

<p>Using text interpolation: {{ rawHtml }}</p>
<p>Using v-html directive: <span v-html="rawHtml"></span></p>

5、属性绑定

双大括号不能在 HTML attributes 中使用。想要响应式地绑定一个 attribute,应该使用 v-bind 指令

<div v-bind:id="dynamicId"></div>

v-bind 指令指示 Vue 将元素的 id attribute 与组件的 dynamicId 属性保持一致。如果绑定的值是 null 或者 undefined,那么该 attribute 将会从渲染的元素上移除。

简写

因为 v-bind 非常常用,我们提供了特定的简写语法:

<div :id="dynamicId"></div>
动态绑定多个值
<script>
export default{
  data(){
    return{
      msg:"active",
      style:"app"
    }
  }
}
</script>

<template>
  <div :class="msg" :id="style">测试</div>
</template>
<style>
  #app{
    color: red;
  }
</style>

6、条件渲染

指令是带有 v- 前缀的特殊 attribute。Vue 提供了许多内置指令,包括上面我们所介绍的 v-bindv-html

指令 attribute 的期望值为一个 JavaScript 表达式 (除了少数几个例外,即之后要讨论到的 v-forv-onv-slot)。一个指令的任务是在其表达式的值变化时响应式地更新 DOM。以 v-if 为例:

<script>
export default{
    data(){
        return{
            msg:false
        }
    }
}
</script>
<template>
    <div v-if="msg">你能看见我吗</div>
    <div v-else>那你看看我</div>
</template>
v-ifv-show的区别

v-if也是惰性的:如果在初次渲染条件值为false,则不会做任何事。条件区只有当条件首次变为true时才被渲染。

相比之下,v-show简单许多,元素无论初始条件如何,始终会被渲染,只有CSSdisplay属性会被切换。

总的来说,v-if有更高的切换开销,而v-show有更高的初始渲染开销。因此,如果需要频繁切换,则使用v-show较好;如果在运行时绑定条件很少改变,则v-if会更合适

7、列表渲染

我们可以使用v-for指令基于一个数组来渲染一个列表。v-for指令的值需要使用item in items形式来遍历。

<script>
export default{
    data(){
        return{
            names:["小丁","小海","小段"]
        }
    }
}
</script>
<template>
<p v-for="i in names">{{ i }}</p>
</template>

v-for支持使用可选的第二个参数标识当前项的位置索引

<p v-for="(i,index) in names">{{ i }}-{{ index }} </p>

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

<p v-for="(i,index) of names">{{ i }}-{{ index }} </p>

v-for支持使用可选的第二个参数标识当前项的名称

<p v-for="(i,key,index) in names">{{ i }}-{{ key }}-{{ index }} </p>
遍历对象的时候名称要不一样

遍历对象的时候名称要不一样,如果names:{name:"小丁",name:"小海",name:"小段"}只会输出一个小段

export default{
    data(){
        return{
            names:{name:"小丁",age:"小海",id:"小段"}
        }
    }
}
通过key管理状态

Vue默认按照“就地更新”的策略来更新通过v-for渲染的元素列表。当数据项的顺序改变时,Vue不会随之移动DOM元素的顺序,而是就地更新每一个元素,确保它们在原本指定的索引位置上渲染。

为了给Vue一个提示,以便他可以跟踪每一个节点的标识,从而重用和重新排序现有的元素,你需要为每一个元素对应的块提供一个唯一的key

<p v-for="(i,index) of names" :key="index">{{ i }}</p>

key在这里是一个提供v-bind绑定的特殊attribute

推荐在任何可行的时候为v-for提供一个keyattribute

key绑定的值期望是一个基础类型的值,例如字符串或number类型

数组变化侦测
变更方法

Vue能够侦测响应式数组的变更方法,并在它们被调用时触发相关的更新。这些变更方法包括:

  • push()
  • pop()
  • shift()
  • unshift()
  • splice()
  • sort()
  • reverse()
替换一个数组

变更方法,就是会对调用它们的原数组进行变更。相对的,也有一些不可变方法,如filter()concat()slice(),这些都不会更改原数组,而总是返回一个新数组。

<template>
    <button @click="add()">add</button>
<p v-for="(i,index) of num" :key="index">{{ i }}</p>
</template>
<script>
export default{
    data(){
        return{
            num:[1,2,3,4]
        }
    },
    methods:{
        add(){
            //修改原数组
            //this.num.push("5")
            //不修改原数组,需要重新赋值
            this.num = this.num.concat(["6"])
        }
    }
}
</script>

8、事件处理

我们可以使用v-on指令(简写为@)来监听DOM事件,并在事件触发时执行对应的JS。用法:v-on:click="methodName"@click="handler"

事件处理器的值可以是

  • 内联事件处理器:事件被触发时执行的内联JS语句(与onclick类似)
  • 方法事件处理器:一个指向组件上定义的方法的属性名或者路径
内联事件处理器
<template>
    <button v-on:click="count++">add</button>
    <p>{{ count }}</p>
</template>
<script>
export default{
    data(){
        return{
            count:0
        }
    }
}
</script>
方法事件处理器
<template>
    <button @click="add">add</button>
    <p>{{ count }}</p>
</template>
<script>
export default{
    data(){
        return{
            count:0
        }
    },
    methods:{
        add(){
            this.count+=1
        }
    }
}
</script>
事件修饰符

在处理事件时调用event.preventDefault()event.stopPropagation()是很常见的。尽管我们可以直接在方法内调用,但如果方法能更专注与数据逻辑而不用处理DOM事件的细节会更好

为解决这一问题,Vue为v-on提供了事件修饰符,常用有以下几个:

  • .stop
  • .prevent
  • .once
  • .enter
阻止默认事件
<template>
<a href="" @click="one">阻止默认事件</a>
</template>
<script>
export default{
    data(){
        return{
            
        } 
    },
    methods:{
        one(e){
            e.preventDefault();
            console.log("1");
        }
    }
   
}
<a href="" @click.prevent="one">阻止默认事件</a>
阻止冒泡事件
<template>
<div @click="one">
    <p @click="two">阻止冒泡事件</p>
</div>
</template>
<script>
export default{
    data(){
        return{
            
        } 
    },
    methods:{
        one(e){
            console.log("1");
        },
        two(e){
            e.stopPropagation();
            console.log("2");
        }
    }
   
}
</script>
<div @click="one">
    <p @click.stop="two">阻止冒泡事件</p>
</div>

9、计算属性

<template>
<p>{{ person.content.length > 0 ? "yes" : "no"}}</p>
</template>
<script>
export default{
    data(){
        return{
            person:{
                name:"小丁",
                content:["1","2","3"]
            }
        }
    }
}
</script>

模板中的表达式虽然方便,但也只能用来做简单的操作。如果在模板中写太多逻辑,会让模板变得臃肿,难以维护。因此我们推荐使用计算属性来描述响应式状态的复杂逻辑

<template>
<p>{{ getcontent }}</p>
</template>
<script>
export default{
    data(){
        return{
            person:{
                name:"小丁",
                content:["1","2","3"]
            }
        }
    },
    computed:{
        getcontent() {
            return this.person.content.length > 0 ? "yes" : "no"
        }
    },
    methods:{
        getcontent2() {
            return this.person.content.length > 0 ? "yes" : "no"
        }
    }
}
</script>

重点区别:

计算属性:计算属性值会基于其相应式依赖被缓存。一个计算属性仅会在其响应式依赖更新时才重新计算

方法:方法调用总是会在重渲染发生时再次执行函数

10、Class绑定

数据绑定的一个常见需求场景是操作的CSS class 列表,因为class是attribute,我们可以和其它attribute一样使用v-bind将它们和动态的字符串绑定。但是,在处理比较复杂的绑定时,通过拼接生成字符串是麻烦且易出错的。因此,Vue专门为classv-bind用法提供了特殊的功能增强。除了字符串外,表达式的值也可以是对象或数组。

<div :class="{ active: isActive }"></div>

上面的语法表示 active 是否存在取决于数据属性 isActive真假值

你可以在对象中写多个字段来操作多个 class。此外,:class 指令也可以和一般的 class attribute 共存。举例来说,下面这样的状态:

const isActive = ref(true)
const hasError = ref(false)

class会绑定对象、数组

11、Style绑定

绑定对象

:style 支持绑定 JavaScript 对象值,对应的是 HTML 元素的 style 属性

const activeColor = ref('red')
const fontSize = ref(30)
<div :style="{ color: activeColor, fontSize: fontSize + 'px' }"></div>

尽管推荐使用 camelCase,但 :style 也支持 kebab-cased 形式的 CSS 属性 key (对应其 CSS 中的实际名称),例如:

<div :style="{ 'font-size': fontSize + 'px' }"></div>

直接绑定一个样式对象通常是一个好主意,这样可以使模板更加简洁:

const styleObject = reactive({
  color: 'red',
  fontSize: '13px'
})
<div :style="styleObject"></div>

同样的,如果样式对象需要更复杂的逻辑,也可以使用返回样式对象的计算属性。

绑定数组

我们还可以给 :style 绑定一个包含多个样式对象的数组。这些对象会被合并后渲染到同一元素上:

<div :style="[baseStyles, overridingStyles]"></div>

12、侦听器

计算属性允许我们声明性地计算衍生值。然而在有些情况下,我们需要在状态变化时执行一些“副作用”:例如更改 DOM,或是根据异步操作的结果去修改另一处的状态。

在组合式 API 中,我们可以使用 watch 函数在每次响应式状态发生变化时触发回调函数:

<template>
<p>{{ msg }}</p>
<button @click="change"></button>
</template>
<script>
export default{
    data(){
        return{
            msg:"hello"
        }
    },
    methods:{
        change(){
            this.msg="world"
        }
    },
    watch:{
        msg(newValue,oldValue){
            //数据发生变化,自动执行的函数
            console.log(newValue,oldValue);
        }
    }
}
</script>

13、表单输入绑定

在前端处理表单时,我们常常需要将表单输入框的内容同步给 JavaScript 中相应的变量。手动连接值绑定和更改事件监听器可能会很麻烦:

<input
  :value="text"
  @input="event => text = event.target.value">

v-model 指令帮我们简化了这一步骤:

<input v-model="text">

另外,v-model 还可以用于各种不同类型的输入,<textarea><select> 元素。它会根据所使用的元素自动使用对应的 DOM 属性和事件组合:

  • 文本类型的 <input><textarea> 元素会绑定 value property 并侦听 input 事件;
  • <input type="checkbox"><input type="radio"> 会绑定 checked property 并侦听 change 事件;
  • <select> 会绑定 value property 并侦听 change 事件。

注意

v-model 会忽略任何表单元素上初始的 valuecheckedselected attribute。它将始终将当前绑定的 JavaScript 状态视为数据的正确来源。你应该在 JavaScript 中使用响应式系统的 API来声明该初始值。

14、获取DOM操作(模板引用)

虽然Vue的声明性渲染模型为你抽象了大部分对DOM的直接操作,但在某些情况下,我们仍然需要直接访问底层DOM元素。要实现这一点,我们可以使用特殊的refattri

挂载结束后引用都会被暴露在this.$refs之上

<script>
export default {
  mounted() {
    this.$refs.input.focus()
  }
}
</script>

<template>
  <input ref="input" />
</template>

15、组件基础

组件允许我们将 UI 划分为独立的、可重用的部分,并且可以对每个部分进行单独的思考。在实际应用中,组件常常被组织成层层嵌套的树状结构:

组件树

局部注册组件
<template>
<header1/>
</template>
<script>
//引用组件并注册组件
import header1 from './components/header.vue'
export default {
    components:{
            header1
        }   
}
</script>

要使用一个子组件,我们需要在父组件中导入它。假设我们把计数器组件放在了一个叫做 ButtonCounter.vue 的文件中,这个组件将会以默认导出的形式被暴露给外部。

若要将导入的组件暴露给模板,我们需要在 components 选项上注册它。这个组件将会以其注册时的名字作为模板中的标签名。

组件可以被重用任意多次:

<h1>Here is a child component!</h1>
<ButtonCounter />
<ButtonCounter />
<ButtonCounter />
全局注册组件

main.js下设置全局变量

import header2 from './components/header.vue'
const app = createApp(App)
//在这中间写组件注册
app.component('header2',header2)
app.mount('#app')
<template>
<header2/>
</template>
传递 props(父类传递数据给子类)

如果我们正在构建一个博客,我们可能需要一个表示博客文章的组件。我们希望所有的博客文章分享相同的视觉布局,但有不同的内容。要实现这样的效果自然必须向组件中传递数据,例如每篇文章标题和内容,这就会使用到 props。

Props 是一种特别的 attributes,你可以在组件上声明注册。要传递给博客文章组件一个标题,我们必须在组件的 props 列表上声明它。这里要用到 props 选项:

<!--container.vue-->
<template>
    <h3>container</h3>
    <p>{{ title }}</p>
    </template>
    <script>
    export default{
        data(){
            return{
                
            }
        },
        props:['title']
    }    
    </script>
<!--header.vue-->
<template>
<h3>header</h3>
<container :title="title"></container>
</template>
<script>
import container from './container.vue'
export default{
    data(){
        return{
            title:"ncao"
        }
    },
    components:{
        container
    }
}
</script>

在实际应用中,我们可能在父组件中会有如下的一个博客文章数组:

export default {
  // ...
  data() {
    return {
      posts: [
        { id: 1, title: 'My journey with Vue' },
        { id: 2, title: 'Blogging with Vue' },
        { id: 3, title: 'Why Vue is so fun' }
      ]
    }
  }
}

这种情况下,我们可以使用 v-for 来渲染它们:

<BlogPost
  v-for="post in posts"
  :key="post.id"
  :title="post.title"
 /> 
props效验

可以通过子类来验证接收数据的类型和默认值

props:{
            title:{
                type:String,
                default:"默认值"
            }
        }

注意:

prop是只读的,不能修改父元素传递过来的数据,只能修改子元素自身的数据

methods:{
            updateMethode(){
                //错误操作,不允许修改父元素传递过来的数据
                this.title = "新元素!"
            }
        }
组件事件(子类传递数据给父类)

在组件的模板表达式中,可以直接使用$emit方法触发自定义事件

触发自定义事件的目的是组件之间传递数据

通过监听子类的v-model获取数据,$emit将数据从子类传递给父类(自定义方法名为$emit("search",this.search)中设置好的变量名)

<!--one.vue-->
<template>
    <h3>one</h3>
    <p>搜索内容为:{{ msg }}</p>
    <two @search="getdata"/>
</template>
<script>
import two from './two.vue'
export default{
    data(){
        return{
            msg:""
        }
    },
    components:{
        two
    },
    methods:{
        getdata(data){
            this.msg = data
        }
    }
}
</script>
<!--two.vue-->
<template>
    <h3>two</h3>
    <input type="text" v-model="search">
</template>
<script>
export default{
    data(){
        return{
            search:""
        }
    },
    watch:{
        search(newValue,oldValue){
            this.$emit("search",this.search)
        }
    }
}
</script>

16、插槽Slot

插槽内容与出口

在之前的章节中,我们已经了解到组件能够接收任意类型的 JavaScript 值作为 props,但组件要如何接收模板内容呢?在某些场景中,我们可能想要为子组件传递一些模板片段,让子组件在它们的组件中渲染这些片段。

举例来说,这里有一个 <one> 组件,可以像这样使用:

<template>
<one>
  <p>插槽内容</p>
</one>
</template>
<script>
import one from './components/one.vue'
export default{
  data(){
    return{

    }
  },
  components:{
    one
  }
}
</script>

<one>下接收为:(这样可以在<one>中显示插槽内容

<slot></slot>

如果没有数据传递,slot设置默认值

<slot>插槽默认值</slot>

<slot> 元素是一个插槽出口 (slot outlet),标示了父元素提供的插槽内容 (slot content) 将在哪里被渲染。

Slot传递数据
父类传递数据给<one>
<template>
<one>
  <p>{{ msg }}</p>
</one>
</template>
<script>
import one from './components/one.vue'
export default{
  data(){
    return{
      msg:"插槽内容"
    }
  },
  components:{
    one
  }
}
</script>

具名插槽(通过具体变量名来传递数据)

<one>
  <template v-slot:a>
    <p>{{ msg }} a</p>
  </template>
  <template v-slot:b>
    <p>{{ msg }} b</p>
  </template>
</one>
<!-- === v-slot:a可以缩写成#a === -->
<template #a>
<slot name="a">插槽默认值</slot>
<slot name="b">插槽默认值</slot>

具名插槽图示

<one>传递数据给父类

方法一

可以像对组件传递 props 那样,向一个插槽的出口上传递 attributes:

<template>
<h3>one</h3>
<slot name="a" :text="msg">插槽默认值</slot>
</template>
<script>
export default{
  data(){
    return{
      msg:"one传递数据给父类"
    }
  }
}
</script>

当需要接收插槽 props 时,默认插槽和具名插槽的使用方式有一些小区别。下面我们将先展示默认插槽如何接受 props,通过子组件标签上的 v-slot 指令,直接接收到了一个插槽 props 对象:

<template v-slot:a="slotProps">
    <p>{{ slotProps.text }}</p>
</template>

方法二

<slot name="b" text="one传递数据给父类b">插槽默认值</slot>
<template v-slot:b="{text}">
    <p>{{ text }}</p>
</template>

17、Attributes 继承

“透传 attribute”指的是传递给一个组件,却没有被该组件声明为 propsemits 的 attribute 或者 v-on 事件监听器。最常见的例子就是 classstyleid

当一个组件以单个元素为根作渲染时,透传的 attribute 会自动被添加到根元素上。举例来说,假如我们有一个 <MyButton> 组件,它的模板长这样:

template

<!-- <MyButton> 的模板 -->
<button>click me</button>

一个父组件使用了这个组件,并且传入了 class

<MyButton class="large" />

最后渲染出的 DOM 结果是:

<button class="large">click me</button>

这里,<MyButton> 并没有将 class 声明为一个它所接受的 prop,所以 class 被视作透传 attribute,自动透传到了 <MyButton> 的根元素上。

classstyle 的合并

如果一个子组件的根元素已经有了 classstyle attribute,它会和从父组件上继承的值合并。如果我们将之前的 <MyButton> 组件的模板改成这样:

<!-- <MyButton> 的模板 -->
<button class="btn">click me</button>

则最后渲染出的 DOM 结果会变成:

<button class="btn large">click me</button>

18、生命周期钩子

每个 Vue 组件实例在创建时都需要经历一系列的初始化步骤,比如设置好数据侦听,编译模板,挂载实例到 DOM,以及在数据改变时更新 DOM。在此过程中,它也会运行被称为生命周期钩子的函数,让开发者有机会在特定阶段运行自己的代码。

注册周期钩子

举例来说,mounted 钩子可以用来在组件完成初始渲染并创建 DOM 节点后运行代码:

export default {
  mounted() {
    console.log(`the component is now mounted.`)
  }
}

还有其他一些钩子,会在实例生命周期的不同阶段被调用,最常用的是 mountedupdatedunmounted

所有生命周期钩子函数的 this 上下文都会自动指向当前调用它的组件实例。注意:避免用箭头函数来定义生命周期钩子,因为如果这样的话你将无法在函数中通过 this 获取组件实例。

生命周期图示

下面是实例生命周期的图表。你现在并不需要完全理解图中的所有内容,但以后它将是一个有用的参考。

组件生命周期图示

19、异步组件

异步组件就是异步请求,防止大项目中组件过多加载容量大,加载缓慢。

在大型项目中,我们可能需要拆分应用为更小的块,并仅在需要时再从服务器加载相关组件。Vue 提供了 defineAsyncComponent 方法来实现此功能:

import { defineAsyncComponent } from 'vue'
const two = defineAsyncComponent(
  () => import('./two.vue')
)

20、依赖注入

Prop 逐级透传问题

通常情况下,当我们需要从父组件向子组件传递数据时,会使用 props。想象一下这样的结构:有一些多层级嵌套的组件,形成了一颗巨大的组件树,而某个深层的子组件需要一个较远的祖先组件中的部分数据。在这种情况下,如果仅使用 props 则必须将其沿着组件链逐级传递下去,这会非常麻烦:

Prop 逐级透传的过程图示

注意,虽然这里的 <Footer> 组件可能根本不关心这些 props,但为了使 <DeepChild> 能访问到它们,仍然需要定义并向下传递。如果组件链路非常长,可能会影响到更多这条路上的组件。这一问题被称为“prop 逐级透传”,显然是我们希望尽量避免的情况。

provideinject 可以帮助我们解决这一问题。一个父组件相对于其所有的后代组件,会作为依赖提供者。任何后代的组件树,无论层级有多深,都可以注入由父组件提供给整条链路的依赖。

Provide/inject 模式

provide:{
    prop: "依赖注入"
  }
inject:['prop']

this上下文都会自动指向当前调用它的组件实例。注意:避免用箭头函数来定义生命周期钩子,因为如果这样的话你将无法在函数中通过this` 获取组件实例。

生命周期图示

下面是实例生命周期的图表。你现在并不需要完全理解图中的所有内容,但以后它将是一个有用的参考。

[外链图片转存中…(img-Xpyvylt0-1694591464564)]

19、异步组件

异步组件就是异步请求,防止大项目中组件过多加载容量大,加载缓慢。

在大型项目中,我们可能需要拆分应用为更小的块,并仅在需要时再从服务器加载相关组件。Vue 提供了 defineAsyncComponent 方法来实现此功能:

import { defineAsyncComponent } from 'vue'
const two = defineAsyncComponent(
  () => import('./two.vue')
)

20、依赖注入

Prop 逐级透传问题

通常情况下,当我们需要从父组件向子组件传递数据时,会使用 props。想象一下这样的结构:有一些多层级嵌套的组件,形成了一颗巨大的组件树,而某个深层的子组件需要一个较远的祖先组件中的部分数据。在这种情况下,如果仅使用 props 则必须将其沿着组件链逐级传递下去,这会非常麻烦:

[外链图片转存中…(img-7iLSgRfl-1694591464564)]

注意,虽然这里的 <Footer> 组件可能根本不关心这些 props,但为了使 <DeepChild> 能访问到它们,仍然需要定义并向下传递。如果组件链路非常长,可能会影响到更多这条路上的组件。这一问题被称为“prop 逐级透传”,显然是我们希望尽量避免的情况。

provideinject 可以帮助我们解决这一问题。一个父组件相对于其所有的后代组件,会作为依赖提供者。任何后代的组件树,无论层级有多深,都可以注入由父组件提供给整条链路的依赖。

[外链图片转存中…(img-em5RVjJN-1694591464565)]

provide:{
    prop: "依赖注入"
  }
inject:['prop']
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

海量的海

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值