【Vue】——组件之间数据的传递
💻博主现有专栏:
C51单片机(STC89C516),c语言,c++,离散数学,算法设计与分析,数据结构,Python,Java基础,MySQL,linux,基于HTML5的网页设计及应用,Rust(官方文档重点总结),jQuery,前端vue.js,Javaweb开发,设计模式、Python机器学习等
🥏主页链接:
目录
🎃创建 TodoList.vue组件,接收来自App.vue中todoList中的数据,并将数据渲染到表格中。(父组件向子组件传递数据)
🎃创建 TodoInput.vue组件,实现任务添加功能。(子组件向父组件传递数据)
🎯创建 TodoButton.vue组件,实现任务删选功能。(子组件向父组件传递数据)
🎯本文目的
(一)掌握vue项目中组件的注册与引用;
(二)掌握vue项目中组件之间的数据传递。
🎯实现一个“投票”
🎃要求
要求:1、掌握父组件向子组件传递数据的方法(利用组件的自定义属性)。
2、掌握子组件向父组件传递数据的方法(利用组件的自定义事件)。
3、单击每位被投票人下面的按钮可以为其投票,在按钮后面显示当前的总票数,同时在页面下方显示每位投票人的详细信息,包括投票时间、投票人的姓名和总票数。
🎃打开App.vue文件添加代码
<template> <div class="vote-wrapper"> <h1>请为您最喜欢的人投票—</h1> <ul> <li v-for="item in list" v-bind:key="item.id"> <div class="img"> <img v-bind:src="item.avatar" v-bind:alt="item.name"> </div> <Greeting v-bind:to="item.name" @toupiao="onClick"></Greeting> <!--引用greeting.vue组件--> </li> </ul> <p v-for="(item, index) in appList" v-bind:key="index"> {{item.time}} - {{item.name}} - {{item.count}}票 </p> </div> </template> <script setup> import { reactive } from 'vue' import Greeting from './components/greeting.vue' //导入并注册greeting.vue组件 const list = [ { id: 1, avatar: '/src/assets/images/jane.png', name: 'Jane' }, { id: 2, avatar: '/src/assets/images/mike.png', name: 'Mike' }, { id: 3, avatar: '/src/assets/images/kate.png', name: 'Kate' }, { id: 4, avatar: '/src/assets/images/tom.png', name: 'Tom' } ] const appList = reactive([]) //存储投票信息 const onClick = (name, count) => { //接收子组件传递过来的数据 console.log(name, count) appList.push({ time: new Date().toLocaleTimeString(), name, count }); } </script> <style scoped> .vote-wrapper { border: 1px solid #999; border-radius: 10px; width: 600px; margin: auto; } .vote-wrapper h1 { text-align: center; } ul { display: flex; justify-content: space-around; padding: 25px; border-top: 1px solid #999; margin: 0; } li { list-style: none; text-align: center; } li .img { width: 110px; border: 1px solid #999; border-radius: 10px; margin-bottom: 20px; } li .img img { width: 100%; } p { text-align: center; } </style>
这段代码是一个Vue.js组件,用于创建一个投票页面。用户可以在这个页面上为四个候选人(Jane、Mike、Kate和Tom)进行投票。
首先,我们来看一下HTML部分:
1. `<template>`标签内包含了整个投票页面的结构。
2. `<div class="vote-wrapper">`是投票页面的主要容器。
3. `<h1>`标签显示了投票的主题。
4. `<ul>`标签包含了四个候选人的信息。
5. `<li>`标签表示每个候选人的信息。
6. `<div class="img">`标签用于显示候选人的头像。
7. `<img>`标签用于显示候选人的头像图片。
8. `Greeting`组件用于显示候选人的名字和投票数。
9. `{{item.time}} - {{item.name}} - {{item.count}}票`用于显示投票的时间、候选人的名字和投票数。接下来,我们看一下JavaScript部分:
1. 导入了`reactive`函数,用于创建响应式数据。
2. 导入了`Greeting`组件。
3. 定义了一个名为`list`的数组,包含了四个候选人的信息。
4. 定义了一个名为`appList`的响应式数组,用于存储投票信息。
5. 定义了一个名为`(name, count)`的函数,用于接收子组件传递过来的数据。当用户投票时,这个函数会被调用,并将投票信息添加到`appList`数组中。最后,我们看一下CSS部分:
1. 定义了`.vote-wrapper`类的样式,包括边框、宽度等。
2. 定义了`h1`标签的样式,包括文本居中等。
3. 定义了`ul`标签的样式,包括布局、边框等。
4. 定义了`li`标签的样式,包括列表样式、文本居中等。
5. 定义了`.img`类的样式,包括宽度、边框等。
6. 定义了`img`标签的样式,包括宽度等。
7. 定义了`p`标签的样式,包括文本居中等。总的来说,这段代码实现了一个简单的投票页面,用户可以为候选人进行投票,并查看投票结果。
🎃实现投票人图片下面按钮的投票功能
<template> <button class="greeting" v-on:click="btn">{{to}}</button> <span v-if="count > 0"> x {{ count }}</span> </template> <script setup> import { ref } from 'vue' const props=defineProps(['to']) //声明自定义属性 const emit = defineEmits(['toupiao']) //声明自定义事件 let count = ref(0) const btn = () => { if (count.value < 10) { count.value++; emit('toupiao',props.to, count.value); //触发自定义事件时将数据传递 } } </script> <style scoped> .greeting { border: 1px solid #ccc; padding: 5px; border-radius: 5px; cursor: pointer; outline: none; margin-left: 10px; } </style>
这段代码是一个Vue.js组件,用于创建一个带有投票功能的按钮。下面是对代码的详细解释和分析:
1. 模板部分(`<template>`):
- `<button class="greeting" v-on:click="btn">{{to}}</button>`:创建一个按钮元素,类名为"greeting",点击时触发名为"btn"的方法。按钮上显示的内容为"{{to}}",这是一个动态绑定的属性,表示按钮上的文字内容。
- `<span v-if="count > 0"> x {{ count }}</span>`:创建一个条件渲染的`<span>`元素,当变量"count"的值大于0时才会显示。这个元素用于显示投票次数,其中"{{ count }}"是动态绑定的变量,表示投票次数。2. 脚本部分(`<script>`):
- `import { ref } from 'vue'`:从Vue.js中导入ref函数,用于创建响应式数据。
- `const props=defineProps(['to'])`:声明一个名为"props"的自定义属性,它接收一个数组作为参数,数组中的元素是该组件需要接收的外部传入的属性名。在这个例子中,只有一个属性"to",用于设置按钮上的文字内容。
- `const emit = defineEmits(['toupiao'])`:声明一个名为"emit"的自定义事件,它接收一个数组作为参数,数组中的元素是该组件可以触发的事件名。在这个例子中,只有一个事件"toupiao",用于在投票时触发。
- `let count = ref(0)`:使用ref函数创建一个响应式数据"count",并将其初始值设置为0。这个变量用于记录投票次数。
- `const btn = () => {...}`:定义一个名为"btn"的方法,用于处理按钮的点击事件。
- `if (count.value < 10) {...}`:判断当前投票次数是否小于10,如果是,则执行以下操作:
- `count.value++`:将投票次数加1。
- `emit('toupiao',props.to, count.value)`:触发名为"toupiao"的自定义事件,并传递两个参数:props.to(按钮上的文字内容)和count.value(投票次数)。3. 样式部分(`<style scoped>`):
- `.greeting {...}`:定义一个名为"greeting"的CSS类,用于设置按钮的样式。包括边框、内边距、圆角、光标样式、轮廓以及左边距等。这段代码的功能是创建一个带有投票功能的按钮,用户可以通过点击按钮进行投票,每次点击会增加投票次数,并且当投票次数小于10时会触发名为"toupiao"的自定义事件,并将按钮上的文字内容和投票次数作为参数传递给该事件。
🎃运行效果
🎯实现一个“本周任务管理”
🎃要求
要求:1、掌握组父子组件之间的数据传递和父子组件之间数据的同步。
2、在文本框中输入任务,按下enter键或单击“添加新任务”,将新任务添加到列表下方。(TodoInput.vue向App.vue传递数据)
3、选中任务前面的复选框,将显示该项目完成。(TodoList.vue向App.vue传递数据)
4、单击“全部”、“已完成”和“未完成”按钮,任务列表中显示对应的任务。(用到了父子组件之间数据的同步)
🎃创建 TodoList.vue组件,接收来自App.vue中todoList中的数据,并将数据渲染到表格中。(父组件向子组件传递数据)
<template> <ul class="list-group"> <li class="list-group-item d-flex justify-content-between align-items-center" v-for="item in list" :key="item.id"> <!-- 复选框 --> <div class="custom-control custom-checkbox"> <input type="checkbox" class="custom-control-input" :id="item.id"v-model="item.done" /> <label class="custom-control-label" :for="item.id":class="item.done ?'delete' :''"> {{item.task }} </label> </div> <!-- badge 效果 --> <span class="badge badge-success badge-pill"v-if="item.done">完成</span> <span class="badge badge-warning badge-pill"v-else>未完成</span> </li> </ul> </template> <script setup> const props=defineProps({ // 表格的数据源 list: { //声明自定义属性 type: Array, required: true, default: [], } }) </script> <style scoped> /* 为列表设置固定宽度 */ .list-group { width: 700px; } /* 删除效果 */ .delete { text-decoration: line-through; } </style>
这段代码是一个Vue.js组件,用于显示一个任务列表。每个任务都有一个复选框,用于标记任务是否完成。如果任务完成,任务文本会被划掉,并在任务旁边显示"完成"的徽章;如果任务未完成,任务文本不会被划掉,并在任务旁边显示"未完成"的徽章。
代码的主要部分包括HTML模板、JavaScript代码和CSS样式。
HTML模板:
- 使用`<ul>`元素创建一个无序列表,类名为"list-group"。
- 使用`v-for`指令遍历名为"list"的数组,为每个数组元素生成一个`<li>`元素。
- 在每个`<li>`元素中,使用`<div>`元素创建一个复选框,类名为"custom-control custom-checkbox"。复选框的状态由数组元素的"done"属性决定。
- 使用`<label>`元素显示任务文本,类名根据"done"属性的值决定是否添加"delete"类。
- 根据"done"属性的值,使用`v-if`和`v-else`指令在任务旁边添加"完成"或"未完成"的徽章。JavaScript代码:
- 使用`defineProps`函数定义一个名为"list"的自定义属性,类型为数组,默认值为空数组。这个属性是组件的数据源。CSS样式:
- 为"list-group"类设置固定宽度为700px。
- 为"delete"类设置文本装饰为划线,实现删除效果。
🎃创建 TodoInput.vue组件,实现任务添加功能。(子组件向父组件传递数据)
<template> <!-- form 表单 --> <form class="form-inline" @submit.prevent="onFormSubmit"> <div class="input-group mb-2 mr-sm-2"> <!-- 输入框的前缀 --> <div class="input-group-prepend"> <div class="input-group-text">任务</div> </div> <!-- 文本输入框 --> <input type="text" class="form-control" placeholder="请填写任务信息" style="width: 356px" v-model.trim="taskname"/> </div> <!-- 添加按钮 --> <button type="submit" class="btn btn-primary mb-2">添加新任务</button> </form> </template> <script setup> import { ref } from 'vue' const taskname = ref('') const emit = defineEmits(['add']) //自定义事件 // 表单提交的事件处理函数 const onFormSubmit = () => { // 1. 判断任务名称是否为空 if (!taskname.value) return alert("任务名称不能为空!"); // 2. 触发自定义的 add 事件,并向外界传递数据 emit('add', taskname.value) // 3. 清空文本框 taskname.value = '' } </script>
这段代码是一个Vue.js组件,用于创建一个表单,用户可以在其中输入任务名称并提交。
首先,我们来看一下HTML部分:
这是一个表单,包含一个输入框和一个提交按钮。输入框用于输入任务名称,提交按钮用于提交表单。
v-model.trim="taskname"
表示输入框的值与taskname
变量双向绑定,并且在输入时会自动去除前后的空格。接下来,我们看一下JavaScript部分:
首先,我们导入了
ref
函数,这是Vue.js提供的一个工具函数,用于创建响应式的数据。然后,我们创建了一个名为
taskname
的响应式数据,初始值为空字符串。接着,我们定义了一个自定义事件
add
,这个事件可以在组件内部触发,并向外界传递数据。最后,我们定义了一个名为
onFormSubmit
的事件处理函数,这个函数会在表单提交时被调用。在这个函数中,我们首先判断任务名称是否为空,如果为空则返回错误信息。然后,我们触发了自定义的add
事件,并向外界传递了任务名称。最后,我们将任务名称清空,以便下次输入。
🎯创建 TodoButton.vue组件,实现任务删选功能。(子组件向父组件传递数据)
<template> <div class="button-container mt-3"> <div class="btn-group"> <button type="button" class="btn" :class="active === 0 ? 'btn-primary' : 'btn-secondary'"@click="btnClick(0)">全部 </button> <button type="button" class="btn" :class="active === 1 ? 'btn-primary' : 'btn-secondary'"@click="btnClick(1)">已完成 </button> <button type="button" class="btn" :class="active === 2 ? 'btn-primary' : 'btn-secondary'"@click="btnClick(2)">未完成 </button> </div> </div> </template> <style scoped> .button-container { width: 700px; text-align: center; } </style> <script setup> import { ref } from 'vue' const active = ref(0) const emit = defineEmits(['updateActive']) const btnClick = (index) => { active.value = index emit('updateActive', index) } </script>
这段代码是一个Vue组件,用于创建一个包含三个按钮的按钮组。每个按钮都有一个点击事件,当点击时,会触发一个名为"updateActive"的事件,并将对应的索引值传递给该事件。
首先,我们来看一下模板部分:
这是一个使用Bootstrap样式的按钮组,包含三个按钮。每个按钮都有一个`@click`事件监听器,当点击按钮时,会调用`btnClick`方法,并传递一个参数(0、1或2),分别代表"全部"、"已完成"和"未完成"这三个选项。按钮的样式会根据`active`的值动态改变,如果`active`等于按钮的索引值,那么按钮的样式为`btn-primary`,否则为`btn-secondary`。
接下来,我们看一下样式部分:
这里定义了一个名为`.button-container`的样式类,设置了宽度为700px,文本居中对齐。
最后,我们看一下脚本部分:
首先,我们从`vue`中导入了`ref`函数,用于创建响应式引用。然后,我们创建了一个名为`active`的响应式引用,初始值为0。接着,我们定义了一个名为`emit`的函数,用于触发自定义事件。最后,我们定义了一个名为`btnClick`的方法,当点击按钮时,会更新`active`的值,并触发名为"updateActive"的自定义事件,同时传递当前按钮的索引值。
🎃修改App.vue组件
<template> <div> <h1>本周任务管理</h1> <hr /> <TodoInput @add="onAddNewTask"></TodoInput> <TodoList :list="tasklist"></TodoList> <!-- 使用TodoList组件 --> <TodoButton :active="activeBtnIndex" @updateActive="changeActive"></TodoButton> </div> </template> <script setup> import TodoInput from './components/TodoInput.vue'; import TodoList from './components/TodoList.vue' //导入并注册TodoList组件 import { reactive, ref,computed } from 'vue' import TodoButton from './components/TodoButton.vue'; // 任务列表的数据 const todoList = reactive([ { id: 1, task: '周一早晨9点开会', done: false }, { id: 2, task: '周一晚上8点聚餐', done: false }, { id: 3, task: '准备周三上午的演讲稿', done: true }, { id: 4, task: '准备周四上午的课件', done: false }, { id: 5, task: '准备周五上午的实验指导', done: false }, ] ) const nextId = ref(6) //下一条数据的id值 const onAddNewTask = (tname) => { // 1. 向任务列表中新增任务信息 todoList.push({ id: nextId.value, task: tname, done: false, // 完成状态默认为 false }); // 2. 让 nextId 自增+1 nextId.value++; } const activeBtnIndex = ref(0) //用来接收子组件传过来的数据,注意ref需按需导入 const changeActive = (status) => { console.log(status) activeBtnIndex.value = status // 将子组件的状态赋值给父组件 } // 根据激活按钮的索引值,动态计算要展示的列表数据 const tasklist=computed(()=>{ // 对“源数据”进行 switch...case 的匹配,并返回“计算之后的结果” switch (activeBtnIndex.value) { case 0: // 全部 return todoList; case 1: // 已完成 return todoList.filter((x) => x.done); case 2: // 未完成 return todoList.filter((x) => !x.done); } }) </script>
这段代码是一个Vue.js的组件,用于实现一个简单的任务管理功能。主要包含三个子组件:TodoInput、TodoList和TodoButton。
1. TodoInput组件:用于输入新的任务。当用户输入新任务并点击添加按钮时,会触发onAddNewTask方法,将新任务添加到任务列表中。
2. TodoList组件:用于展示任务列表。它接收一个名为list的属性,该属性的值是一个数组,包含了所有的任务信息。
3. TodoButton组件:用于切换任务列表的显示状态。它接收两个属性,一个是active,表示当前激活的按钮索引;另一个是updateActive,当用户点击按钮时,会触发这个方法,更新父组件中的activeBtnIndex值。
在父组件中,定义了一个响应式数组todoList,用于存储所有的任务信息。同时,定义了一个ref类型的变量nextId,用于生成新任务的id。定义了一个computed类型的变量tasklist,根据activeBtnIndex的值,动态计算要展示的任务列表。
当用户点击TodoButton组件的按钮时,会触发changeActive方法,更新activeBtnIndex的值,从而改变tasklist的值,实现了任务列表的动态展示。
🎃运行效果
更多推荐
所有评论(0)