日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 前端技术 > vue >内容正文

vue

「后端小伙伴来学前端了」Vue中Props 实现组件通信TodoList案例

發布時間:2025/3/19 vue 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 「后端小伙伴来学前端了」Vue中Props 实现组件通信TodoList案例 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.


自己拍的小云彩

源碼在文末。

前言

上篇文章寫了個V利用Props進行組件之間的通信,這不立馬就安排上這個案例拉丫。光學不敲等于沒學哈(資深大佬除外哈)

目標就是實現如下的樣子:

能夠進行增刪改查,并且是在各個組件之間。

一、環境準備

針對這個頁面,我們將他們劃分為下面四個組件哈。其實也不是固定的,只是為了更好的展示組件之間的通信。

項目結構:

準備靜態頁面

MyTodoHeader頭部組件:

<template><div class="todo-header-box"><input type="text" placeholder="請輸入你的任務名稱,按回車鍵確認" v-model="title"/></div> </template> <script> import { v4 as uuidv4 } from 'uuid' export default {props: {},data () {return {title: ''}},methods: {} } </script> <style scoped> .todo-header-box{width: 500px;height: 40px;margin-top:10px; } .todo-header-box input{width: 460px;height: 40px;margin-left: 10px;border: 1px solid #43B984;border-radius: 8px;padding-left: 10px; } :focus-visible{ outline:none; } </style>

MyTodoList組件,另外組件內還包含著MyTodoItem組件

<template> <ul class="todo-main"><TodoItem v-for="(todo, index) in todos" :key="index" :todo="todo"/></ul> </template> <script> import TodoItem from './MyTodoItem' export default {components: {TodoItem},props: {},methods: {} } </script> <style scoped> /*main*/ .todo-main {margin-top: 10px;margin-left: 0px;border: 1px solid #ddd;border-radius: 2px;padding: 0px; }.todo-empty {height: 40px;line-height: 40px;border: 1px solid #ddd;border-radius: 2px;padding-left: 5px;margin-top: 10px; }/*item*/ li {list-style: none;height: 36px;line-height: 36px;padding: 0 5px;border-bottom: 1px solid #ddd; }li label {float: left;cursor: pointer; }li label li input {vertical-align: middle;margin-right: 6px;position: relative;top: -1px; }li button {float: right;display: none;margin-top: 3px; }li:before {content: initial; }li:last-child {border-bottom: none; } </style>

MyTodoItem組件

<template><li :style="{background: bgColor}"><label><input type="checkbox" :checked="todo.done" /><span>{{todo.title}}</span></label><button class="btn btn-danger" style="display:none" v-show="isShow">刪除</button></li> </template><script> export default {props: {todo: Object},data () {return {bgColor: 'white',isShow: false}},methods: {} } </script>

MyTodoFooter組件

<template><div class="todo-footer" v-show="total"><label><!-- // 第一種方式:通過dom元素來判斷有沒有進行勾選 不是最佳方式 --><!-- <input type="checkbox" :checked="isAllCheck" @click="checkAll" /> --><!-- 第二種方式: 通過綁定計算屬性來進行展示 --><input type="checkbox" v-model="isAllCheck" /></label><span>已完成{{ doneTotal }}<span> / 全部{{ todos.length }} </span></span><buttonclass="btn btn-danger">清除已完成任務</button></div> </template><script> export default {props: {todos: Array,clearDoneTodos: Function,checkAllTodos: Function},computed: {total () {return this.todos.length},doneTotal () {return this.todos.reduce((preTotal, todo) => preTotal + (todo.done ? 1 : 0), 0)},isAllCheck: {get () {return this.doneTotal === this.todos.length && this.doneTotal > 0}}},methods: {} } </script> /*footer*/ <style scoped> .todo-footer {height: 40px;line-height: 40px;padding-left: 6px;margin-top: 5px; }.todo-footer label {display: inline-block;margin-right: 20px;cursor: pointer; }.todo-footer label input {position: relative;top: -1px;vertical-align: middle;margin-right: 5px; }.todo-footer button {float: right;margin-top: 5px; } </style>

App組件

<template><div class="todo-container"><!-- header模塊 --><TodoHeader/><!-- main 模塊 --><TodoList :todos="todos"/><!-- 主要的內容模塊 --><TodoFooter :todos="todos"/><!-- footer模塊 --></div> </template> <script> import TodoHeader from './components/MyTodoHeader' import TodoList from './components/MyTodoList' import TodoFooter from './components/MyTodoFooter'export default {components: {TodoHeader,TodoList,TodoFooter},data () {return {todos: [{ id: '001', title: '吃飯', done: true },{ id: '002', title: '睡覺', done: false },{ id: '003', title: '敲代碼', done: true }]}},methods: {}} </script> <style> * {margin: 0 0;padding: 0 0; } .todo-container {margin: 0 auto;margin-top: 10px;width: 500px;height: 500px;background-color: #ccc;border: 1px solid #ddd;border-radius: 8px; } </style>

二、在頭部組件中實現增加方法

首先說說我們的需求:

就是在頭部組件中的輸入框中進行輸入,然后按下回車鍵就將數據增加到todos數組中,并在下面的列表中展示出來。

思路大致如下:

  • 首先我們要明確數據我們是存儲在App組件中的,那么我們真實修改的方法也應該寫在App組件中。由App組件將方法傳遞給子組件(MyTodoHead)組件。
  • 在子組件中通過Props進行接收
  • 最后再在子組件的input中定義一個回車事件,觸發父組件中的增加方法,進行數據的更新。
  • App組件中修改:

    <template><div class="todo-container"><!-- header模塊:addTodo 定義的是子組件接收的名稱"addTodo" 指向的是此組件中所定義的方法 --><TodoHeader :addTodo="addTodo" /><!-- main 模塊 --><TodoList :todos="todos" /><!-- 主要的內容模塊 --><TodoFooter :todos="todos"/><!-- footer模塊 --></div> </template> <script> import TodoHeader from './components/MyTodoHeader' import TodoList from './components/MyTodoList' import TodoFooter from './components/MyTodoFooter'export default {components: {TodoHeader,TodoList,TodoFooter},data () {return {message: 'hello',todos: [{ id: '001', title: '吃飯', done: true },{ id: '002', title: '睡覺', done: false },{ id: '003', title: '敲代碼', done: true }]}},methods: {// 回車增加一個todoaddTodo (todo) {this.todos.unshift(todo)}} } </script>

    我們通過:addTodo="addTodo"傳遞給子組件一個方法,然后在子組件中我們用props來接收。

    <template><div class="todo-header-box"><input type="text" placeholder="請輸入你的任務名稱,按回車鍵確認" v-model="title" @keyup.enter="add"/></div> </template> <script> import { v4 as uuidv4 } from 'uuid' export default {props: {// 通過props來接收addTodo: Function},data () {return {title: ''}},methods: {add () {// 1. 檢查輸入合法性const title = this.title.trim()if (!title) {alert('請輸入內容')return}const id = uuidv4()// 2. 根據輸入生成一個todo對象const todo = { id, title, done: false }// 3. 這里的this.addTodo 調用的實際上就是執行父組件中的addTodo函數 //添加到todosthis.addTodo(todo)// 4. 清除輸入this.title = ''}} } </script>

    這里我使用到了uuid生成全局唯一id。

    安裝方式:

    npm install uuid --save # 引用的話直接 import { v4 as uuidv4 } from 'uuid'; # 用法: 直接調用這個函數即可 uuidv4(); // ? '9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d'

    三、完善 MyTodoList 組件 | 根據id刪除一條todo&判斷是否選中

    先說說需求:

  • 鼠標經過每個todo上顯示刪除按鈕,可以點擊刪除
  • 判斷是否勾選,即判斷是否已完成
  • 其實還有第三個的哈,我沒寫了(懶了),第三個是編輯,大家可以試一試.

    如下圖:

    思路其實蠻簡單的哈:

  • 點擊刪除,只要傳個id即可,雖然是祖孫組件之間傳值,但其實就是將方法傳了兩層,借助了List組件做個中介,接收完再傳遞給item組件而已
  • 判斷是否已完成也一樣,都是借助了list組件傳遞,實現祖孫組件通信.
  • MyTodoList組件

    <template> <ul class="todo-main"><TodoItem v-for="(todo, index) in todos" :key="index" :todo="todo" :deleteTodo="deleteTodo" :checkTodo="checkTodo" /></ul> </template> <script> import TodoItem from './MyTodoItem' export default {components: {TodoItem},props: {todos: Array,deleteTodo: Function,checkTodo: Function},methods: {} } </script>

    MyTodoItem組件

    <template><li @mouseenter="handleEnter(true)" @mouseleave="handleEnter(false)" :style="{background: bgColor}"><label><input type="checkbox" :checked="todo.done" @click="handlerCheck(todo.id)" /><span>{{todo.title}}</span></label><button class="btn btn-danger" style="display:none" v-show="isShow" @click="handlerDeleteItem(todo.id)">刪除</button></li> </template><script> export default {props: {todo: Object,checkTodo: Function,deleteTodo: Function},data () {return {bgColor: 'white',isShow: false}},methods: {handleEnter (isEnter) {if (isEnter) {this.bgColor = '#aaa'this.isShow = true} else {this.bgColor = 'white'this.isShow = false}},// 修改勾選狀態handlerCheck (id) {console.log(id)this.checkTodo(id)},// 根據id刪除handlerDeleteItem (id) {if (window.confirm('確定刪除嗎')) {this.deleteTodo(id)}}} } </script>

    App組件見下文哈

    四、完善尾部組件 | 判斷是否全部勾選及清除全部已完成任務

    照常先談談我們的需求:

    1、判斷是否全部勾選,修改數據狀態。

    2、清除選中的任務

    3、當沒有任何數據時,底部欄不展示


    先講講第一個的思路:判斷有沒有全選,其實就是判斷todos數組的長度是否等于已經選中的數量(另外就是注意就是數組長度必須要大于零)

    第二個:清除選中的任務,其實就是根據id 刪除掉 App父組件中 todos中我們選中的數據。

    第三個:使用v-show指令即可,直接用todos數組的長度即可,當數組長度為0時,v-show自然為”false“,反之為true

    理清楚,直接看代碼哈

    <template><div class="todo-footer" v-show="total"><label><!-- // 第一種方式:通過dom元素來判斷有沒有進行勾選 不是最佳方式 --><!-- <input type="checkbox" :checked="isAllCheck" @click="checkAll" /> --><!-- 第二種方式: 通過綁定計算屬性來進行展示 --><input type="checkbox" v-model="isAllCheck" /></label><span>已完成{{ doneTotal }}<span> / 全部{{ todos.length }} </span></span><buttonclass="btn btn-danger"@click="deleteDoneAll">清除已完成任務</button></div> </template><script> export default {props: {todos: Array,clearDoneTodos: Function,checkAllTodos: Function},computed: {total () {return this.todos.length},doneTotal () {return this.todos.reduce((preTotal, todo) => preTotal + (todo.done ? 1 : 0), 0)},isAllCheck: {get () {return this.doneTotal === this.todos.length && this.doneTotal > 0},// 通過計算屬性來判斷是否全選或全不選set (checked) {this.checkAllTodos(checked)}}},methods: {deleteDoneAll () {this.clearDoneTodos()}// 通過dom元素來判斷有沒有進行勾選 不是最佳方式// checkAll (e) {// console.log(e.target.checked)// this.checkAllTodos(e.target.checked)// }} } </script>

    為什么不選擇通過dom元素來判斷有沒有進行勾選呢?

    Vue框架中并不建議我們直接操作Dom元素,更多的是希望我們通過vue框架自帶的方式來實現.

    App組件:

    <template><div class="todo-container"><!-- :message 對應的是子組件 prop 中接收變量的名稱"message" 對應的父組件中data中定義的數據--><!-- header模塊 --><TodoHeader :addTodo="addTodo" /><!-- main 模塊 --><TodoList :todos="todos" :deleteTodo="deleteTodo" :checkTodo="checkTodo" /><!-- 主要的內容模塊 --><TodoFooter:todos="todos":clearDoneTodos="clearDoneTodos":checkAllTodos="checkAllTodos"/><!-- footer模塊 --></div> </template> <script> import TodoHeader from './components/MyTodoHeader' import TodoList from './components/MyTodoList' import TodoFooter from './components/MyTodoFooter'export default {components: {TodoHeader,TodoList,TodoFooter},data () {return {message: 'hello',todos: [{ id: '001', title: '吃飯', done: true },{ id: '002', title: '睡覺', done: false },{ id: '003', title: '敲代碼', done: true }]}},methods: {// 回車增加一個todoaddTodo (todo) {this.todos.unshift(todo)},// 判斷勾選不勾選checkTodo (id) {this.todos.forEach((todo) => {if (todo.id === id) todo.done = !todo.done})},// 刪除一個tododeleteTodo (id) {this.todos = this.todos.filter(todo => todo.id !== id)},// 全選全不選checkAllTodos (done) {this.todos.forEach((todo) => { todo.done = done })},// 清除所有已完成的任務clearDoneTodos () {this.todos = this.todos.filter(todo => !todo.done)}}} </script>

    五 小結

    vue中組件通信的方式其實有很多種,就像我已經學過的就有props | emit | 全局事件主線 | 發布訂閱模式

    之后還有Vuex,另外我們還可以自己定制.還有蠻多我沒學到的 捂臉

    其實本質都是去做數據的共享,大都數情況都是根據實際情況來選擇的,并非那一樣就是最好的。

    六 源碼

    gitee

    github

    后語

    大家一起加油!!!如若文章中有不足之處,請大家及時指出,在此鄭重感謝。

    紙上得來終覺淺,絕知此事要躬行。

    大家好,我是博主寧在春:主頁

    一名喜歡文藝卻踏上編程這條道路的小青年。

    希望:我們,待別日相見時,都已有所成。L

    總結

    以上是生活随笔為你收集整理的「后端小伙伴来学前端了」Vue中Props 实现组件通信TodoList案例的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。