Uniapp中怎么實現(xiàn)全局消息提示及其組件?下面本篇文章給大家介紹一下Uniapp全局消息提示及其組件的實現(xiàn)方法,希望對大家有所幫助!
最近有項目需求我們能夠在H5及小程序中全局實時刷新消息,并且在全局做一個消息提示,提示組件也需要自定義樣式,首先實時消息的刷新無非有兩種,一種是短輪詢,一種是長輪詢。
所謂短輪詢,其實就是前端使用定時器,在一定間隔時間內(nèi)向后端發(fā)起請求,并且后端需要對輪詢請求做優(yōu)化。
長輪詢則是將消息請求發(fā)送到后端后,請求掛起,等待后端有新消息返回后,再重新發(fā)起消息請求,實則是一個websocket通信,鑒于項目上線時間以及成本,最后選擇短輪詢方式,且全局消息提示在App.vue中進行。
實現(xiàn)
1.短輪詢請求-App.vue中
async created(){const _this=thissetInterval(async ()=>{ const res=await _this.$ajax({ url:`/api/notice/status` }) if(res.data.code===200){ const value=res.data.data.hasNew _this.$store.commit({type: 'changeNew', value}) } },6000) }
2.全局消息提示組件
消息請求后需要有一個全局的自定義組件來展示消息,但是遇到一個問題,那就是在Unipp中, 雖然App.vue
是uni-app的主組件,所有頁面都是在App.vue
下進行切換的,是頁面入口文件。但App.vue
本身不是頁面,這里不能編寫視圖元素。這個文件的作用包括:調(diào)用應用生命周期函數(shù)、配置全局樣式、配置全局的存儲globalData。也就是App.vue
中只能進行js以及css的編寫,而不能掛載視圖元素,那么是否可以在js中像使用this.$message
一樣使用組件呢,我想到了Vue
中使用vue.prototype.$message
掛載全局組件的方式。
(1)定義一個GlobalMessage.vue組件
自定義一個消息提示組件,text將會是我們傳入的提示消息參數(shù)
<template> <div class='message-container'> 全局消息提示 {{text}} </div> </template> <script></script> <style lang="scss" scoped> .message-container{ position: fixed; top: 10%; z-index: 2000; left: 10%; width: 200px; height: 200px; background-color: red; } </style>
(2)新建GlobalMessage.js
將自定義組件引入,vue.extend
可以使用基礎的Vue構造器,創(chuàng)建一個子類,參數(shù)是一個包含組件的對象。對象示例如下:
{ template:'', data(){ return { 屬性 } } }
但此時創(chuàng)建的并非組件實例,需要通過new 方式創(chuàng)建組件實例,參數(shù)包括創(chuàng)建的組件Dom節(jié)點,組件內(nèi)部屬性。然后使用document.body.appendChild
將組件渲染到body中,此時我們已經(jīng)可以調(diào)用此方法,將自定義組件掛載到全局。
function showMessage(text,duration){ const MessageDom=new MessageConstructor({ el:document.createElement('div'),data(){ return {text:text, } } })document.body.appendChild(MessageDom.$el) }
接下來我們需要將該方法掛載到vue原型上,從而能夠像this.$message
一樣使用,我們在vue.prototype
上掛載$message
,并將此方法導出。
function registryMessage(){ vue.prototype.$message=showMessage } export default registryMessage
GlobalMessage.js全部代碼
import vue from "vue" import GlobalMessage from './GlobalMessage.vue'; const MessageConstructor= vue.extend(GlobalMessage) function showMessage(text,duration){ const MessageDom=new MessageConstructor({ el:document.createElement('div'),data(){ return {text:text, } } }) document.body.appendChild(MessageDom.$el) } function registryMessage(){ vue.prototype.$message=showMessage } export default registryMessage
(3)main.js中
將我們拋出的方法引入,使用Vue.use
進行全局注冊,這樣就可以愉快的使用this.$message
了。
import GlobalMessage from "./GlobalMessage.js"; // 這里也可以直接執(zhí)行 toastRegistry()Vue.use(GlobalMessage);
使用
this.$message('測試數(shù)據(jù)')
3.小程序中如何實現(xiàn)
超導馬得,剛剛能夠全局使用this.$message
,但是又遇到一個問題,小程序中沒有document
,我們看uni-app
官方文檔:
uni-app
的js API由標準ECMAScript的js API 和 uni 擴展 API 這兩部分組成。
標準ECMAScript的js僅是最基礎的js。瀏覽器基于它擴展了window、document、navigator等對象。小程序也基于標準js擴展了各種wx.xx、my.xx、swan.xx的API。node也擴展了fs等模塊。
uni-app基于ECMAScript擴展了uni對象,并且API命名與小程序保持兼容。uni-app
的js代碼,h5端運行于瀏覽器中。非h5端(包含小程序和App),Android平臺運行在v8引擎中,iOS平臺運行在iOS自帶的jscore引擎中,都沒有運行在瀏覽器或webview里。非H5端,不支持window、document、navigator等瀏覽器的js API
uni-app的js API
那么需求不能不完成,我們采用另外一套方案,使用vuex狀態(tài)機來進行全局狀態(tài)控制,將自定義組件放在需要的頁面中,使用狀態(tài)機來控制消息的提示內(nèi)容以及展示與隱藏。注:請自行安裝配置vuex。
main.js中全局注冊組件
import GlobalMessage from '@/components/common/GlobalMessage.vue'; Vue.component('GlobalMessage',GlobalMessage)
在需要的頁面放置GlobalMessage
組件,但是我們需要每個頁面都要加組件標簽,實在是一個難以忍受的方式,于是在翻閱一些文檔后,在jy文章中發(fā)現(xiàn)一個工具vue-inset-loader
4.vue-inset-loader的使用
我們來看該loader的提示:編譯階段在sfc模板指定位置插入自定義內(nèi)容,適用于webpack構建的vue應用,常用于小程序需要全局引入組件的場景。(由于小程序沒有開放根標簽,沒有辦法在根標簽下追加全局標簽,所以要使用組件必須在當前頁面引入組件標簽),該插件剛好能夠幫助我們?nèi)肿芳咏M件標簽。
vue-inset-loader
(1)安裝
npm install vue-inset-loader –save-dev
(2)vue.config.js注入loader
沒有vue.config.js
請新建文件。
module: { rules: [ { test: /.vue$/, use:{ loader: "vue-inset-loader" // // 針對Hbuilder工具創(chuàng)建的uni-app項目 // loader: path.resolve(__dirname,"./node_modules/vue-inset-loader") } } ] }, // 支持自定義pages.json文件路徑 // options: { // pagesPath: path.resolve(__dirname,'./src/pages.json') // }
(3)pages.json配置文件中添加insetLoader
"insetLoader": { "config":{ "message": "<GlobalMessage></GlobalMessage>", }, // 全局配置 "label":["confirm"], "rootEle":"div" }, "pages": [ { "path": "pages/tabbar/index/index", "style": { "navigationBarTitleText": "測試頁面", // 單獨配置,用法跟全局配置一致,優(yōu)先級高于全局 "label": ["confirm","abc"], "rootEle":"div" } }, ]
- 配置說明
config
(default:{}
) 定義標簽名稱和內(nèi)容的鍵值對label
(default:[]
) 需要全局引入的標簽,打包后會在所有頁面引入此標簽rootEle
(default:"div"
) 根元素的標簽類型,缺省值為div,支持正則,比如匹配任意標簽 ".*"
✔ label
和 rootEle
支持在單獨頁面的style里配置,優(yōu)先級高于全局配置
總結
雖然實現(xiàn)了全局消息的提示,但是在小程序中,該方法還是過于麻煩,需要在每個頁面追加全局組件標簽,希望大家有更好的方法能夠不吝賜教。
推薦:《uniapp教程》