Vue2-全局事件總線、消息的訂閱與發布、TodoList的編輯功能、$nextTick、動畫與過渡

🥔:高度自律即自由

更多Vue知識請點擊——Vue.js

VUE2-Day9

    • 全局事件總線
      • 1、安裝全局事件總線
      • 2、使用事件總線
        • (1)接收數據
        • (2)提供數據
        • (3)組件銷毀前最好解綁
      • 3、TodoList中的孫傳父
        • (1)首先在main.js中安裝全局事件總線
        • (2)在App.vue中綁定全局自定義事件,并使用之前寫好的回調
        • (3)Item中觸發事件,并把數據id傳過去
    • 消息的訂閱與發布
      • (1)使用消息的訂閱與發布
      • (2)TodoList案例使用消息的訂閱與發布
    • TodoList的編輯功能
      • 1、整體思路
      • 2、給標簽添加事件
      • 3、點擊編輯按鈕切換span為input
      • 4、失去焦點傳數據
      • 5、App收數據
    • $nextTick
    • 動畫與過渡
      • 進入離開動畫三種寫法

全局事件總線

一種組件間通信的方式,適用于任意組件間通信。通俗理解就是一個定義在所有組件之外的公共嘎達,這個嘎達可以有vm或vc上的同款$on、$off、$emit,也可以讓所有組件都訪問到。要想實現這個事情,只能在Vue.prototype上添加一個屬性,值是vm或vc

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-q3OYNFD4-1692378989491)(D:\wxf\前端學習筆記\vue2+vue3\筆記圖片\全局事件總線.png)]

vm.$emit( event, arg ) //觸發當前實例上的事件,arg是傳遞給父組件的參數
vm.$on( event, fn )    //監聽event事件后運行 fn
$off(type, fn)		   //注銷消息方法 type:消息名稱	fn:消息回調函數

1、安裝全局事件總線

安裝全局事件總線可以用vc也可以用vm,寫在main.js里面

  • 用vc的話這么寫:
const Demo = Vue.extend({});
const d = new Demo();
Vue.prototype.$bus = d;
  • 用vm的話這么寫(我們通常用vm):
new Vue({el: '#app',render: (h) => h(App),//放這個函數里,是因為模板還未解析,這個函數在自定義事件定義之前,是不會報錯滴beforeCreate() {Vue.prototype.$bus = this //安裝全局事件總線},
})

在這里我們使用vm安裝全局事件總線。

2、使用事件總線

(1)接收數據

接收數據:A組件想接收數據,則在A組件中給$bus綁定自定義事件,事件的回調留在A組件自身

methods(){demo(data){......}
}
......
mounted() {this.$bus.$on('xxxx',this.demo)
}

(2)提供數據

任意一個組件,都可以給上面說的A組件傳數據

  methods:{sendStudentName(){this.$bus.$emit('xxxx',this.name)}
}

(3)組件銷毀前最好解綁

最好在beforeDestroy鉤子中,用`$of去解綁當前組件所用到的事件。
因為接收數據的組件A中定義的回調函數和自定義事件是綁定的,而這個用來接收數據的組件實例A都銷毀了,回調函數也沒了,那這個自定義事件也就沒用了,你留著會污染全局環境。

beforeDestroy() {this.$bus.$off('hello')
}

3、TodoList中的孫傳父

之前我們孫傳父都是父親傳給兒子函數,兒子傳給孫子函數,然后孫子再調用函數傳值,很麻煩,但是現在我們可以用全局事件總線實現孫子給父親傳數據。此處只展示修改部分,記得把之前方法的相關代碼刪掉或注釋掉。

(1)首先在main.js中安裝全局事件總線

new Vue({el: '#app',render: h => h(App),beforeCreate() {Vue.prototype.$bus = this; //創建全局事件總線}
});

(2)在App.vue中綁定全局自定義事件,并使用之前寫好的回調

mounted() {//掛載完成后給全局事件總線添加事件this.$bus.$on('changeTodo', this.changeTodo);this.$bus.$on('deleteTodo', this.deleteTodo);
},
beforeDestroy() {//最好在銷毀前解綁this.$bus.$off(['changeTodo', 'deleteTodo']);
},

(3)Item中觸發事件,并把數據id傳過去

handleChange(id) {//觸發全局事件總線中的事件this.$bus.$emit('changeTodo', id);
},
handleDelete(id) {if (confirm('確定要刪除嗎?'))  //點確定是true,取消是falsethis.$bus.$emit('deleteTodo', id);
}

消息的訂閱與發布

(1)使用消息的訂閱與發布

消息的訂閱與發布用的不多,和全局事件總線寫法差不多,但是全局事件總線更好,因為是在Vue身上操作,但是這個的話要引入第三方庫,庫有很多,比如pubsub-js

安裝pubsub:npm i pubsub-js
引入:import pubsub from 'pubsub-js

接收數據:A組件想接收數據,則在A組件中訂閱消息,訂閱的回調留在A組件自身。
接收兩個參數,第一個是消息名字,第二個是傳過來的數據

methods(){demo(msgName,data){......}
}
......
mounted() {//訂閱消息this.pubsubId = pubsub.subscribe('xxx',this.demo) 
},   
beforeDestroy() {//銷毀時取消訂閱pubsub.unsubscribe(this.pubsubId); 
},

提供數據:

methods: {sendStudentName() {// this.$bus.$emit('hello', this.name);//發布消息并傳數據pubsub.publish('hello', this.name); }
},

可以對比一下前面的全局事件總線寫法,個人認為寫法差別不大。

可以嘗試把TodoList案例里孫傳父使用全局事件總線的寫法改成使用消息訂閱與發布試試。

(2)TodoList案例使用消息的訂閱與發布

這里把**deleteTodo改成消息訂閱與發布,changeTodo依舊使用全局事件總線**,大家可以仔細對比他們的區別。

  • App.vue(訂閱消息/接收數據):
 mounted() {//掛載完成后給全局事件總線添加事件this.$bus.$on('changeTodo', this.changeTodo)// this.$bus.$on('deleteTodo', this.deleteTodo)//deleteTodo換一種方法 用訂閱消息寫this.pubsubIs = pubsub.subscribe('deleteTodo', this.deleteTodo)},beforeDestroy() {//最好在銷毀前解綁// this.$bus.$off(['changeTodo', 'deleteTodo'])//使用全局事件總線解綁this.$bus.$off('changeTodo')//deleteTodo換一種方法 用訂閱消息解綁pubsub.unsubscribe(this.pubsubId)},

這里別忘了這個subscribe里的回調,接收兩個參數,第一個是消息名,后面才是數據,所以deleTodo方法得加個參數

//雖然msgName沒用上,但是如果不加就會把id當第一個參數,id就變成msgName,所以這里必須要加,或者直接拿一個下劃線_占位也行
deleteTodo(msgName, id) {this.todos = this.todos.filter(todo => todo.id !== id);},
  • Item.vue(發布消息/提供數據)
handleChange(id) {//使用全局事件總線//觸發全局事件總線中的事件this.$bus.$emit('changeTodo', id);
},
handleDelete(id) {//confirm點確定是true,取消是falseif (confirm('確定要刪除嗎?')) //使用消息訂閱與發布發布消息pubsub.publish('deleteTodo', id);  //發布消息
}

TodoList的編輯功能

1、整體思路

首先得有一個按鈕,點擊之后出現input框,框里是todo.title,而且原來的span要隱藏。然后修改完之后,失去焦點會自動更新數據,并且span出現,input框隱藏。
除此之外還有個細節,那就是點擊編輯要自動獲取焦點,要不然會有一個小問題(點擊編輯,然后突然不想改了,還得手動點一下input,再點下別的地方,才會變回span)

想實現span和input的來回切換,就要給todo添加新的屬性,用來標識這個變換,這里起名叫isEdit

所以大致思路:給標簽添加事件 => 點擊編輯按鈕切換span為input => 失去焦點傳數據 => App收數據 => 解決焦點bug

2、給標簽添加事件

(1)isEdit一上來是沒有的,所以todo.isEdit = false,再加上默認上來顯示的是span,所以span加個v-show=“!todo.isEdit”,input加個v-show=“todo.isEdit” ,button加v-show="!todo.isEdit"是因為我們一般編輯時,這個按鈕應該消失才對,所以和span一致

(2)由于props接過來的數據不能改,所以使用單向數據綁定:value=“todo.title”

(3)ref=“inputTitle” 是為了方便后面拿到input元素然后操作它寫的(nextTick)

(4)@blur="handleBlur(todo, $event)"是失去焦點時觸發的事件,用來給App傳值

<span v-show="!todo.isEdit">{{ todo.title }}</span>
<input 
type="text" 
v-show="todo.isEdit" 
:value="todo.title" 
ref="inputTitle" 
@blur="handleBlur(todo, $event)"><button class="btn btn-edit" @click="handleEdit(todo)" v-show="!todo.isEdit">編輯</button>

給這個編輯按鈕加個樣式:

.btn-edit {color: #fff;background-color: rgb(13, 166, 13);border: 1px solid green;margin-right: 5px;
}.btn-edit:hover {color: #fff;background-color: green;
}

3、點擊編輯按鈕切換span為input

點擊編輯給todo追加屬性,用來切換span為input。這里考慮到給todo追加屬性的問題,如果想要讓Vue監測到這個屬性,那么必須使用$set來添加isEdit,且默認值為true(因為編輯的時候顯示的是input啊,想想v-show="todo.isEdit")。

但是這里邊有點兒問題,如果已經添加過了isEdit,那每次點擊編輯按鈕,都會添加一次isEdit屬性,這樣是不太好的,所以要加個判斷,添加過了就改成true,沒添加過就添加個true

   handleEdit(todo) {if (todo.isEdit !== undefined) {console.log('todo里有isEdit屬性了')todo.isEdit = true;} else {console.log('todo里沒有isEdit屬性')this.$set(todo, 'isEdit', true);}this.$nextTick(function () {this.$refs.inputTitle.focus();})},

4、失去焦點傳數據

失去焦點首先input得變回span,然后使用全局事件總線傳值,傳值一定要傳當前input框的value值,因為這才是你修改后的值,使用事件對象獲取。(當然,別忘了id也要傳)

handleBlur(todo, e) {todo.isEdit = false;if (!e.target.value.trim()) return alert('值不能為空!');  //trim去掉空格this.$bus.$emit('updateTodo', todo.id, e.target.value);
}

5、App收數據

把input框里你寫的東西拿過來,給對應的todo.title

//6.實現編輯todo
methods: {......updateTodo(id, title) {this.todos.forEach((todo) => {if (todo.id === id) { todo.title = title }});}}
mounted() {......//實現編輯功能,接收數據this.$bus.$on('updateTodo', this.editTodo);
},
beforeDestroy() {//最好在銷毀前解綁this.$bus.$off('updateTodo');
},

$nextTick

1、語法:this.$nextTick(回調函數)
2、作用:在下一次 DOM 更新結束,v-for循環結束后執行其指定的回調。
3、什么時候用:當改變數據后,要基于更新后的新DOM進行某些操作時(如input自動獲取焦點),要在nextTick所指定的回調函數中執行。

4、比如剛才點擊編輯后,input框沒法自動獲取焦點,那么我就得先點一下,再點別處兒才能切換回去,如果直接this.$refs.inputTitle.focus();不行,因為這個函數雖然動了isEdit的值,但是模板重新解析也得等這個函數走完啊,那input還沒創建出來呢,就focus了,肯定是不行滴。
有個辦法就是用異步,也可以解決,但是更好的辦法是$nextTick

動畫與過渡

1、作用:在插入、更新或移除 DOM元素時,在合適的時候給元素添加樣式類名。

請添加圖片描述

2、寫法:

準備好樣式:

元素進入的樣式:
v-enter:進入的起點
v-enter-active:進入過程中
v-enter-to:進入的終點

元素離開的樣式:
v-leave:離開的起點
v-leave-active:離開過程中
v-leave-to:離開的終點

使用<transition>包裹要過度的元素,并配置name屬性:

<transition name="hello"><h1 v-show="isShow">你好啊!</h1>
</transition>

3、備注:若有多個元素需要過度,則需要使用:<transition-group>,且每個元素都要指定key值。

進入離開動畫三種寫法

  • 1、動畫(Test.vue)
<template><div><button @click="isShow = !isShow">顯示/隱藏</button><transition name="hello" appear><h1 v-show="isShow">你好呀!</h1></transition></div>
</template><script>
export default {name: 'Test',data() {return {isShow: true,}},
}
</script><style scoped>
h1 {background-color: pink;
}.hello-enter-active {animation: potato 1s;
}
.hello-leave-active {animation: potato 1s reverse;
}@keyframes potato {from {transform: translateX(-100%);}to {transform: translateX(0px);}
}
</style>
  • 2、過渡動畫(Test2.vue)
<template><div><button @click="isShow = !isShow">顯示/隱藏</button><transition-group name="hello" appear><h1 v-show="isShow" key="1">你好呀!</h1><h1 v-show="isShow" key="2">小土豆</h1></transition-group></div>
</template><script>
export default {name: 'Test2',data() {return {isShow: true,}},
}
</script><style scoped>
h1 {background-color: skyblue;
}/* 進入的起點,離開的終點 */
.hello-enter,
.hello-leave-to {transform: translateX(-100%);
}
/* 進入的終點,離開的起點 */
.hello-enter-to,
.hello-leave {transform: translateX(0);
}
.hello-enter-active,
.hello-leave-active {transition: 0.5s linear;
}
</style>
  • 3、集成第三方動畫
<template><div><button @click="isShow = !isShow">顯示/隱藏</button><transition-groupname="animate__animated animate__bounce"appearenter-active-class="animate__swing"leave-active-class="animate__backOutUp"><h1 v-show="isShow" key="1">你好呀!</h1><h1 v-show="isShow" key="2">小土豆</h1></transition-group></div>
</template><script>
import 'animate.css'
export default {name: 'Test3',data() {return {isShow: true,}},
}
</script><style scoped>
h1 {background-color: orange;
}
</style>
  • App.vue
<template><div id="App"><Test /><Test2 /><Test3 /></div>
</template><script>
import Test from './components/Test'
import Test2 from './components/Test2'
import Test3 from './components/Test3'
export default {name: 'App',components: { Test, Test2, Test3 },
}
</script>
  • 效果:(從上往下分別是Test、Test2、Test3效果)
    請添加圖片描述

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/42644.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/42644.shtml
英文地址,請注明出處:http://en.pswp.cn/news/42644.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

【Git】Git中用到的一些命令

Git文件有四種狀態&#xff1a; 未跟蹤未修改&#xff08;已跟蹤&#xff09;已修改&#xff08;已跟蹤&#xff09;已暫存&#xff08;已跟蹤&#xff09; 通常我們將項目clone下來就會處于已跟蹤狀態 1、git diff命令 git diff&#xff1a;查看沒有暫存的文件更新哪些部分…

js判斷手指的上滑,下滑,左滑,右滑,事件監聽 和 判斷鼠標滾輪向上滾動滑輪向下滾動

js判斷手指的上滑&#xff0c;下滑&#xff0c;左滑&#xff0c;右滑&#xff0c;事件監聽 和 判斷鼠標滾輪向上滾動滑輪向下滾動 pc端 判斷鼠標滾輪向上滾動滑輪向下滾動 const scrollFunc (e) > { e e || window.event; let wheelDelta e.wheelDelta ? e.wheelDelta…

Spring Clould 部署 - Docker

視頻地址&#xff1a;微服務&#xff08;SpringCloudRabbitMQDockerRedis搜索分布式&#xff09; 初識Docker-什么是Docker&#xff08;P42&#xff0c;P43&#xff09; 微服務雖然具備各種各樣的優勢&#xff0c;但服務的拆分通用給部署帶來了很大的麻煩。 分布式系統中&…

[強網杯 2019]隨便注

輸入1‘ 輸入1“ 和輸入1 一樣說明是由‘閉合 然后我們嘗試輸入select 這里提示過濾了select&#xff0c;說明聯合查詢&#xff0c;報錯注入&#xff0c;布爾,時間盲注就都不可以使用了。我們只剩下了 堆疊注入。 或者將select編碼繞開也可以。 按sql注入測試1 or 11 # ?然…

Unity 物體的運動之跟隨鼠標

你想讓鼠標點擊哪里&#xff0c;你的運動的對象就運動到哪里嗎&#xff1f; Please follow me ! 首先&#xff0c;你要先添加一個Plane ,以及你的圍墻&#xff0c;你的移動的物體 想要實現跟隨鼠標移動&#xff0c;我們先創建一個腳本 using System.Collections; using Syst…

銅卡計混合法比熱測試儀絕熱量熱計的高精度主動控制解決方案

摘要&#xff1a;在下落法比熱容測試中絕熱量熱計的漏熱是最主要誤差源&#xff0c;為實現絕熱量熱計的低漏熱要求&#xff0c;本文介紹了主動護熱式等溫絕熱技術以及相應的解決方案。方案的核心一是采用循環水冷卻金屬圓筒給量熱計和護熱裝置提供低溫環境或恒定冷源&#xff0…

黑馬點評-項目集成git及redis實現短信驗證碼登錄

目錄 IDEA集成git 傳統session存在的問題 redis方案 業務流程 選用的數據結構 整體訪問流程 發送短信驗證碼 獲取校驗驗證碼 配置登錄攔截器 攔截器注冊配置類 攔截器 用戶狀態刷新問題 刷新問題解決方案 IDEA集成git 遠程倉庫采用碼云&#xff0c;創建好倉庫&…

【O2O領域】Axure外賣訂餐騎手端APP原型圖,外賣配送原型設計圖

作品概況 頁面數量&#xff1a;共 110 頁 兼容軟件&#xff1a;Axure RP 9/10&#xff0c;不支持低版本 應用領域&#xff1a;外賣配送、生鮮配送 作品申明&#xff1a;頁面內容僅用于功能演示&#xff0c;無實際功能 作品特色 本品為外賣訂餐騎手端APP原型設計圖&#x…

CentOS下MySQL的徹底卸載的幾種方法

這里我為大家詳細講解下“CentOS下MySQL的徹底卸載的幾種方法”的完整攻略。 一、關閉MySQL服務 在開始操作之前&#xff0c;需要先關閉MySQL服務。可以使用以下命令來關閉MySQL服務&#xff1a; systemctl stop mysqld 或者 service mysqld stop 二、使用yum命令卸載MySQL…

微前端 - qiankun

qiankun 是一個基于 single-spa 的微前端實現庫&#xff0c;旨在幫助大家能更簡單、無痛的構建一個生產可用微前端架構系統。 本文主要記錄下如何接入 qiankun 微前端。主應用使用 vue2&#xff0c;子應用使用 vue3、react。 一、主應用 主應用不限技術棧&#xff0c;只需要提…

數據結構之線性表的類型運用Linear Lists: 數組,棧,隊列,鏈表

線性表 定義 一個最簡單&#xff0c;最基本的數據結構。一個線性表由多個相同類型的元素穿在一次&#xff0c;并且每一個元素都一個前驅&#xff08;前一個元素&#xff09;和后繼&#xff08;后一個元素&#xff09;。 線性表的類型 常見的類型&#xff1a;數組、棧、隊列…

mysql、redis面試題

mysql 相關 1、數據庫優化查詢方法 外鍵、索引、聯合查詢、選擇特定字段等等2、簡述mysql和redis區別 redis&#xff1a; 內存型非關系數據庫&#xff0c;數據保存在內存中&#xff0c;速度快mysql&#xff1a;關系型數據庫&#xff0c;數據保存在磁盤中&#xff0c;檢索的話&…

[Go版]算法通關村第十二關黃金——字符串沖刺題

目錄 題目&#xff1a;最長公共前綴解法1&#xff1a;縱向對比-循環內套循環寫法復雜度&#xff1a;時間復雜度 O ( n ? m ) O(n*m) O(n?m)、空間復雜度 O ( 1 ) O(1) O(1)Go代碼 解法2&#xff1a;橫向對比-兩兩對比&#xff08;類似合并K個數組、合并K個鏈表&#xff09;復…

okhttp下載文件 Java下載文件 javaokhttp下載文件 下載文件 java下載 okhttp下載 okhttp

okhttp下載文件 Java下載文件 javaokhttp下載文件 下載文件 java下載 okhttp下載 okhttp 1、引入Maven1.1、okhttp發起請求官網Demo 2、下載文件3、擴充&#xff0c;讀寫 txt文件內容3.1讀寫內容 示例 http客戶端 用的是 okhttp&#xff0c;也可以用 UrlConnetcion或者apache …

SD WebUI 擴展:prompt-all-in-one

sd-webui-prompt-all-in-one 是一個基于 Stable Diffusion WebUI 的擴展&#xff0c;旨在提高提示詞/反向提示詞輸入框的使用體驗。它擁有更直觀、強大的輸入界面功能&#xff0c;它提供了自動翻譯、歷史記錄和收藏等功能&#xff0c;它支持多種語言&#xff0c;滿足不同用戶的…

[MAUI]在.NET MAUI中實現可拖拽排序列表

文章目錄 創建可拖放控件創建綁定服務類拖拽&#xff08;Drag&#xff09;拖拽懸停&#xff0c;經過&#xff08;DragOver&#xff09;釋放&#xff08;Drop&#xff09; 創建頁面元素最終效果項目地址 .NET MAUI 中提供了拖放(drag-drop)手勢識別器&#xff0c;允許用戶通過拖…

Mysql驅動包下載

第一步&#xff1a;下載地址 MySQL :: Download Connector/J 第二步&#xff1a; 第三步&#xff1a; 第四步&#xff1a;解壓 第五步&#xff1a;找到驅動包&#xff0c;放入項目使用即可

管理類聯考——邏輯——真題篇——按知識分類——匯總篇——三、綜合推理

文章目錄 題-綜合推理-分類1-排序真題&#xff08;2016-54-55&#xff09;-難度最高*****-綜合推理-分類1-排序-畫表排除法真題&#xff08;2016-54&#xff09;真題&#xff08;2016-55&#xff09;真題&#xff08;2019-36&#xff09;-綜合推理-分類1-排序真題&#xff08;2…

【AIGC】 國內版聊天GPT

國內版聊天GPT 引言一、國內平臺二、簡單體驗2.1 提問2.2 角色扮演2.3 總結畫圖 引言 ChatGPT是OpenAI發開的聊天程序&#xff0c;功能強大&#xff0c;可快速獲取信息&#xff0c;節省用戶時間和精力&#xff0c;提供個性化的服務。目前國產ChatGPT&#xff0c;比如文心一言&a…

OJ練習第151題——克隆圖

克隆圖 力扣鏈接&#xff1a;133. 克隆圖 題目描述 給你無向 連通 圖中一個節點的引用&#xff0c;請你返回該圖的 深拷貝&#xff08;克隆&#xff09;。 示例 分析 對于一張圖而言&#xff0c;它的深拷貝即構建一張與原圖結構&#xff0c;值均一樣的圖&#xff0c;但是…