Vue 组件基础与组件间的数据传递

一、什么是组件

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

这和我们嵌套HTML元素的方式类似,Vue实现了自己的组件模型,使我们可以在每个组件内封装自定义内容与逻辑。在Vue中,我们可以将页面中独立的、可重用的部分封装成组件,对组件的结构、样式和行为进行设置。组件是Vue的基本结构单元,组件之间可以相互引用。

1.1定义一个计数器组件ButtonCounter.vue
<script setup>
import { ref } from 'vue'
const count = ref(0)
</script>

<template>
  <button @click="count++">You clicked me {{ count }} times.</button>
</template>
1.2在父组件ButtonFather.vue中导入ButtonCounter组件
<script setup>
import ButtonCounter from './ButtonCounter.vue'
  // 引入ButtonCounter组件
</script>

<template>
    <h1>Here is a child component!</h1>
    <!--  使用ButtonCounter组件,在使用组件时有两种方式1.<组件名/> 2.<组件名></组件名> ,而且组件可以被重用任意多次 -->
    <ButtonCounter/> <!-- 使用第一种方式使用组件  -->
    <ButtonCounter></ButtonCounter> <!-- 使用第二种方式使用组件  -->
</template>

分别点击页面中这两个组件不同次数后的浏览器页面截图如下(你会注意到,每当点击这些按钮时,每一个组件都维护着自己的状态,是不同的count。这是因为每当你使用一个组件,就创建了一个新的实例): 

1.3全局注册ButtonCounter计数器组件

使用component(‘组件名称’, 需要被注册的组件)方法在main.js中全局注册ButtonCounter计数器组件:

import { createApp } from 'vue'
import './style.css'
import ButtonCounter from './components/ButtonCounter.vue' // 引入组件

import App from './components/ButtonFather.vue' // 引入根组件,程序的入口

// createApp(App).mount('#app') 将这句代码注释掉,并拆成如下两句const app = createApp(App)和app.mount('#app')

const app = createApp(App)
app.component('ButtonCounter',ButtonCounter) // 注册全局组件
app.mount('#app')

之后注释掉父组件ButtonFather.vue中引入ButtonCounter组件的代码:

<script setup>
// import ButtonCounter from './ButtonCounter.vue'
</script>

<template>
    <h1>Here is a child component!</h1>
    <!--  使用ButtonCounter组件,在使用组件时有两种方式1.<组件名/> 2.<组件名></组件名> ,而且组件可以被重用任意多次 -->
    <ButtonCounter/> <!-- 使用第一种方式使用组件  -->
    <ButtonCounter></ButtonCounter> <!-- 使用第二种方式使用组件  -->
</template>

浏览器依旧正常显示全局注册的ButtonCounter组件:

 二、父组件向子组件传递数据

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

Props是一种特别的attributes,你可以在组件上声明注册。要传递给博客文章组件一个标题,我们必须在组件的props列表上声明它。这里要用到defineProps宏,defineProps是一个仅<script setup>中可用的编译宏命令,并不需要显式地导入。声明的props会自动暴露给模板。defineProps会返回一个对象,其中包含了可以传递给组件的所有props。
传递prop的细节详见Props | Vue.js

2.1在子组件中声明数据

在子组件BlogPost.vue中声明要从父组件那里接收的props数据:

<script setup>
defineProps(['title'])  // 通过 defineProps 定义 title 属性
</script>

<template>
  <h4>{{ title }}</h4>   <!-- 使用 title 属性 -->
</template>
2.2在父组件中向子组件传递数据

在父组件BlogFather.vue中向子组件传递数据:

<script setup> 
import { ref } from 'vue'
import BlogPost from './BlogPost.vue' // 导入子组件BlogPost
const title1 = ref('My journey with Vue')  // 定义一个变量title1
</script>

<template>
	 <BlogPost :title="title1" ></BlogPost>
<!— 动态绑定title1变量给子组件BlogPost的title属性 -->
</template>

三、子组件向父组件传递数据

3.1在子组件中定义事件

在子组件EmitSub.vue中通过调用内置的defineEmits方法,定义updateCount事件,并在点击按钮时触发该事件同时向父组件传递参数:

<template>
    <h4>点击按钮{{ count }}次</h4>
    <button @click="add">每次加{{ n }}</button>
</template>

<script setup>
import { ref } from 'vue'
const emit = defineEmits(['updateCount']) // 定义一个 updateCount 事件
const count = ref(0)
const n = ref(2)
const add = () => {
    count.value++ // count 自增
    emit('updateCount', n.value) // 触发 updateCount 事件,并传参
}
</script>
3.2在父组件中监听事件

在父组件EmitFather.vue中监听子组件的事件updateCount,并触发 updateEmitCount 方法:

<template>
    <!-- 事件监听,监听子组件的事件updateCount,触发 updateEmitCount 方法 -->
     <EmitSub  @updateCount ="updateEmitCount" ></EmitSub>  
   <h4>父组件当前值为number:{{ number }}</h4>
</template>

<script setup> 
import { ref } from 'vue'
import EmitSub from './EmitSub.vue'  // 导入子组件
 
const number = ref(10)  
// 定义一个 updateEmitCount 方法,接收一个参数 value, value 为子组件传递的值
const updateEmitCount = (value) => { 
   number.value += value
}
</script>

四、跨级组件之间的数据传递

通过 inject()函数 获取数据,通过 provide()函数提供数据。

子组件:

<template>
    <div>子组件</div>
    <hr>
    从爷爷组件接收到的资金:{{ money }}
    <button @click="updateMoney(500)">单击按钮增加资金</button>
  </template>
  
  <script setup>
  import { inject } from 'vue' // 导入 inject
  let money = inject('money') // 通过 inject 获取爷爷组件传递的 money
  let updateMoney = inject('updateMoney') // 通过 inject 获取爷爷组件传递的 updateMoney 方法
  </script>

父组件:

<template>
    <div>父组件</div>
    <hr>
    <ProvideChildren />
  </template>
  
  <script setup>
  import ProvideChildren from './ProvideChildren.vue'
  </script> 

爷爷组件:

<template>
    <div>爷爷组件</div>
    <hr>
    <ProvideParent />
</template>

<script setup>
import ProvideParent from './ProvideParent.vue'
import { ref, provide } from 'vue'  // 导入 provide
let money = ref(1000)
let updateMoney = (value) => {
    money.value += value
}
provide('money', money) // 通过 provide 提供 money
provide('updateMoney', updateMoney) // 通过 provide 提供 updateMoney
</script>

附本节项目代码下载地址:

链接:https://pan.baidu.com/s/1ssiN4GAkxLfhxcg7tRXRiA?pwd=8888 
提取码:8888 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值