目录
前言:一、什么是组件二、注册组件1. 全局注册2. 局部注册
二、传递数据【父 -> 子】1. 字符串数组的形式2. 对象的形式
三、组件事件【子 -> 父】1. 字符串数组式声明自定义事件2. 【子组件】触发组件事件3. 【父组件】监听子组件自定义事件4. 组件事件例子
总结:
前言:
在编写vue里的SPA(Single Page Application单页面应用)时,我们始终绕不开组件的使用,Vue3 里有一些重要更新,在这里分享给大家。
一、什么是组件
组件(Component)是 Vue.js 最强大的功能之一。
组件可以扩展 HTML 元素,封装可重用的代码。
组件系统让我们可以用独立可复用的小组件来构建大型应用,几乎任意类型的应用的界面都可以抽象为一个组件树:
组件就相当于页面的零件,当做正常的标签使用,不过能够进行自定义的数据传输和事件监听。 组件内也能使用其他的组件,任意处都能够使用。
二、注册组件
一个 Vue 组件在使用前需要先被 “注册”,这样 Vue 才能在渲染模板时找到其对应的实现;组件注册有两种方式:全局注册、局部注册
1. 全局注册
可使用 app.component(name, Component)注册组件的方法,在此应用的任意组件的模板中使用
name:注册的名字Component:需要注册的组件
// 在 main.js 中注册全局组件
import { createApp } from 'vue'
import App from './App.vue'
// 1:引入需要被注册的组件
import Login from './components/Login.vue'
const app = createApp(App)
// 2:全局注册组件
app.component('MLogin', Login)
app.mount('#app')
// 我们使用注册的组件
登录系统
2. 局部注册
局部注册的组件需要在使用它的父组件中显式导入,并且只能在该父组件中使用
在组合式 API 中的
登录系统
二、传递数据【父 -> 子】
如果父组件向子组件进行传递数据,那么我们需要在子组件中声明 props 来接收传递数据的属性,可采用字符串数组式或对象式来声明 props 父组件向子组件传递数据,在使用组件 let 的标签上采用属性方式传递的 props 值,可使用 v-bind: 或 : 来绑定属性 组件中 props 中的数据是只读的,不可直接更改,只能通过父组件进行更改
声明与使用
在选项式 API 中 1. 我们可以提供 props 选项来声明接收传递的数据 2. 在 JS 中可使用 this.$props 来访问声明的自定义的属性 3. 在视图模板中,可直接访问 props 中声明的自定义属性在组合式 API 中 1. 我们可以采用 defineProps 宏来声明接收传递的数据 2. 在 JS 中可使用 defineProps 返回的对象来访问声明的自定义的属性 3. 在视图模板中,可直接访问 defineProps 中声明的自定义属性
1. 字符串数组的形式
// 字符串数组的形式
// 使用 defineProps 宏来声明
defineProps(['flat', 'title'])
例子:
// 父组件
import { ref } from 'vue';
import ButtonVue from './components/Button.vue';
let isError = ref(false) // 主题
let isFlat = ref(false) // 阴影
let btnText = ref('普通按钮') // 按钮文本
主题:
阴影:
按钮文本:
// 子组件
// 声明接收父组件传递的属性值:自定义属性
let propsData = defineProps(['title', 'error', 'flat'])
function showPropsData() {
// 在 JS 中,需要通过 defineProps 返回对象来访问 props 的内容
console.log(propsData)
console.log(propsData.title)
console.log(propsData.error)
console.log(propsData.flat)
}
function changeErrorProps() {
// 不能直接修改 props 的数据,因为是只读的
propsData.error = !propsData.error
}
{{ title }}
button {
border: none;
padding: 12px 25px;
}
.error {
background-color: rgb(197, 75, 75);
color: white;
}
.flat {
box-shadow: 0 0 10px grey;
}
2. 对象的形式
对象形式声明的 props,可以对传来的值进行校验,如果传入的值不满足类型要求,会在浏览器控制台中抛出警告来提醒使用者 对象形式声明的 props,key 是 prop 的名称,值则为约束的条件
对象中的属性:
type:类型,如 String、Number、Boolean、Array、Object、Date、Function、Symbol default:默认值;对象或者数组应当用工厂函数返回 required:是否必填,布尔值 validator:自定义校验,函数类型
// 对象的形式
defineProps({
// 基础类型检查
// (给出 `null` 和 `undefined` 值则会跳过任何类型检查)
propA: Number,
// 多种可能的类型
propB: [String, Number],
// 必传,且为 String 类型
propC: {
type: String,
required: true
},
// Number 类型的默认值
propD: {
type: Number,
default: 100
},
// 对象类型的默认值
propE: {
type: Object,
// 对象或数组的默认值
// 必须从一个工厂函数返回。
// 该函数接收组件所接收到的原始 prop 作为参数。
default(rawProps) {
return { message: 'hello' }
}
},
// 自定义类型校验函数
propF: {
validator(value) {
// The value must match one of these strings
return ['success', 'warning', 'danger'].includes(value)
}
},
// 函数类型的默认值
propG: {
type: Function,
// 不像对象或数组的默认,这不是一个工厂函数。这会是一个用来作为默认值的函数
default() {
return 'Default function'
}
}
})
例子:
// 父组件
import { ref } from 'vue';
import ButtonVue from './components/Button.vue';
let isError = ref(false) // 主题
let isFlat = ref(false) // 阴影
let btnText = ref('普通按钮') // 按钮文本
主题:
阴影:
按钮文本:
// 子组件
// 声明接收父组件传递的属性值:自定义属性
let propsData = defineProps({
title: {
type: String,
required: true
},
error: Boolean,
flat: Boolean,
tips: {
type: String,
default: '我是一个普通的按钮'
}
})
function showPropsData() {
// 在 JS 中,需要通过 defineProps 返回对象来访问 props 的内容
console.log(propsData)
console.log(propsData.title)
console.log(propsData.error)
console.log(propsData.flat)
}
function changeErrorProps() {
// 不能直接修改 props 的数据,因为是只读的
propsData.error = !propsData.error
}
{{ title }}
button {
border: none;
padding: 12px 25px;
}
.error {
background-color: rgb(197, 75, 75);
color: white;
}
.flat {
box-shadow: 0 0 10px grey;
}
注意:
所有 prop 默认都是可选的,除非声明了 required: true除 Boolean 外的未传递的可选prop将会有一个默认值 undefinedBoolean 类型的未传递 prop 将被转换为 false;当 prop 的校验失败后,Vue 会抛出一个控制台警告【在开发模式下】注意 prop 的校验是在组件实例被创建之前 1. 在选项式 API 中,实例的属性(比如 data、computed 等) 将在 default 或 validator 函数中不可用 2. 在组合式 API 中,defineProps 宏中的参数不可以访问
对象式声明自定义事件
采用对象式声明自定义事件,还可以进行校验传递的参数是否符合预期要求 对象式声明自定义事件中,属性名为自定义事件名,属性值则是是否验证传递的参数:
属性值为 null 则不需要验证属性值为函数时,参数为传递的数据,函数返回 true 则验证通过,返回 false 则验证失败,验证失败可以用警告语句提示开发者【注意:无论是 true 还是 false 都会继续执行下去的,父组件都会获取到传递的值】
defineEmits({
autoEvent1: null, // 无需校验
// 需要校验,param 可以是多个参数,返回布尔值来表明事件是否合法
autoEvent2: (param) => {
// true 则通过
// false 则不通过,可以在控制台输入警告语句
}
})
2. 【子组件】触发组件事件
在选项式 API 中,可通过组件当前实例 this.$emit(event, ...args) 来触发当前组件自定义的事件 在组合式 API 中,可调用 defineEmits 宏返回的 emit(event, ...args) 函数来触发当前组件自定义的事件 其中上方两个参数分别为:
event:触发事件名,字符串类型...args:传递参数,可没有,可多个
// 自定义事件,并返回 emit 函数
const emit = defineEmits(['changeAge'])
function emitAgeEvent() {
// 触发自定义事件 changeAge,并传递参数 1,20
emit('changeAge', 1, 20)
}
3. 【父组件】监听子组件自定义事件
使用 v-on:event="callback" 或者 @event="callback" 来监听子组件是否触发了该事件
event:事件名字(camelCase 形式命名的事件,在父组件中可以使用 kebab-case 形式来监听)callback:回调函数,如果子组件触发该事件,那么在父组件中执行对应的回调函数,回调函数声明参数可自动接收到触发事件传来的值
import { ref } from 'vue';
import ButtonVue from './components/Button.vue';
let startAge = ref(0)
let endAge = ref(0)
// 子组件触发事件的回调函数
function addAge(start_age, end_age) {
console.log('----------------');
console.log(start_age)
console.log(end_age)
startAge.value = start_age
endAge.value = end_age
}
开始年龄:{{ startAge }}
结束年龄:{{ endAge }}
4. 组件事件例子
字符串数组式声明自定义事件
// 父组件
import { reactive } from 'vue';
import StudentVue from './components/Student.vue';
let student = reactive({
name: 'Jack',
age: 18,
sex: '男'
})
// 获取子组件传递值
function getNewAge(newAge) {
console.log('年龄的新值:' + newAge)
student.age = newAge
}
function getNewAgeAndName(newAge, newName) {
console.log('年龄的新值:' + newAge)
console.log('名字的新值:' + newName)
student.age = newAge
student.name = newName
}
function getNewStudent(stu){
console.log('学生新值:');
console.log(stu);
student.age = stu.age
student.name = stu.name
student.sex = stu.sex
}
{{ student }}
@change-student="getNewStudent" @change-age-and-name="getNewAgeAndName" @change-age="getNewAge" /> // 子组件 // 自定义事件 let emit = defineEmits(['changeAge', 'changeAgeAndName', 'changeStudent']) function emitEventAge() { // 选项式通过 this.$emit 触发自定义事件,并传值 emit('changeAge', 30) } 更改年龄和名字 更改学生(验证通过) 更改学生(验证失败) 对象式声明自定义事件 // 父组件 import { reactive } from 'vue'; import StudentVue from './components/Student.vue'; let student = reactive({ name: 'Jack', age: 18, sex: '男' }) // 获取子组件传递值 function getNewAge(newAge) { console.log('年龄的新值:' + newAge) student.age = newAge } function getNewAgeAndName(newAge, newName) { console.log('年龄的新值:' + newAge) console.log('名字的新值:' + newName) student.age = newAge student.name = newName } function getNewStudent(stu){ console.log('学生新值:'); console.log(stu); student.age = stu.age student.name = stu.name student.sex = stu.sex } {{ student }}
@change-student="getNewStudent" @change-age-and-name="getNewAgeAndName" @change-age="getNewAge" /> // 子组件 // 自定义事件 let emit = defineEmits({ changeAge: null, // 无需验证 changeAgeAndName: null, // 无需验证 changeStudent: stu => { if (stu.age <= 0) { console.warn('年龄不得小于等于0') // false:验证不通过,会有警告语句,父组件依旧可以获取该值 return false } // true:验证通过 return true } }) function emitEventAge() { // 选项式通过 this.$emit 触发自定义事件,并传值 emit('changeAge', 30) } 更改年龄和名字 更改学生(验证通过) 更改学生(验证失败) 总结: 欢迎大家加入我的社区,在社区中会不定时发布一些精选内容:https://bbs.csdn.net/forums/db95ba6b828b43ababd4ee5e41e8d251?category=10003 以上就是 Vue3 中组件的使用(上),不懂得也可以在评论区里问我或私聊我询问,以后会持续发布一些新的功能,敬请关注。 我的其他文章:https://blog.csdn.net/weixin_62897746?type=blog 参考文章
发表评论