当前位置: 首页 > news >正文

【一】Vue组件开发教程

目录

一、环境

二、为什么要组件开发

三、正式开发

【初步封装】child.vue

【初步封装】App.vue

【父组件向子组件传参数/方法】child.vue

【父组件向子组件传参数/方法】App.vue

【子组件向父组件暴露参数/方法】child.vue

【子组件向父组件暴露参数/方法】App.vue

【子组件向父组件传递参数/方法】child.vue

【子组件向父组件传递参数/方法】App.vue

总结

四、defineProps、defineEmits、defineExpose方法介绍

defineProps、defineEmits

defineExpose

子组件

父组件

一、环境

本文组件开发使用环境如下:

  • Vue3
  • setup语法糖

二、为什么要组件开发

Vue3的一个很大特性在于“组件”,有了组件,我们可以将原本需要几千几万行的一个前端文件(html、js、css)分成若干个小的部分,根据需要再将小的部分拼装起来,同时体现组件的复用性

三、正式开发

首先在component文件夹下创建一个“child.vue”文件,作为组件,默认的App.vue作为父组件使用child.vue组件

假设我们的子组件需要封装一个<input>输入框,父组件只需充当子组件的容器,假设在这个阶段,我们不需要与子组件进行信息交互。

【初步封装】child.vue

在这里我们封装了一个输入框,该输入框高度宽度取决于父组件,并且该输入框的值依赖于组件本身的变量“inputValue

注意此时父组件无法获取到子组件的值,因为我们没有设置外部方法和外部参数。

<script setup>
import { ref } from 'vue'
const inputValue = ref('')
</script>

<template>
  <div class="container">
    <div>测试:</div>
    <input type="text" v-model="inputValue" class="input">
  </div>
</template>

<style scoped>

.container {
  width: 100%;
  height: 100%;
}
.input {
    width: 100%;
    height: auto;
    line-height: 100%;
    font-size: 18pxpx;
}
</style>

【初步封装】App.vue

<script setup>
import myInput from './components/child.vue'
</script>

<template>
  <div class="container">
      <myInput />
  </div>
</template>

<style scoped>
.container {
    width: 300px;
    margin: 20px auto;
}
</style>

效果:

此时组件可以正常运行,但是此时我们的业务需求增加一条:“可以由父组件传入输入框的标签,即label

【父组件向子组件传参数/方法】child.vue

子组件使用defineProps预编译宏,该函数可以用来指定父组件传入的参数,并且可以指定传入参数的类型和默认值。

注意在新版本Vue3中,defineProps不需要导入,在旧版本中仍然需要使用import导入

<script setup>
import { ref } from 'vue'

const props = defineProps({
    labelName:{
        type: String,
        default: '测试'
    }
})

const inputValue = ref('')
</script>

<template>
  <div class="container">
    <div>{{ props.labelName }}</div>
    <input type="text" v-model="inputValue" class="input">
  </div>
</template>

<style scoped>

.container {
  width: 100%;
  height: 100%;
}
.input {
    width: 100%;
    height: auto;
    line-height: 100%;
    font-size: 18px;
}
</style>

【父组件向子组件传参数/方法】App.vue

<script setup>
import { ref } from 'vue'
import myInput from './components/child.vue'
const name = ref('用户名')
</script>

<template>
  <div class="container">
      <myInput 
        labelName="用户名"
      />
      <!-- 或者 -->
      <myInput 
        :labelName="name"
      />
  </div>
</template>

<style scoped>
.container {
    width: 300px;
    height: auto;
    margin: 20px auto;
}
</style>

效果:

看起来,我们成功向父组件传入了参数,但是此时业务需求再次增加:“父组件创建一个按钮,点击按钮后,输入框会清空

【子组件向父组件暴露参数/方法】child.vue

这里,我们使用defineExpose方法,暴露组件本身的“inputValue”变量,顾名思义,暴露的变量,父组件可以控制改组件的变量

<script setup>
import { ref } from 'vue'

const props = defineProps({
    labelName:{
        type: String,
        default: '测试'
    }
})

const inputValue = ref('')

//定义暴露的参数
defineExpose({
    inputValue
})
</script>

<template>
  <div class="container">
    <div>{{ props.labelName }}</div>
    <input type="text" v-model="inputValue" class="input">
  </div>
</template>

<style scoped>

.container {
  width: 100%;
  height: 100%;
}
.input {
    width: 100%;
    height: auto;
    line-height: 100%;
    font-size: 18px;
}
</style>

【子组件向父组件暴露参数/方法】App.vue

父组件子组件传递一个“ref”,后续使用refvalue方法获取组件暴露的变量

<script setup>
import { ref } from 'vue'
import myInput from './components/child.vue'
const name = ref('用户名')
// 使用ref获取子组件的DOM节点
const input = ref(null)

function clearInput() {
    input.value.inputValue = ''
}
</script>

<template>
  <div class="container">
      <myInput 
        labelName="用户名"
        ref="input"
      />
      <button @click="clearInput">清空</button>
  </div>
</template>

<style scoped>
.container {
    width: 300px;
    height: auto;
    margin: 20px auto;
}
</style>

点击后,输入框中的内容成功被清除。

此时,我们又多了一个需求:“输入框中值为子字符串’abcd‘时,向父组件发出信号(执行父组件的方法)

在这里为方便起见,当输入框出现abcd时,父组件接收子组件的值,并且弹窗提醒

秉持着,父组件尽量不应破坏子组件的原则检测字符串的任务应交由“子组件child.vue”完成,弹窗提醒交由“父组件App.vue

弹窗提醒交给父组件是为了保证:当出现abcd时,父组件可以根据场景灵活的选择处理方案

【子组件向父组件传递参数/方法】child.vue

这里使用defineEmits方法(需要import导入最新版本已不需要导入),用来向主动的向父组件传递参数

<script setup>
import { ref,defineEmits } from 'vue'

// 定义外部参数
const props = defineProps({
    labelName:{
        type: String,
        default: '测试'
    }
})

const inputValue = ref('')

//定义暴露的参数
defineExpose({
    inputValue
})

// 定义事件
const emit = defineEmits(['customInput'])

function watchValue() {
    if (inputValue.value == 'abcd'){
        emit('customInput', inputValue.value);
    }
}
</script>

<template>
  <div class="container">
    <div>{{ props.labelName }}</div>
    <input type="text" v-model="inputValue" class="input" @input="watchValue">
  </div>
</template>

<style scoped>

.container {
  width: 100%;
  height: 100%;
}
.input {
    width: 100%;
    height: auto;
    line-height: 100%;
    font-size: 18px;
}
</style>

【子组件向父组件传递参数/方法】App.vue

<script setup>
import { ref } from 'vue'
import myInput from './components/child.vue'
const name = ref('用户名')
// 使用ref获取子组件的DOM节点
const input = ref(null)

function clearInput() {
    input.value.inputValue = ''
}
function Pop(value){
  console.log(value);
  alert(value);
}
</script>

<template>
  <div class="container">
      <myInput 
        labelName="用户名"
        ref="input"
        @customInput="Pop"
      />
      <button @click="clearInput">清空</button>
  </div>
</template>

<style scoped>
.container {
    width: 300px;
    height: auto;
    margin: 20px auto;
}
</style>

效果:

总结

  • 子组件主动的向父组件传递消息:使用defineEmits
  • 子组件被动的接收父组件传递消息:使用defineExpose
  • 子组件初始化的接收父组件传递消息:使用defineProps

四、defineProps、defineEmits、defineExpose方法介绍

defineProps、defineEmits

  • definePropsdefineEmits只能在<script setup>中使用,不需要被导入
  • definePropsdefineEmits可以对传入值进行类型约束
const props = defineProps({
    test:{
        type: String,
        default: '测试',
        required: true,
        validator:(value) => {
          if (value.length > 5){
            return false
          }
          else {
            return true
          }
        }
    }
})
  • type:指定prop的类型,例如String、Number、Boolean、Object、Array、Func
  • default:指定prop默认值
  • required:表明该prop是否为必需项
  • validator:自定义验证函数,用于对传入的prop值进行验证,返回true表示验证通过,返回false表示验证失败

响应式Props结构:

Vue3.5及以上版本中,从defineProps返回值解构出的变量是响应式的

const { foo } = defineProps(['foo'])
// 使用数组形式定义事件
const emit = defineEmits(['messageSent']);

// 或者使用对象形式定义事件并进行参数验证
// const emit = defineEmits({
//   messageSent: (payload) => {
//     if (typeof payload === 'string') {
//       return true;
//     } else {
//       console.warn('messageSent 事件的参数必须是字符串');
//       return false;
//     }
//   }
// });
  • 使用对象形式定义事件时,以键值对的形式,对参数进行验证

defineExpose

子组件

<template>
  <div>
    <p>子组件内容</p>
  </div>
</template>

<script setup>
import { ref } from 'vue';

// 定义子组件内部的响应式数据
const innerCount = ref(0);

// 定义子组件内部的方法
const increment = () => {
  innerCount.value++;
};

// 使用 defineExpose 暴露属性和方法
defineExpose({
  innerCount,
  increment
});
</script>

<style scoped>
/* 子组件样式 */
</style>

父组件

<template>
  <div>
    <ChildComponent ref="childRef" />
    <button @click="callChildMethod">调用子组件方法</button>
    <p>子组件的计数: {{ childRef?.innerCount }}</p>
  </div>
</template>

<script setup>
import { ref } from 'vue';
import ChildComponent from './ChildComponent.vue';

// 创建一个 ref 来引用子组件
const childRef = ref(null);

// 调用子组件暴露的方法
const callChildMethod = () => {
  if (childRef.value) {
    childRef.value.increment();
  }
};
</script>

<style scoped>
/* 父组件样式 */
</style>

相关文章:

  • Halcon算子 二维码识别、案例
  • AI 时代的通信新范式:MCP(模块化通信协议)的优势与应用
  • openvela新时代的国产开源RTOS系统
  • [网络安全] 滥用Azure内置Contributor角色横向移动至Azure VM
  • QA:备份产品的存储架构采用集中式和分布式的优劣?
  • 如何配置本地git
  • QT软件匠心开发,塑造卓越设计服务
  • 智慧港口新未来:大数据赋能应急消防,筑牢安全防线
  • 关于numpy里面的轴(axis)
  • w264民族婚纱预定系统
  • Python 爬虫(4)HTTP协议
  • 如何提高G口服务器的安全性?
  • 【技术简析】触觉智能RK3506 Linux星闪网关开发板:重新定义工业物联新标杆
  • 星越L_ 雨刷使用功能讲解
  • IDA调试时对异常的处理
  • Maven 简介及其核心概念
  • MySql中 一条select语句的执行流程
  • 使用DeepSeek翻译英文科技论文,以MarkDown格式输出,使用Writage 3.3.1插件转换为Word文件
  • 使用AMD方式,加载supermap iclient Cesium.js v11.2.1
  • 双核锁步技术在汽车芯片软错误防护中的应用详解
  • 埃尔多安:愿在土耳其促成俄乌领导人会晤
  • 向猫学习禅修之后,你会发现将生活降格为劳作是多么愚蠢
  • 上海锦江乐园摩天轮正在拆除中,预计5月底6月初拆完
  • 上海静安将发放七轮文旅消费券,住宿券最高满800元减250元
  • 美叙领导人25年来首次会面探索关系正常化,特朗普下令解除对叙经济制裁
  • 美国与卡塔尔签署超2435亿美元经济及军事合作协议