版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
Vue3组件演讲人:XXXXXXJavaScript+Vue.jsWeb开发实战教程09学习目标了解选项式API和组合式API掌握组件生命周期函数的使用方法掌握组件的注册和引用方法掌握组件之间的样式冲突的解决方法掌握父、子组件之间的数据传递方法握跨级组件之间的数据传递方法能够使用组合式API能够灵活运用组件生命周期函数能够独立创建组件能够解决组件之间的样式冲突能够在父、子组件之间传递数据能够在跨级组件之间传递数据思维导图9.1选项式API和组合式API选项式API是一种通过包含多个选项的对象来描述组件逻辑的API,其常用的选项包括data、methods、computed、watch等。其中,data用于定义数据,methods用于定义方法,computed用于定义计算属性,watch用于定义侦听器。选项式API的语法格式如下所示。<script>
exportdefault{
data(){
return{//定义数据
}
},
methods:{//定义方法
},
computed:{//定义计算属性
},
watch:{//定义侦听器
}
}</script>1.选项式API9.1选项式API和组合式API2.组合式API组合式API的语法格式如下所示。<script>
import{computed,watch}from'vue'
exportdefault{
setup(){
//定义数据
const数据名=数据值
//定义方法
const方法名=()=>{}
//定义计算属性
const计算属性名=computed(()=>{})
//定义侦听器
watch(侦听器的来源,回调函数,可选参数)
return{
数据名,
方法名,
计算属性名
}
}
}</script>9.1选项式API和组合式APIVue3还提供了setup语法糖,用于简化组合式API的代码。在使用setup语法糖的情况下,组合式API的语法格式如下所示。<scriptsetup>
import{computed,watch}from'vue'
//定义数据
const数据名=数据值
//定义方法
const方法名=()=>{}
//定义计算属性
const计算属性名=computed(()=>{})
//定义侦听器
watch(侦听器的来源,回调函数,可选参数)</script>Vue3提供的选项式API和组合式API可以覆盖大部分的应用场景,它们是同一底层系统所提供的两套不同的接口。当企业开发大型项目时,随着业务复杂度的增加,代码量会不断增加。如果使用选项式API,整个项目的代码不易阅读且其逻辑不易理解,查找对应功能的代码存Vue3提供的选项式API和组合式API可以覆盖大部分的应用场景,它们是同一底层系统所提供的两套不同的接口。当企业开发大型项目时,随着业务复杂度的增加,代码量会不断增加。如果使用选项式API,整个项目的代码不易阅读且其逻辑不易理解,查找对应功能的代码存在一定难度。如果使用组合式API,可以将项目的每个功能的数据、方法放到一起,这样无论项目规模大小,都可以快速定位到功能的相关代码,从而提高了代码的可读性和可维护性。同时,组合式API可以通过函数实现高效的逻辑复用,这种形式更加灵活,但需要开发者有较强的代码组织能力和逻辑拆分能力。在一定难度。如果使用组合式API,可以将项目的每个功能的数据、方法放到一起,这样无论项目规模大小,都可以快速定位到功能的相关代码,从而提高了代码的可读性和可维护性。同时,组合式API可以通过函数实现高效的逻辑复用,这种形式更加灵活,但需要开发者有较强的代码组织能力和逻辑拆分能力。9.1选项式API和组合式API3.选项式API和组合式API的使用方法接下来通过实际操作演示选项式API和组合式API的使用方法。例如,在网页中实现单击“+1”按钮使数字加1的效果,具体步骤如下创建src/components/OptionApi.vue文件,代码如下所示。<template>
<div>数字:{{number}}</div>
<button@click="addNumber">+1</button></template><script>
exportdefault{
data(){
return{number:1}
},
methods:{
addNumber(){
this.number++}
}
}</script>在App.vue中引入OptionApi组件,切换页面中显示的组件,代码如下所示。<scriptsetup>
importOptionApifrom'./components/OptionApi.vue'</script><template>
<option-api/></template>在浏览器中访问:5173,通过选项式API实现的初始页面效果如图所示。图
通过选项式API实现的初始页面效果图
单击“+1”按钮后的页面效果9.1选项式API和组合式API<template>
<div>数字:{{number}}</div>
<button@click="addNumber">+1</button></template><scriptsetup>
import{ref}from'vue'
letnumber=ref(1)
constaddNumber=()=>{
number.value++
}</script>创建src/components/CompositionApi.vue文件,代码如下所示。<scriptsetup>
importCompositionApifrom'./components/CompositionApi.vue'</script><template>
<composition-api/></template>在App.vue中引入CompositionApi组件,切换页面中显示的组件,代码如下所示。在浏览器中访问:5173,效果与①②效果相同。
9.2.1组合式API下的生命周期函数
函数调用时间onBeforeMount()组件挂载前onMounted()组件挂载成功后onBeforeUpdate()组件更新前onUpdated()组件中任意DOM元素更新后onBeforeUnmount()组件实例销毁前onUnmounted()组件实例销毁后表
组合式API下的生命周期函数<scriptsetup>
import{onMounted}from'vue'
onMounted(()=>{
//执行操作
})</script>下面以onMounted()函数为例,演示组合式API下的生命周期函数的使用方法。示例如下。9.2.1组合式API下的生命周期函数
接下来通过实际操作演示组合式API下的生命周期函数的使用方法,具体步骤如下。<template>
<divclass="container">container</div></template><scriptsetup>
import{onBeforeMount,onMounted}from'vue'
onBeforeMount(()=>{
console.log('DOM元素渲染前:',document.querySelector('.container'))
})
onMounted(()=>{
console.log('DOM元素渲染后:',document.querySelector('.container'))
})</script>在App.vue中引入LifecycleHook组件,切换页面中显示的组件,代码如下所示。<scriptsetup>
importLifecycleHook'./components/LifecycleHook.vue'</script><template>
<lifecycle-hook/></template>在浏览器中访问:5173并打开控制台,使用onBeforeMount()和onMounted()函数实现的页面效果和控制台效果如图所示。图
使用onBeforeMount()和onMounted()函数实现的页面效果和控制台效果创建src/components/LifecycleHook.vue文件,代码如下所示。9.2.2选项式API下的生命周期函数函数调用时间beforeCreate()组件实例创建前created()组件实例创建后beforeMount()组件挂载前mounted()组件挂载成功后beforeUpdate()组件更新前updated()组件中任意DOM元素更新后beforeDestroy()组件实例销毁前destroyed()组件实例销毁后表
组合式API下的生命周期函数<script>
exportdefault{
beforeCreate(){
//执行操作
},
created(){
//执行操作}
}</script>接下来演示选项式API下的beforeCreate()函数和created()函数的使用方法。示例如下。9.2.2选项式API下的生命周期函数接下来通过实际操作演示选项式API下的生命周期函数的使用方法,具体步骤如下。<script>
exportdefault{
data(){
return{
value:'HelloWorld'
}
},
beforeCreate(){
console.log('组件实例创建前:'+this.value)
},
created(){
console.log('组件实例创建后:'+this.value)
}
}</script>在App.vue中引入LifecycleHook2组件,切换页面中显示的组件,代码如下所示。<scriptsetup>
importLifecycleHook2'./components/LifecycleHook2.vue'</script><template>
<lifecycle-hook2/></template>在浏览器中访问:5173并打开控制台,使用beforeCreate()和created()函数实现的控制台效果如图所示。图
使用beforeCreate()和created()函数实现的控制台效果创建src/components/LifecycleHook2.vue文件,代码如下所示。9.3.1注册组件全局注册01component('组件名',需要被注册的组件)被全局注册的组件可以在当前Vue项目的任何一个组件内引用。在Vue项目的src/main.js文件中,通过Vue应用实例的component()方法可以全局注册组件。该方式的语法格式如下所示。import{createApp}from'vue'importMyComponentfrom'./components/MyComponent.vue'importAppfrom'./App.vue'constapp=createApp(App)ponent('MyComponent',MyComponent)app.mount('#app')例如,在src/main.js文件中注册一个全局组件MyComponent,代码如下所示。component()方法支持链式调用,可用于连续注册多个组件。示例如下。ponent('ComponentA',,ComponentA)
.component('ComponentB',,ComponentB)
.component('ComponentC',,ComponentC)9.3.1注册组件局部注册组件的示例如下。局部注册02<script>
importComponentAfrom'./ComponentA'
exportdefault{
components:{ComponentA:ComponentA}
}</script>在使用setup语法糖时,引入的组件会被自动注册,无须手动注册,而且组件引入后可以直接在模板中使用。示例如下。<scriptsetup>
importComponentAfrom'./ComponentA'</script>上述代码完成了ComponentA组件的引入和注册。9.3.2引用组件创建src/components/ComponentUse.vue文件,代码如下所示。<template>
<h3>父组件</h3>
<divclass="box"></div></template><style>
.box{
display:flex;
}</style>默认情况下,Vue项目中有一个根组件,根组件可以引用其他组件,引用后组件之间会形成父子关系——根组件是父组件,被引用的组件是子组件。在子组件中也可以引用其他组件。在组件的<template>标签中可以引用其他组件,被引用的组件需要写成标签的形式,标签名应与组件名对应。组件的标签名可以使用短横线分隔或用帕斯卡命名法定义,如<my-component>标签和<MyComponent>标签都表示引用MyComponent组件。接下来通过实际操作演示组件的引用方法,具体步骤如下。在App.vue中引入ComponentUse组件,切换页面中显示的组件,代码如下所示。<scriptsetup>
importComponentUse'./components/ComponentUse.vue'</script><template>
<component-use/></template>9.3.2引用组件<template>
<divclass="global-container">
<h3>全局组件</h3>
</div></template><style>
.global-container{
border:1pxsolidblack;
height:50px;
flex:1;
}</style>创建src/components/GlobalComponent.vue文件,其表示全局组件,代码如下所示。修改src/main.js文件,引入GlobalComponent组件并调用component()方法全局注册GlobalComponent组件,代码如下所示。import{createApp}from'vue'importGlobalComponentfrom'./components/GlobalComponent.vue'importAppfrom'./App.vue'constapp=createApp(App)ponent(GlobalComponent,GlobalComponent)app.mount('#app')<template>
<divclass="local-container">
<h3>局部组件</h3>
</div></template><style>
.local-container{
border:1pxsolidblack;
height:50px;
flex:1;
}</style>创建src/components/LocalComponent.vue文件,其表示局部组件,代码如下所示。修改src/components/ComponentUse.vue文件,添加代码引入LocalComponent组件,代码如下所示。<scriptsetup>
importLocalComponentfrom'./LocalComponent.vue'</script>修改src/components/ComponentUse.vue文件,在class为box的<div>标签中引用GlobalComponent组件和LocalComponent组件,代码如下所示。<divclass="box">
<global-component/>
<local-component/></div>在浏览器中访问:5173,引用组件后的页面效果如图所示。图
引用组件后的页面效果9.4解决组件之间的样式冲突问题在默认情况下,写在Vue组件中的样式会全局生效,容易造成多个组件之间的样式冲突。例如,为ComponentUse组件中的h3元素添加边框样式,代码如下所示。h3{
border:1pxsolidred;}保存上述代码后,在浏览器中访问:5173,添加边框样式后的页面效果如图所示。图
添加边框样式后的页面效果从图可以看出,ComponentUse组件、GlobalComponent组件和LocalComponent组件中h3元素的边框样式都发生了改变,但代码中只有ComponentUse组件设置了边框样式效果,这说明组件之间存在样式冲突。导致组件之间出现样式冲突的根本原因是在单页Web应用中,所有组件的DOM结构都是基于唯一的index.html页面进行呈现的,每个组件中设置的样式都可以影响整个页面中的DOM元素。9.4.1scoped属性<stylescoped>修改ComponentUse组件,为<style>标签添加scoped属性,代码如下所示。在浏览器中访问:5173,在<style>标签中添加scoped属性后的页面效果如图所示。打开开发者工具,切换到“元素”面板,查看父组件的h3元素的代码,如图所示。从图可以看出,当<style>标签添加scoped属性后,h3元素和相应的选择器被Vue自动添加了data-v-e4f30916属性,从而解决了样式冲突问题。图
在<style>标签中添加scoped属性后的页面效果图
查看父组件的h3元素的代码9.4.2深度选择器如果给当前组件的<style>标签添加了scoped属性,则当前组件的样式对其子组件是不生效的。如果在添加了scoped属性后还需要让某些样式对子组件生效,则可以使用深度选择器来实现。深度选择器使用:deep()伪类,在其圆括号中可以定义用于子组件的选择器。例如,“:deep(.title)”被编译之后,生成的选择器的格式为“[data-v-7ba5bd90].title”。接下来通过实际操作演示如何通过ComponentUse组件更改LocalComponent组件的样式,具体步骤如下。为LocalComponent组件的h3元素添加class属性,代码如下所示。<h3class="title">局部组件</h3>在ComponentUse组件中定义“.title”的样式,代码如下所示。:deep(.title){
border:3pxdottedblack;}在浏览器中访问:5173,利用深度选择器实现样式穿透的页面效果如图所示。图
利用深度选择器实现样式穿透的页面效果打开开发者工具,切换到“元素”面板,查看LocalComponent组件的h3元素的代码,如图所示。图
查看LocalComponent组件的h3元素的代码9.5父组件向子组件传递数据在实际开发中,有时会遇到同一模块中的多个子组件请求同一份数据的情况,如果在子组件中逐个进行网络请求,会导致代码冗余。Vue提供了props语法,可以让父组件为子组件提供要展示的数据,即在父组件中请求该模块下所有子组件中的数据,并通过props将数据传递给子组件。9.5.1声明props在不使用setup语法糖的情况下,可以使用props属性声明props。props选项的形式可以是对象或字符串数组。声明对象形式的props的语法格式如下所示。<script>
exportdefault{
props:{
自定义属性A:类型;
自定义属性B:类型;
...
}
}</script>props:['自定义属性A','自定义属性B']如果不需要限制prop的类型,可以声明字符串数组形式的props,语法格式如下所示。<scriptsetup>
constprops=defineProps({'自定义属性A':类型},{'自定义属性B':类型})</script>当使用setup语法糖时,可以用defineProps()函数声明props,语法格式如下所示。constprops=defineProps(['自定义属性A','自定义属性B'])如果需要声明字符串数组形式的props,可以使用如下语法格式。<template>
{{自定义属性A}}
{{自定义属性B}}</template>在组件中声明了props后,可以直接在模板中输出每个prop的值,语法格式如下所示。9.5.2静态绑定props<子组件标签名
自定义属性A="数据"自定义属性B="数据"/><template>初始值为:{{num}}</template><scriptsetup>
constprops=defineProps({
num:String
})</script>创建src/components/CountComponent.vue文件,用于展示子组件的相关内容,代码如下所示。当在父组件中引用了子组件后,如果子组件中声明了props,则可以在父组件中向子组件传递数据。如果传递的数据是固定不变的,则可以通过静态绑定props的方式为子组件传递数据。其语法格式如下所示。为了帮助读者更好地理解props,接下来通过实际操作演示父组件向子组件传递数据的方法,具体步骤如下。<template>
<Countnum="1"/></template><scriptsetup>
importCountfrom'./CountComponent.vue'</script>创建src/components/PropsComponent.vue文件,用于展示父组件的相关内容,代码如下所示。9.5.2静态绑定props<scriptsetup>
importPropsComponentfrom'./components/PropsComponent.vue'</script><template>
<props-component/></template>在App.vue中引入PropsComponent组件,切换页面中显示的组件,代码如下所示。保存上述代码后,在浏览器中访问:5173,父组件向子组件传递数据的页面效果如图所示。图
父组件向子组件传递数据的页面效果从图可以看出,页面中显示了“初始值为:1”,表示成功将数据从父组件传递给子组件。9.5.3动态绑定props从父组件向子组件传递String类型的props数据,示例如下。String类型01<template>
<Child:init="username"/></template><scriptsetup>
importChildfrom"./Child.vue"
import{ref}from"vue"
constusername=ref("小明")</script>上述代码用到了名为Child的子组件,该子组件的示例如下。<template></template><scriptsetup>
constprops=defineProps(["init"])
console.log(props)</script>9.5.3动态绑定props从父组件向子组件传递Number类型的props数据,示例如下。Number类型02从父组件向子组件传递Boolean类型的props数据,示例如下。Boolean类型03<template>
<Child:init="12"/>
<Child:init="age"/></template><scriptsetup>
impotChildfrom"./Child.vue"
import{ref}from"vue"
constage=ref(12)</script><template>
<Childinit/>
<Child:init="false"/>
<Child:init="isFlag"/></template><scriptsetup>
impotChildfrom"./Child.vue"
import{ref}from"vue"
constisFlag=ref(true)</script>9.5.3动态绑定props从父组件向子组件传递Array类型的props数据,示例如下。Array类型04从父组件向子组件传入Object类型的props数据,或者将对象中的部分属性作为被传入的props数据,示例如下。Object类型05<template>
<Child:init="['唱歌','跳舞','滑冰']”/>
<Child:init="hobby"/></template><template>
<Child:init="{height:'180厘米',weight:'70千克}”/>
<Child:height="bodyInfo.height":weight="bodyInfo.weight"/>
<Childv-bind="bodyInfo"/></template><scriptsetup>
impotChildfrom"./Child.vue"
import{reactive}from"vue"
constbodyInfo=reactive({
height:'180厘米',
weight:'70千克
})</script><scriptsetup>
impotChildfrom"./Child.vue"
import{ref}from"vue"
consthobby=ref(['唱歌','跳舞','滑冰'])</script>9.5.4验证props
在封装组件时,可以在子组件中对从父组件传递过来的props数据进行合法性校验,以防止出现数据不合法的问题。如果使用字符串数组形式的props,则无法为每个prop指定具体的数据类型;如果使用对象形式的props,则可以对每个prop进行数据类型的校验。对象形式的props可以使用多种数据验证方案,包括基础类型检查、必填项的校验、属性默认值定义、自定义验证函数等。可以在声明props时添加数据验证方案。9.5.4验证props
在开发中,有时需要对从父组件中传递过来的props数据进行基础类型检查,这时可以通过type属性检查合法的类型。如果从父组件中传递过来的值的类型不合法,则会发出警告。常见的值的类型有String(字符串)、Number(数字)、Boolean(布尔值)、Array(数组)、Object(对象)、Date(日期)、Function(函数)、Symbol(符号),以及任何自定义构造函数等。为props指定基础类型检查的示例如下。基础类型检查01props:{
自定义属性A:String, //字符串
自定义属性B:Number, //数字
自定义属性C:Boolean, //布尔值
自定义属性D:Array, //数组
自定义属性E:Object, //对象
自定义属性F:Date, //日期
自定义属性G:Function, //函数
自定义属性H:Symbol, //符号}9.5.4验证props
除了上述方式外,还可以通过配置对象的形式定义检查规则。示例如下。props:{
自定义属性:{type:Number},}如果某个prop的类型不唯一,可以通过数组的形式为其指定多个可能的类型。示例如下。props:{
自定义属性:{type:[String,Array]},//字符串或数组}9.5.4验证props
当父组件向子组件传递props数据时,传递的数据有可能为空,但是子组件要求必须传递该数据。此时,可以在声明props时通过required属性设置必填项,强调组件使用者必须传递该属性的值。示例如下。必填项的校验02在声明props时,可以通过default属性定义属性默认值,当父组件没有向子组件的属性传递数据时,属性将会使用默认值。示例如下。属性默认值定义03props:{自定义属性:{required:true}}props:{
自定义属性:{default:0}}为props属性指定自定义验证函数的示例如下。自定义验证函数04props:{
自定义属性:{
validator(value){
return['success','warning','danger'].indexOf(value)!==-1;}
}}9.6.1在子组件中声明自定义事件<scriptsetup>
exportdefault{
emits:['demo']
}</script><scriptsetup>
constemit=defineEmits(['demo'])</script>若想使用自定义事件,首先需要在子组件中声明自定义事件。在不使用setup语法糖时,可以通过emits选项声明自定义事件。示例如下。在使用setup语法糖时,需要通过调用defineEmits()函数声明自定义事件。示例如下。9.6.2在子组件中触发自定义事件在子组件中声明自定义事件后,需要继续在子组件中触发自定义事件。当使用场景较简单时,可以使用内联事件处理程序,通过调用$emit()方法触发自定义事件,将数据传递给父组件。示例如下。<button@click="$emit('demo',1)">按钮</button>除了使用内联事件处理程序外,还可以直接定义方法来触发自定义事件。在不使用setup语法糖时,可以通过setup()函数的第2个参数访问emit()方法。示例如下。exportdefault{
setup(props,ctx){
constupdate=()=>{
ctx.emit('demo',2)}
return{update}
}}在使用setup语法糖时,可以调用emit()函数来实现事件触发。示例如下。<scriptsetup>
constupdate=()=>{
emit('demo',2)
}</script>9.6.3在父组件中监听自定义事件<子组件标签名@demo="fun"/><template>
<p>count值为:{{count}}</p>
<button@click="add">加n</button></template><scriptsetup>
import{ref}from'vue'
constemit=defineEmits(['updateCount'])
constcount=ref(1)
constadd=()=>{
count.value++
emit('updateCount',2)
}</script>创建src/components/CustomSubComponent.vue文件,用于展示子组件的相关内容,代码如下所示。在父组件中,可以通过v-on指令监听子组件中抛出的事件。示例如下。在父组件中定义fun()方法,示例如下。<子组件标签名@demo="fun"/>constfun=(value)=>{
console.log(value)}接下来通过实际操作演示子组件向父组件传递数据的方法,具体步骤如下。9.5.2静态绑定props<template>
<p>父组件当前的值为:{{number}}</p>
<CustomSubComponent@updateCount="updateEmitCount"/></template><scriptsetup>
importCustomSubComponentfrom'./CustomSubComponent.vue'
import{ref}from'vue'
constnumber=ref(10)
constupdateEmitCount=(value)=>{
number.value+=value
}</script>创建src/components/CustomEvents.vue文件,用于展示父组件的相关内容,代码如下所示。保存上述代码后,在浏览器中访问:5173,初始页面效果如图所示。单击“加n”按钮后的页面效果如图所示。<scriptsetup>
importCustomEventsfrom'./components/CustomEvents.vue'</script><template>
<custom-events/></template>在App.vue中引入CustomEvents组件,切换页面中显示的组件,代码如下所示。图
单击“加n”按钮后的页面效果图
初始页面效果9.7跨级组件之间的数据传递Vue提供了跨级组件之间的数据传递方式——依赖注入。一个父组件相对其所有的子组件而言,可作为依赖提供者;而任何子组件,无论层级多深,都可以注入由父组件提供的依赖。对父组件而言,如果要为子组件提供数据,则需要使用provide()函数;对子组件而言,如果想要注入父组件或整个应用提供的数据,则需要使用inject()函数。下面分别对provide()函数和inject()函数进行讲解。provide()函数可以提供一个值,用于被子组件注入。provide()函数的语法格式如下所示。provide(注入名,注入值)在不使用setup语法糖的情况下,provide()函数必须在组件的setup()函数中调用。使用provide()函数的示例如下。provide()函数01<script>
import{ref,provide}from"vue"
exportdefault{
setup(){
constcount=ref(l)
provide(
//注入名
'message',
//注入值
count
)
}
}</script>9.7跨级组件之间的数据传递<scriptsetup>
import{provide}from"vue"
provide('message','HelloVue.js')</script>在使用setup语法糖的情况下,使用provide()函数的示例如下。constapp=createApp(App)vide('message','HelloVue.js')provide()函数除了可以在某个组件中提供依赖外,还可以提供全局依赖。例如,在src\main.js文件中添加全局依赖,示例如下。子组件可以通过inject()函数注入父组件或者整个应用提供的数据。inject()函数的语法格式如下。inject()函数02inject(注入名,默认值,布尔值)在不使用setup语法糖的情况下,inject()函数必须在组件的setup()函数中调用。使用inject()函数的示例如下。9.7跨级组件之间的数据传递在使用setup语法糖的情况下,使用inject()函数的示例如下。<script>
import{inject}from"vue"
exportdefault{
setup(){
constcount=inject("count")
//注入一个值,若为空则使用默认值
constfoo=inject('foo','defaultvalue')
//当没有匹配到注入值时,默认值可以是工厂函数
constbaz=inject("foo",()=>newMap())
//注入时为了表明提供的默认值是函数,传入第3个参数
constfn=inject('function',()=>{},false)
}
}</script><scriptsetup>import{inject}from"vue"constcount=inject("count")9.7跨级组件之间的数据传递了解了provide()函数和inject()函数的用法后,接下来通过实际操作演示跨级组件之间的数据传递,步骤如下。跨级组件之间的数据传递过程03<template>
<div>子组件</div></template>创建src/components/ProvideChildren.vue文件,用于展示子组件的相关内容,代码如下所示。<template>
<div>父组件</div>
<hr/>
<ProvideChildren/></template><scriptsetup>
importProvideChildrenfrom'./ProvideChildren.vue'</script>创建src/components/ProvideParent.vue文件,用于展示父组件的相关内容,代码如下所示。<template>
<div>爷爷组件</div>
<hr/>
<provide-parent/></template>创建src/components/ProvideGrand.vue文件,用于展示父组件的父组件(爷爷组件)的相关内容,代码如下所示。<scriptsetup>
importProvideParentfrom'./ProvideParent.vue'
import{ref,provide}from'vue'
constmoney=ref(100)
constupdateMoney=(value)=>{
money.value=value}
provide('money',money)
provide('updateMoney',updateMoney)</script>9.7跨级组件之间的数据传递<template>
<div>子组件</div>
<hr/>
从爷爷组件接收到的资金:{{money}}
<button@click="updateMoney(500)">单击按钮增加资金</button></template><scriptsetup>
import{inject}from'vue'
constmoney=inject('money')
constupdateMoney=inject('updateMoney')</script>修改src/components/ProvideChildren.vue文件,通过inject()函数接收爷爷组件中传递来的数据,代码如下所示。<scriptsetup>
importProvideGrandfrom'./components/ProvideGrand.vue'</script><template>
<provide-grand/></template>在App.vue中引入ProvideGrand组件,切换页面中显示的组件,代码如下所示。保存上述代码后,在浏览器中访问:5173,初始页面效果如图所示。单击“单击按钮增加资金”按钮后的页面效果如图所示。击按钮后,资金增加,说明子组件成功从爷爷组件接收到了数据和方法,通过provide()函数和inject()函数实现了跨级组件之间的数据传递。图9.14初始页面效果图
单击“单击按钮增加资金”按钮后的页面效果【商业案例】
学生信息管理系统——查看和删除学生信息任务1查看学生信息实现查看学生信息的功能与实现修改学生信息的功能类似,都需要复用ModalComponent组件,区别在于“查看学生信息”弹窗中的输入框都处于禁用状态,不允许编辑,所以需要对输入框绑定disabled属性,在当前弹窗处于查看状态时将输入框设置为禁用。在学生信息列表中所有的“查看”按钮上绑定click事件,当单击该按钮时调用自定义函数handleView(),并将当前选择的学生序号和查看状态传递给父组件,父组件打开弹窗并展示对应的学生信息。“查看学生信息”弹窗如图9.16所示。ModalComponent.vue中与查看学生信息的功能有关的代码如下所示(位置:学生信息管理系统-Vue3版/student-management/src/components/MainComponent.vue)。图“查看学生信息”弹窗【商业案例】
学生信息管理系统——查看和删除学生信息<aclass="viewInf"@click="handleView(id)">查看</a>consthandleView=(id)=>{
emit('showModal',true,id,'view')}ModalComponent.vue中与查看学生信息功能有关的代码如下所示(位置:学生信息管理系统-Vue3版/student-management/src/components/ModalComponent.vue)。<template>
<divclass="modal">
<divclass="modal-dialog">
<divclass="modal-content">
<divclass="modal-header">
<i@click="handleClose">X</i>
<h4>{{title}}</h4>
</div>
<divclass="modal-body">
<p>
序号:<input
@change="changeStudent('id',$event)"
:value="editStudent.id"
type="text"
disabled
/>
</p><p>
学号:<input
@change="changeStudent('No',$event)"
:value="editStudent.No"
type="text"
:disabled="props.modalType==='view'"
/>
</p>
<p>
姓名:<input
@change="changeStudent('name',$event)"
:value="editS"
type="text"
:disabled="props.modalType==='view'"
/>
</p>
<p>
学院:<input
@change="changeStudent('college',$event)"
:value="editStudent.college"
type="text"
:disabled="props.modalType==='view'"
/>
</p>
<p>
专业:<input
@change="changeStudent('major',$event)"
:value="editStudent.major"
type="text"
:disabled="props.modalType==='view'"
/>
</p>【商业案例】
学生信息管理系统——查看和删除学生信息
<p>
年级:<input
@change="changeStudent('grade',$event)"
:value="editStudent.grade"
type="text"
:disabled="props.modalType==='view'"
/>
</p>
<p>
班级:<input
@change="changeStudent('className',$event)"
:value="editStudent.className"
type="text"
:disabled="props.modalType==='view'"
/>
</p>
<p>
年龄:<input
@change="changeStudent('age',$event)"
:value="editStudent.age"
type="text"
:disabled="props.modalType==='view'"
/>
</p>
</div><divclass="modal-footer">
<buttonclass="ok-button"@click="handleConfirm">确定</button>
<buttonclass="cancel-button"@click="handleClose">取消</button>
</div>
</div>
</div>
</div></template><scriptsetup>import{computed,reactive}from'vue'constprops=defineProps({
currentStudent:{
type:Object,
default:()=>{},
},
modalType:{
type:String,
default:()=>'add',
},})consteditStudent=reactive(props.currentStudent)constchangeStudent=(key,e)=>{
editStudent[key]=e.target.value}constemit=defineEmits(['showModal','confirmModal'])consttitle=computed(()=>{
consttitleMap={
add:'新增学生信息',
edit:'修改学生信息',
view:'查看学生信息',
}
returntitleMap[props.modalType]})【商业案例】
学生信息管理系统——查看和删除学生信息consthandleClose=()=>{
emit('showModal',false)}consthandleConfirm=()=>{
emit('confirmModal',editStudent)}</script><stylescoped>.modal{
position:fixed;
left:0px;
top:0px;
right:0px;
bottom:0px;
background:rgba(0,0,0,0.5);}.modal-dialog{
position:absolute;
width:500px;
margin:0pxauto;
background:white;
border-radius:5px;
left:50%;
top:50%;
transform:translate(-50%,-50%);}【商业案例】
学生信息管理系统——查看和删除学生信息.modal-header{
border-bottom:1pxsolid#e5e5e5;
color:#fff;
background-color:#555;
height:40px;
line-height:40px;
padding:020px;
text-align:center;}.modal-header>i{
font-weight:bold;
color:#adadad;
float:right;
cursor:pointer;
font-style:normal;}.modal-body{
position:relative;
text-align:center;
color:#000000;}.modal-bodyinput{
width:202px;
border:1pxsolid#a9a9a9;
outline:none;
margin:10px;}.modal-footer{
padding:15px;
text-align:right;
border-top:1pxsolid#e5e5e5;}.ok-button{
width:93px;
height:38px;
border-radius:4px;
background:#5cb85c;
color:#fff;
outline:none;
cursor:pointer;
border:1pxsolid#aeaeae;
margin-right:10px;}.cancel-button{
width:93px;
height:38px;
border-radius:4px;
background:#fff;
color:#808080;
outline:none;
cursor:pointer;
border:1pxsolid#aeaeae;}</style>任务2删除学生信息【商业案例】
学生信息管理系统——查看和删除学生信息首先需要使用@change为表格中的复选框绑定选中事件,当改变复选框的选中状态时,将当前选择的学生序号传递给父组件(IndexComponent.vue)。使用defineEmits()函数定义changeSelectedStudent事件。在IndexComponent组件中,使用reactive()函数定义selectedStudent
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2026年常见输血、输液不良反应及处理试题及答案
- 医院医务人员防护制度及防护措施
- 地下矿山操作员装卸作业安全操作规程
- 物流企业事故管理制度
- 垃圾处理场(深基坑开挖专项施工方案)
- 2026年安全工程师考试安全生产事故应急救援模拟试卷及答案
- 掌握高分逻辑初中地理等值线判读暑假思维提升复习课
- 我是家里的好帮手互动课件
- 2026年初中道德与法治七年级上册第一单元测试卷
- 纯檀香项目可行性研究报告
- AI赋能公共卫生应急管理的应用与价值
- 2026年上海市中考语文试卷(含答案)
- 2026年河北物理卷高考真题(含答案)(网络参考)
- 教师招聘公共基础知识
- 2025年海南省中考道德与法治试题(试卷+解析)
- 彩灯加工外包合同
- 超声诊断先天性巨结肠
- 叉车聘用协议书
- 2026中国银行间市场流动性风险管理与压力测试专题报告
- 施工阶段成本控制目标方案
- 机房建设投标方案(技术标)
评论
0/150
提交评论