【Vue】自定义组件

系列文章目录

第六章 自定义组件


文章目录


一、定义属性

有时候我们定义一个组件后,需要让调用者传入参数,那么就可以将参数定义成属性。示例代码如下:

Person组件代码:

html 复制代码
<script setup name="Person">
// Person组件
import {defineProps} from "vue";

// 1. 使用数组的形式
//const props = defineProps(['username'])
// 2. 使用对象的形式
const props = defineProps({
    gender: {
        type: String,
        default: '男'
    },
    username: String,
    age: Number,
    body: {
        height: Number,
        weight: Number
    }
})

</script>

<template>
<p>
    用户名:{{ props.username }},
    年龄:{{ props.age }},
    身高:{{ props.body.height }},
    体重:{{ props.body.weight }}
</p>
</template>

App.vue组件代码:.

html 复制代码
<script setup>
import Person from "./components/Person.vue"
</script>

<template>
<Person :age="18" username="张三" :body="{height: 180, weight: 140}"></Person>
</template>

子组件不能修改父组件传过来的props ,否则会引起错误。

二、自定义事件

子组件可以自定义事件,然后父组件可以实现发生这个事件的处理函数。示例代码如下:

Person.vue组件:

html 复制代码
<script setup name="Person">
import {defineEmits, ref} from "vue";

let steps = ref(0);

const emit = defineEmits(['change']);

const onUpdate = () => {
    steps.value += 10
    emit('change', steps.value);
}

</script>

<template>
<button @click="onUpdate">行走10步</button>
</template>

App.vue组件:

html 复制代码
<script setup>
import Person from "./components/Person.vue"

const onPersonChange = (steps) => {
    console.log("步行了:", steps);
}
</script>

<template>
<Person @change="onPersonChange"></Person>
</template>

三、定义v-model

使用v-model 可以定义一个在父组件和子组件中双向绑定的对象。示例代码如下:

Person.vue组件代码:

html 复制代码
<script setup name="Person">
import {defineModel, watch} from "vue";

let steps = defineModel();
const onUpdate = () => {
    steps.value += 10;
}
watch(steps, (newValue, oldValue) => {
    console.log("Person中监听到steps:", newValue);
})

</script>

<template>
<button @click="onUpdate">行走10步</button>
</template>

App.vue组件代码:

html 复制代码
<script setup>
import {ref, watch} from "vue";
import Person from "./components/Person.vue"

let steps = ref(0);
watch(steps, (newValue, oldValue) => {
    console.log("App中监听到的:", newValue);
})
</script>

<template>
<Person v-model="steps"></Person>
</template>

四、插槽

插槽(Slots)在Vue中是一种非常重要的内容组织方式,它能够让你在子组件中留下预先定义的位置,然后在父组件中填充这些位置。

1. 基本使用:

示例代码如下:

SubmitButton.vue代码:

html 复制代码
<template>
<button type="submit">
    <slot></slot>
</button>
</template>

App.vue代码:

html 复制代码
<template>
<SubmitButton>登录</SubmitButton>
</template>

"登录"这个文本就会填充在SubmitButton的slot标签处。或者也可以在定义插槽的时候指定默认值,比如:

html 复制代码
// SubmitButton.vue代码
<template>
<button type="submit">
    <slot>提交</slot>
</button>
</template>

那么以后在使用SubmitButton组件的时候,使用 也会有提交两个文字。

2. 具名插槽:

如果在一个组件中想要定义多个插槽,则可以使用"具名"插槽,就是给每个插槽指定一个名称,父组件使用的时候,也要指明相应代码要放到哪个插槽下,比如我们定义一个BaseLayout 组件:

html 复制代码
<div class="container">
  <header>
    <!-- 标题内容放这里 -->
  </header>
  <main>
    <!-- 主要内容放这里 -->
  </main>
  <footer>
    <!-- 底部内容放这里 -->
  </footer>
</div>

其中header 、main 、footer 是由父组件自由指定的,那么组件的代码可以修改为:

html 复制代码
<div class="container">
  <header>
    <slot name="header"></slot>
  </header>
  <main>
    <slot></slot>
  </main>
  <footer>
    <slot name="footer"></slot>
  </footer>
</div>

其中有三个插槽,分别是header、默认的插槽、以及footer插槽。那么在父组件中可以按照如下方式使用:

html 复制代码
<BaseLayout>
  <template #header>
    <h1>Here might be a page title</h1>
  </template>

  <template #default>
    <p>A paragraph for the main content.</p>
    <p>And another one.</p>
  </template>

  <template #footer>
    <p>Here's some contact info</p>
  </template>
</BaseLayout>

对于default插槽,可以不用指明名称,因此也可以如下使用:

html 复制代码
<BaseLayout>
  <template #header>
    <h1>Here might be a page title</h1>
  </template>

  <!-- 隐式的默认插槽 -->
  <p>A paragraph for the main content.</p>
  <p>And another one.</p>

  <template #footer>
    <p>Here's some contact info</p>
  </template>
</BaseLayout>

3. 插槽作用域:

在父组件中,如果使用插槽,则插槽中的代码是无法访问子组件中的变量的。如果想要访问,那么必须在定义插槽的时候显示指定。示例代码如下:

BaseLayout.vue组件代码:

html 复制代码
<div class="container">
  <header>
    <slot name="header" :tab="1"></slot>
  </header>
  <main>
    <slot :card="2"></slot>
  </main>
  <footer>
    <slot name="footer" :box="3"></slot>
  </footer>
</div>

App.vue组件代码:以后在父组件中,可以通过以下方式,获取到子组件中传递过来的插槽信息:

html 复制代码
<BaseLayout>
  <template #header="headerProps">
    {{ headerProps }}
  </template>

  <template #default="defaultProps">
    {{ defaultProps }}
  </template>

  <template #footer="footerProps">
    {{ footerProps }}
  </template>
</BaseLayout>

相关推荐
编程零零七3 小时前
Python数据分析工具(三):pymssql的用法
开发语言·前端·数据库·python·oracle·数据分析·pymssql
北岛寒沫4 小时前
JavaScript(JS)学习笔记 1(简单介绍 注释和输入输出语句 变量 数据类型 运算符 流程控制 数组)
javascript·笔记·学习
everyStudy4 小时前
JavaScript如何判断输入的是空格
开发语言·javascript·ecmascript
(⊙o⊙)~哦5 小时前
JavaScript substring() 方法
前端
无心使然云中漫步5 小时前
GIS OGC之WMTS地图服务,通过Capabilities XML描述文档,获取matrixIds,origin,计算resolutions
前端·javascript
Bug缔造者5 小时前
Element-ui el-table 全局表格排序
前端·javascript·vue.js
xnian_6 小时前
解决ruoyi-vue-pro-master框架引入报错,启动报错问题
前端·javascript·vue.js
罗政6 小时前
[附源码]超简洁个人博客网站搭建+SpringBoot+Vue前后端分离
vue.js·spring boot·后端
麒麟而非淇淋7 小时前
AJAX 入门 day1
前端·javascript·ajax
2401_858120537 小时前
深入理解MATLAB中的事件处理机制
前端·javascript·matlab