weex-coms
weex元件庫,這裡主要是分享下weex開發過程中封裝的一些weex元件,如popup、rich-text、lamp(努力持續更新),會分享自己遇到的一些坑,以及自己的一個做法和想法。
專案啟動
- 下載當前工程
git clone https://github.com/yuwanli/weex-coms.git
複製程式碼
- 安裝依賴
npm install --registry=https://registry.npm.taobao.org
複製程式碼
weex -v
確認已經安裝weex-previewer,若沒有安裝則
npm install weex-previewer --save
複製程式碼
- 安裝軟體
因為跑馬燈lamp是使用了bindingx的,所以建議下載bindingx的app,拉到頁面底部有二維碼,掃碼下載
- 啟動頁面(以popup為例)
weex-previewer examples/popup/index.vue
複製程式碼
- 掃碼檢視相應頁面
元件相關說明
元件 | 描述 | 引數 |
---|---|---|
weex-popup | 彈窗元件支援居中的淡入淡出、向上向下彈出的形式 | showPopup(boolean ):是否顯示彈窗,預設false popupType( string ):彈窗型別(center 、top 、bottom ),預設center defaultClose( boolean ):是否點選蒙層關閉彈窗,預設true popupColor( string ):蒙層顏色,預設rgba(0,0,0,0.6) |
weex-lamp | 跑馬燈元件,支援單條和容器式跑馬燈 | |
weex-rich-text | 富文字元件,彌補weex不支援v-html /v-text 的短板 |
可能有人會說,不是有weex-ui了麼,我這個是不是在重複造輪子?
weex-ui確實封裝了很多實用的元件,很多元件我們也在實際的專案中在使用,所以當然我不會重複造輪子。封裝的這些元件時為了解決其他的一些問題,或者說是做了一些優化,實現的功能上也會有些許差異,具體的細節可以檢視
看元件相關內容時,我希望你已經(點選瞭解更多)
- 對weex有所瞭解,最好已經做過weex相關的開發
- 知道如何用weex-previewer啟動頁面
- 對weex比較感興趣,有vue開發經驗
- 瞭解bindingx
- 瞭解weex-ui
weex-popup
weex彈窗元件。支援居中淡入淡出彈窗及向下向上彈出彈窗。
如何使用
- 安裝weex-coms
npm install weex-coms -i
//若403無法安裝,則切換原有npm,再安裝
npm config set registry https://registry.npmjs.org/
複製程式碼
- 元件引入
import {weexPopup} from 'weex-coms';
複製程式碼
- 具體使用程式碼如下
<template>
<div class="weex-demo">
<text class="button" @click="showPopup = true" style="background-color:#f21818">居中淡入</text>
<text class="button" @click="showPopup2 = true" style="background-color:yellowgreen">向上彈出</text>
<text class="button" @click="showPopup3 = true" style="background-color:#3c8dbc">向下彈出</text>
<weex-popup :show-popup="showPopup" @maskClick="maskClick('居中彈窗')" popup-type="center" @hidePopup="showPopup = false" :default-close=true popup-color="rgba(255,0,0,0.6)">
<div class="popup center">
<text class="popup__title">這是一個居中彈窗</text>
<text class="popup__desc">點選蒙層關閉彈窗(default-close=true)</text>
<text class="popup__desc">popup-type=center</text>
<text class="popup__desc">居中彈窗預設顯示</text>
<text class="popup__desc">這裡是內容這裡是內容</text>
</div>
</weex-popup>
<weex-popup :show-popup="showPopup2" @maskClick="maskClick('向上彈出')" popup-type="bottom" @hidePopup="showPopup2 = false" :default-close=false popup-color="rgba(0,255,0,0.6)">
<div class="popup bottom">
<div class="popup-wrapper">
<text class="popup__title">這是一個向上彈出的彈窗</text>
<text class="popup__desc">點選蒙層不可關閉彈窗(default-close=false)</text>
<text class="popup__desc">popup-type=bottom</text>
<text class="popup__desc">這裡是內容這裡是內容</text>
<text class="popup__desc">這裡是內容這裡是內容</text>
</div>
<text class="popup__close" @click="showPopup2 = false">關閉</text>
</div>
</weex-popup>
<weex-popup :show-popup="showPopup3" @maskClick="maskClick('向下彈出')" popup-type="top" @hidePopup="showPopup3 = false" :default-close=true popup-color="rgba(0,0,255,0.6)">
<div class="popup top">
<div class="popup-wrapper">
<text class="popup__title">這是一個向下彈出的彈窗</text>
<text class="popup__desc">點選蒙層不可關閉彈窗(default-close=false)</text>
<text class="popup__desc">popup-type=top</text>
<text class="popup__desc">這裡是內容這裡是內容</text>
<text class="popup__desc">這裡是內容這裡是內容</text>
</div>
<text class="popup__close" @click="showPopup3 = false">關閉</text>
</div>
</weex-popup>
</div>
</template>
<script>
import {weexPopup} from 'weex-coms';
const modal = weex.requireModule('modal');
export default {
components: {
weexPopup,
},
data: {
showPopup: true,
showPopup2: false,
showPopup3: false
},
methods: {
maskClick(str) {
modal.toast({
message: `${str}蒙層點選`,
duration: 0.2
})
}
}
};
</script>
<style lang="less" scoped>
.weex-demo{
flex: 1;
}
.button{
height: 88px;
line-height: 88px;
text-align: center;
border-radius: 10px;
margin-bottom: 20px;
margin-top: 20px;
color: #fff;
}
.popup{
background-color: #ffffff;
align-items: center;
&__title{
font-size: 36px;
font-weight: bold;
margin-bottom: 24px;
}
&__desc{
font-size: 28px;
color: #aaa;
line-height: 40px;
}
&__close{
height: 88px;
line-height: 88px;
border-top-color: #ccc;
border-top-width: 1px;
border-top-style: solid;
width: 750px;
text-align: center;
margin-top: 24px;
}
&-wrapper{
align-items: center;
}
}
.center{
padding: 24px;
width: 540px;
border-radius: 10px;
}
.bottom{
width: 750px;
padding: 24px 24px 0;
justify-content: space-between;
align-items: center;
}
.top{
width: 750px;
padding: 24px 24px 0;
justify-content: space-between;
align-items: center;
}
</style>
複製程式碼
- 可執行頁面進行檢視效果(如何執行安裝及檢視頁面可看前一頁)
weex-previewer examples/popup/index.vue
複製程式碼
為啥要再次封裝?
weex-ui裡其實已經有popup元件了,使用也很簡單。但是遇到了一個比較麻煩的問題就是,要準確傳入height
,這個就導致如果彈窗主體內容的高度是自適應的時候,需要先獲取內容的高度,準確給wxc-popup
賦值height
才行,所以weex-popup
主要的功能點就是不用傳入height
。wxc-popoup
的具體用法如下(注意需要傳入height="500"
):
<template>
<div>
<wxc-button text="Open Popup"
@wxcButtonClicked="buttonClicked">
</wxc-button>
<wxc-popup height="500"
pos="bottom"
:show="isShow"
@wxcPopupOverlayClicked="overlayClicked">
</wxc-popup>
</div>
</template>
<script>
import { WxcButton, WxcPopup } from 'weex-ui';
module.exports = {
components: { WxcButton, WxcPopup },
data: () => ({
isShow: false
}),
methods: {
buttonClicked () {
this.isShow = true;
},
overlayClicked () {
this.isShow = false;
}
}
};
</script>
複製程式碼
為什麼一定要傳入一個高度呢?
核心原因就在於weex中單位不支援百分比
大家可以想下在h5中我們要一個元素的移入和移出的效果怎麼寫。以下是我封裝h5的彈窗的程式碼(擷取樣式的一部分)
.popup{
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
z-index: 10000;
background-color: rgba(0,0,0,0.6);
transition: all 0.3s ease;
&[data-type='top']{
.popup-content{
top: 0;
left: 0;
z-index: 3000;
transition: all 0.3s ease;
}
&.fade-leave-active{
background-color: rgba(0,0,0,0.6);
.popup-content{
opacity: 1;
transform: translateY(0);
}
}
&.fade-leave-to{
background-color: rgba(0,0,0,0);
.popup-content{
opacity: 0;
transform: translateY(-100%);
}
}
&.fade-enter-active{
background-color: rgba(0,0,0,0);
.popup-content{
opacity: 0;
transform: translateY(-100%);
}
}
&.fade-enter-to{
background-color: rgba(0,0,0,0.6);
.popup-content{
opacity: 1;
transform: translateY(0);
}
}
}
&-content{
position: absolute;
}
}
複製程式碼
核心就是利用了transition
和transform
,大家注意,我們利用了100%
,這樣我們就不用在乎元素的高度是多少,當一個置於訂部的元素,我們給加上transform: translateY(-100%);
,元素就會完全移出螢幕,然後在配合transition
,就可以達到我們想要的移入移出的效果。
那weex中呢,首先的侷限就在於無法用百分比,所以偏移量只能寫明確的畫素,所以這也是為什麼weex-ui要暴露一個height
引數,需要明確指定高度。
似乎傳高度也沒有什麼問題,好多時候彈窗設計出來的時候高度就是固定的。但是如果彈窗高度是自適應的呢,這個高度該如何獲取?如果彈窗的內容是後端控制的呢?
weex-popup的實現過程
實現的過程(拿置底向上彈出的彈窗為例)
- 首次獲取主內容的高度h,並快取高度(居中顯示的無需獲取高度)
- 進行h高度的正向偏移使其離開螢幕
- 用animation進行tranition動畫使其向上淡入
- 用animation進行tranition動畫使其向下淡出
- 後續就3.4重複即可,無需再次獲取高度
1.獲取主內容的高度h
//...
const getHeight = () => new Promise((resolve) => {
// center型別無需獲取高度,用flex佈局就可以讓自適應的內容居中
// initFlag 用於只獲取一次高度,防止重複獲取
if (!this.initFlag && this.popupType !== 'center') {
this.initFlag = true;
dom.getComponentRect(this.$refs.popupContent, (option) => {
if (option.result) {
this.contentHeight = option.size.height;
// 不能立馬resolve,先讓元素進行h高度的偏移離開螢幕
setTimeout(() => {
resolve();
}, 30);
}
});
} else {
resolve();
}
});
//...
複製程式碼
2. 進行h高度的正向偏移使其離開螢幕
<div :class="['weex-popup_content','weex-popup_content_'+popupType]" :style="computedStyle" ref="popupContent" @click.stop>
<slot></slot>
</div>
...
computed: {
computedStyle() {
if (this.popupType === 'bottom') {
return {
transform: `translate(0px, ${this.contentHeight}px)`,
};
}
if (this.popupType === 'top') {
return {
transform: `translate(0px, ${-1 * this.contentHeight}px)`,
};
}
return {};
},
},
...
複製程式碼
3.用animation進行tranition動畫使其向上淡出
...
let resObj = {
popupMask: this.$refs.popupMask,
popupContent: this.$refs.popupContent,
maskStyle: {
opacity: +flag,
},
contentStyle: {
opacity: +flag,
},
};
...
animation.transition(resObj.popupMask, {
styles: resObj.maskStyle,
duration: 500,
timingFunction: 'ease',
}, () => {
this.showInCurrent = flag;
});
getHeight().then(() => {
animation.transition(resObj.popupContent, {
styles: resObj.contentStyle,
duration: 300,
timingFunction: 'ease',
});
});
複製程式碼
關於setTimeout
細心的同學會發現這邊用的是setTimeout,可能會有疑問,為啥不用nextTick? 因為實際使用發現nextTick會不準,跟weex的渲染機制有關,因為真正渲染的是原生的元素,vue中的nextTick是把回掉放在微任務佇列中(支援promise的情況下),放在渲染函式之後。可是這一套渲染機制放在weex中就不適用了。所以這邊也是踩了好幾次的坑,最後得出的結論,是
30s
。
showInCurrent的作用
因為主內容整個用
v-if='showPopup'
包裹,當關閉彈窗的時候,我們希望彈窗消失是淡出(居中),或者移出(向上或者向下)的,而不是直接關閉掉的,所以這裡引入了另一個引數showInCurrent,可以把它理解為當前狀態彈窗是否可顯示。
showInCurrent的狀態變更過程
- 當彈窗開啟時
showPopup=true
,showInCurrent
會在動畫執行完成被置成true
- 當彈窗關閉時
showPopup=true
,由於現在showInCurrent
為true
所以彈窗一直顯示,當動畫執行完成,再把改成置成false
,整個彈窗就關閉了
weex-popup待優化
當然待優化的點還有很多,這塊我會盡量持續更新,大家有什麼issue或者希望擴充套件的需求可以提,以下幾點會持續去完成
- 支援h5版本(目前只支援在客戶端中使用即native)
- 引數的擴充套件,如:動畫的執行時間、
timingFunction
等 - 效能的檢測和優化
- 向左向右出的彈窗?