【Vue】——组件之间数据的传递

💻博主现有专栏:

                C51单片机(STC89C516),c语言,c++,离散数学,算法设计与分析,数据结构,Python,Java基础,MySQL,linux,基于HTML5的网页设计及应用,Rust(官方文档重点总结),jQuery,前端vue.js,Javaweb开发,设计模式、Python机器学习等
🥏主页链接:

                Y小夜-CSDN博客

目录

🎯本文目的

🎯实现一个“投票”

🎃要求

🎃打开App.vue文件添加代码

🎃实现投票人图片下面按钮的投票功能

🎃运行效果

🎯实现一个“本周任务管理”

🎃要求

🎃创建 TodoList.vue组件,接收来自App.vue中todoList中的数据,并将数据渲染到表格中。(父组件向子组件传递数据)

🎃创建 TodoInput.vue组件,实现任务添加功能。(子组件向父组件传递数据)

🎯创建 TodoButton.vue组件,实现任务删选功能。(子组件向父组件传递数据)

🎃修改App.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的值,实现了任务列表的动态展示。

🎃运行效果

  • 24
    点赞
  • 33
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Y小夜

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值