提交 35c3f166 编写于 作者: 郭胜强

补充小程序组件示例缺少的依赖

上级 7b34e105
const hasOwn = {}.hasOwnProperty;
export function classNames() {
const classes = [];
for (let i = 0; i < arguments.length; i++) {
const arg = arguments[i];
if (!arg) continue;
const argType = typeof arg;
if (argType === 'string' || argType === 'number') {
classes.push(arg);
} else if (Array.isArray(arg) && arg.length) {
const inner = classNames.apply(null, arg);
if (inner) {
classes.push(inner);
}
} else if (argType === 'object') {
for (const key in arg) {
if (hasOwn.call(arg, key) && arg[key]) {
classes.push(key);
}
}
}
}
return classes.join(' ');
};
import { basic } from '../mixins/basic';
import { observe } from '../mixins/observer/index';
export function create(sfc) {
// map props to properties
if (sfc.props) {
sfc.properties = sfc.props;
delete sfc.props;
}
// map mixins to behaviors
if (sfc.mixins) {
sfc.behaviors = sfc.mixins;
delete sfc.mixins;
}
// map classes to externalClasses
sfc.externalClasses = sfc.classes || [];
delete sfc.classes;
// add default externalClasses
sfc.externalClasses.push('custom-class');
// add default behaviors
sfc.behaviors = sfc.behaviors || [];
sfc.behaviors.push(basic);
// add default options
sfc.options = sfc.options || {};
sfc.options.multipleSlots = true;
sfc.options.addGlobalClass = true;
// map field to form-field behavior
if (sfc.field) {
sfc.behaviors.push('wx://form-field');
}
observe(sfc);
Component(sfc);
};
.van-ellipsis{overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.van-multi-ellipsis--l2{overflow:hidden;text-overflow:ellipsis;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical}.van-multi-ellipsis--l3{overflow:hidden;text-overflow:ellipsis;display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical}.van-clearfix::after{content:'';display:table;clear:both}.van-hairline,.van-hairline--bottom,.van-hairline--left,.van-hairline--right,.van-hairline--surround,.van-hairline--top,.van-hairline--top-bottom{position:relative}.van-hairline--bottom::after,.van-hairline--left::after,.van-hairline--right::after,.van-hairline--surround::after,.van-hairline--top-bottom::after,.van-hairline--top::after,.van-hairline::after{content:'';position:absolute;top:-50%;left:-50%;right:-50%;bottom:-50%;-webkit-transform:scale(.5);transform:scale(.5);pointer-events:none;box-sizing:border-box;border:0 solid #eee}.van-hairline--top::after{border-top-width:1px}.van-hairline--left::after{border-left-width:1px}.van-hairline--right::after{border-right-width:1px}.van-hairline--bottom::after{border-bottom-width:1px}.van-hairline--top-bottom::after{border-width:1px 0}.van-hairline--surround::after{border-width:1px}
\ No newline at end of file
.van-clearfix::after{content:'';display:table;clear:both}
\ No newline at end of file
.van-ellipsis{overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.van-multi-ellipsis--l2{overflow:hidden;text-overflow:ellipsis;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical}.van-multi-ellipsis--l3{overflow:hidden;text-overflow:ellipsis;display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical}
\ No newline at end of file
.van-hairline,.van-hairline--bottom,.van-hairline--left,.van-hairline--right,.van-hairline--surround,.van-hairline--top,.van-hairline--top-bottom{position:relative}.van-hairline--bottom::after,.van-hairline--left::after,.van-hairline--right::after,.van-hairline--surround::after,.van-hairline--top-bottom::after,.van-hairline--top::after,.van-hairline::after{content:'';position:absolute;top:-50%;left:-50%;right:-50%;bottom:-50%;-webkit-transform:scale(.5);transform:scale(.5);pointer-events:none;box-sizing:border-box;border:0 solid #eee}.van-hairline--top::after{border-top-width:1px}.van-hairline--left::after{border-left-width:1px}.van-hairline--right::after{border-right-width:1px}.van-hairline--bottom::after{border-bottom-width:1px}.van-hairline--top-bottom::after{border-width:1px 0}.van-hairline--surround::after{border-width:1px}
\ No newline at end of file
function isDef(value) {
return value !== undefined && value !== null;
}
function isObj(x) {
const type = typeof x;
return x !== null && (type === 'object' || type === 'function');
}
export {
isObj,
isDef
};
import { classNames } from '../common/class-names';
export const basic = Behavior({
methods: {
classNames,
$emit() {
this.triggerEvent.apply(this, arguments);
},
getRect(selector, all) {
return new Promise((resolve, reject) => {
wx.createSelectorQuery()
.in(this)[all ? 'selectAll' : 'select'](selector)
.boundingClientRect(rect => {
if (all && Array.isArray(rect) && rect.length) {
resolve(rect);
}
if (!all && rect) {
resolve(rect);
}
})
.exec();
});
}
}
});
export const button = Behavior({
properties: {
loading: Boolean,
openType: String,
appParameter: String,
sendMessageTitle: String,
sendMessagePath: String,
sendMessageImg: String,
showMessageCard: String,
hoverStopPropagation: Boolean,
hoverStartTime: {
type: Number,
value: 20
},
hoverStayTime: {
type: Number,
value: 70
},
lang: {
type: String,
value: 'en'
},
sessionFrom: {
type: String,
value: ''
}
},
methods: {
bindgetuserinfo(event = {}) {
this.$emit('getuserinfo', event.detail);
},
bindcontact(event = {}) {
this.$emit('contact', event.detail);
},
bindgetphonenumber(event = {}) {
this.$emit('getphonenumber', event.detail);
},
bindopensetting(event = {}) {
this.$emit('opensetting', event.detail);
},
binderror(event = {}) {
this.$emit('error', event.detail);
}
}
});
export const behavior = Behavior({
created() {
if (!this.$options) {
return;
}
const cache = {};
const { setData } = this;
const { computed } = this.$options();
const keys = Object.keys(computed);
const calcComputed = () => {
const needUpdate = {};
keys.forEach(key => {
const value = computed[key].call(this);
if (cache[key] !== value) {
cache[key] = needUpdate[key] = value;
}
});
return needUpdate;
};
Object.defineProperty(this, 'setData', { writable: true });
this.setData = (data, callback) => {
data && setData.call(this, data, callback);
setData.call(this, calcComputed());
};
},
attached() {
this.setData();
}
});
import { behavior } from './behavior';
import { observeProps } from './props';
export function observe(sfc) {
if (sfc.computed) {
sfc.behaviors.push(behavior);
sfc.methods = sfc.methods || {};
sfc.methods.$options = () => sfc;
if (sfc.properties) {
observeProps(sfc.properties);
}
}
}
export function observeProps(props) {
if (!props) {
return;
}
Object.keys(props).forEach(key => {
let prop = props[key];
if (prop === null || !prop.type) {
prop = { type: prop };
}
let { observer } = prop;
prop.observer = function() {
if (observer) {
if (typeof observer === 'string') {
observer = this[observer];
}
observer.apply(this, arguments);
}
this.setData();
};
props[key] = prop;
});
}
export const touch = Behavior({
methods: {
touchStart(event) {
this.direction = '';
this.deltaX = 0;
this.deltaY = 0;
this.offsetX = 0;
this.offsetY = 0;
this.startX = event.touches[0].clientX;
this.startY = event.touches[0].clientY;
},
touchMove(event) {
const touch = event.touches[0];
this.deltaX = touch.clientX - this.startX;
this.deltaY = touch.clientY - this.startY;
this.offsetX = Math.abs(this.deltaX);
this.offsetY = Math.abs(this.deltaY);
this.direction = this.offsetX > this.offsetY ? 'horizontal' : this.offsetX < this.offsetY ? 'vertical' : '';
}
}
});
export const transition = function(showDefaultValue) {
return Behavior({
properties: {
customStyle: String,
show: {
value: showDefaultValue,
type: Boolean,
observer(value) {
if (value) {
this.show();
} else {
this.setData({
type: 'leave'
});
}
}
},
duration: {
type: Number,
value: 300
}
},
data: {
type: '',
inited: false,
display: false
},
attached() {
if (this.data.show) {
this.show();
}
},
methods: {
show() {
this.setData({
inited: true,
display: true,
type: 'enter'
});
},
onAnimationEnd() {
if (!this.data.show) {
this.setData({
display: false
});
}
}
}
});
};
const ENTER = 'enter'
const ENTERING = 'entering'
const ENTERED = 'entered'
const EXIT = 'exit'
const EXITING = 'exiting'
const EXITED = 'exited'
const UNMOUNTED = 'unmounted'
const TRANSITION = 'transition'
const ANIMATION = 'animation'
const TIMEOUT = 1000 / 60
const defaultClassNames = {
enter: '', // 进入过渡的开始状态,在过渡过程完成之后移除
enterActive: '', // 进入过渡的结束状态,在过渡过程完成之后移除
enterDone: '', // 进入过渡的完成状态
exit: '', // 离开过渡的开始状态,在过渡过程完成之后移除
exitActive: '', // 离开过渡的结束状态,在过渡过程完成之后移除
exitDone: '', // 离开过渡的完成状态
}
Component({
externalClasses: ['wux-class'],
data: {
animateCss: '', // 动画样式
animateStatus: EXITED, // 动画状态,可选值 entering、entered、exiting、exited
isMounting: false, // 是否首次挂载
},
properties: {
// 触发组件进入或离开过渡的状态
in: {
type: Boolean,
value: false,
observer(newVal) {
if (this.data.isMounting) {
this.updated(newVal)
}
},
},
// 过渡的类名
classNames: {
type: null,
value: defaultClassNames,
},
// 过渡持续时间
duration: {
type: null,
value: null,
},
// 过渡动效的类型
type: {
type: String,
value: TRANSITION,
},
// 首次挂载时是否触发进入过渡
appear: {
type: Boolean,
value: false,
},
// 是否启用进入过渡
enter: {
type: Boolean,
value: true,
},
// 是否启用离开过渡
exit: {
type: Boolean,
value: true,
},
// 首次进入过渡时是否懒挂载组件
mountOnEnter: {
type: Boolean,
value: true,
},
// 离开过渡完成时是否卸载组件
unmountOnExit: {
type: Boolean,
value: true,
},
},
methods: {
/**
* 监听过渡或动画的回调函数
*/
addEventListener() {
const { animateStatus } = this.data
const { enter, exit } = this.getTimeouts()
if (animateStatus === ENTERING && !enter && this.data.enter) {
this.performEntered()
}
if (animateStatus === EXITING && !exit && this.data.exit) {
this.performExited()
}
},
/**
* 会在 WXSS transition 或 wx.createAnimation 动画结束后触发
*/
onTransitionEnd() {
if (this.data.type === TRANSITION) {
this.addEventListener()
}
},
/**
* 会在一个 WXSS animation 动画完成时触发
*/
onAnimationEnd() {
if (this.data.type === ANIMATION) {
this.addEventListener()
}
},
/**
* 更新组件状态
* @param {String} nextStatus 下一状态,ENTERING 或 EXITING
* @param {Boolean} mounting 是否首次挂载
*/
updateStatus(nextStatus, mounting = false) {
if (nextStatus !== null) {
this.cancelNextCallback()
this.isAppearing = mounting
if (nextStatus === ENTERING) {
this.performEnter()
} else {
this.performExit()
}
}
},
/**
* 进入过渡
*/
performEnter() {
const { className, activeClassName } = this.getClassNames(ENTER)
const { enter } = this.getTimeouts()
const enterParams = {
animateStatus: ENTER,
animateCss: className,
}
const enteringParams = {
animateStatus: ENTERING,
animateCss: `${className} ${activeClassName}`,
}
// 若已禁用进入过渡,则更新状态至 ENTERED
if (!this.isAppearing && !this.data.enter) {
return this.performEntered()
}
// 第一阶段:设置进入过渡的开始状态,并触发 ENTER 事件
// 第二阶段:延迟一帧后,设置进入过渡的结束状态,并触发 ENTERING 事件
// 第三阶段:若已设置过渡的持续时间,则延迟指定时间后触发进入过渡完成 performEntered,否则等待触发 onTransitionEnd 或 onAnimationEnd
this.safeSetData(enterParams, () => {
this.triggerEvent('change', { animateStatus: ENTER })
this.triggerEvent(ENTER, { isAppearing: this.isAppearing })
// 由于有些时候不能正确的触发动画完成的回调,具体原因未知
// 所以采用延迟一帧的方式来确保可以触发回调
this.delayHandler(TIMEOUT, () => {
this.safeSetData(enteringParams, () => {
this.triggerEvent('change', { animateStatus: ENTERING })
this.triggerEvent(ENTERING, { isAppearing: this.isAppearing })
if (enter) {
this.delayHandler(enter, this.performEntered)
}
})
})
})
},
/**
* 进入过渡完成
*/
performEntered() {
const { doneClassName } = this.getClassNames(ENTER)
const enteredParams = {
animateStatus: ENTERED,
animateCss: doneClassName,
}
// 第三阶段:设置进入过渡的完成状态,并触发 ENTERED 事件
this.safeSetData(enteredParams, () => {
this.triggerEvent('change', { animateStatus: ENTERED })
this.triggerEvent(ENTERED, { isAppearing: this.isAppearing })
})
},
/**
* 离开过渡
*/
performExit() {
const { className, activeClassName } = this.getClassNames(EXIT)
const { exit } = this.getTimeouts()
const exitParams = {
animateStatus: EXIT,
animateCss: className,
}
const exitingParams = {
animateStatus: EXITING,
animateCss: `${className} ${activeClassName}`,
}
// 若已禁用离开过渡,则更新状态至 EXITED
if (!this.data.exit) {
return this.performExited()
}
// 第一阶段:设置离开过渡的开始状态,并触发 EXIT 事件
// 第二阶段:延迟一帧后,设置离开过渡的结束状态,并触发 EXITING 事件
// 第三阶段:若已设置过渡的持续时间,则延迟指定时间后触发离开过渡完成 performExited,否则等待触发 onTransitionEnd 或 onAnimationEnd
this.safeSetData(exitParams, () => {
this.triggerEvent('change', { animateStatus: EXIT })
this.triggerEvent(EXIT)
this.delayHandler(TIMEOUT, () => {
this.safeSetData(exitingParams, () => {
this.triggerEvent('change', { animateStatus: EXITING })
this.triggerEvent(EXITING)
if (exit) {
this.delayHandler(exit, this.performExited)
}
})
})
})
},
/**
* 离开过渡完成
*/
performExited() {
const { doneClassName } = this.getClassNames(EXIT)
const exitedParams = {
animateStatus: EXITED,
animateCss: doneClassName,
}
// 第三阶段:设置离开过渡的完成状态,并触发 EXITED 事件
this.safeSetData(exitedParams, () => {
this.triggerEvent('change', { animateStatus: EXITED })
this.triggerEvent(EXITED)
// 判断离开过渡完成时是否卸载组件
if (this.data.unmountOnExit) {
this.setData({ animateStatus: UNMOUNTED }, () => {
this.triggerEvent('change', { animateStatus: UNMOUNTED })
})
}
})
},
/**
* 获取指定状态下的类名
* @param {String} type 过渡类型,enter 或 exit
*/
getClassNames(type) {
const { classNames } = this.data
const className = typeof classNames !== 'string' ? classNames[type] : `${classNames}-${type}`
const activeClassName = typeof classNames !== 'string' ? classNames[`${type}Active`] : `${classNames}-${type}-active`
const doneClassName = typeof classNames !== 'string' ? classNames[`${type}Done`] : `${classNames}-${type}-done`
return {
className,
activeClassName,
doneClassName,
}
},
/**
* 获取过渡持续时间
*/
getTimeouts() {
const { duration } = this.data
if (duration !== null && typeof duration === 'object') {
return {
enter: duration.enter,
exit: duration.exit,
}
} else if (typeof duration === 'number') {
return {
enter: duration,
exit: duration,
}
}
return {}
},
/**
* 属性值 in 被更改时的响应函数
* @param {Boolean} newVal 触发组件进入或离开过渡的状态
*/
updated(newVal) {
let { animateStatus } = this.pendingData || this.data
let nextStatus = null
if (newVal) {
if (animateStatus === UNMOUNTED) {
animateStatus = EXITED
this.setData({ animateStatus: EXITED }, () => {
this.triggerEvent('change', { animateStatus: EXITED })
})
}
if (animateStatus !== ENTER && animateStatus !== ENTERING && animateStatus !== ENTERED) {
nextStatus = ENTERING
}
} else {
if (animateStatus === ENTER || animateStatus === ENTERING || animateStatus === ENTERED) {
nextStatus = EXITING
}
}
this.updateStatus(nextStatus)
},
/**
* safeSetData
* @param {Object} nextData 数据对象
* @param {Function} callback 回调函数
*/
safeSetData(nextData, callback) {
this.pendingData = Object.assign({}, this.data, nextData)
callback = this.setNextCallback(callback)
this.setData(nextData, () => {
this.pendingData = null
callback()
})
},
/**
* 设置下一回调函数
* @param {Function} callback 回调函数
*/
setNextCallback(callback) {
let active = true
this.nextCallback = (event) => {
if (active) {
active = false
this.nextCallback = null
callback.call(this, event)
}
}
this.nextCallback.cancel = () => {
active = false
}
return this.nextCallback
},
/**
* 取消下一回调函数
*/
cancelNextCallback() {
if (this.nextCallback !== null) {
this.nextCallback.cancel()
this.nextCallback = null
}
},
/**
* 延迟一段时间触发回调
* @param {Number} timeout 延迟时间
* @param {Function} handler 回调函数
*/
delayHandler(timeout, handler) {
if (timeout) {
this.setNextCallback(handler)
setTimeout(this.nextCallback, timeout)
}
},
/**
* 点击事件
*/
onTap() {
this.triggerEvent('click')
},
},
created() {
this.nextCallback = null
},
attached() {
let animateStatus = null
let appearStatus = null
if (this.data.in) {
if (this.data.appear) {
animateStatus = EXITED
appearStatus = ENTERING
} else {
animateStatus = ENTERED
}
} else {
if (this.data.unmountOnExit || this.data.mountOnEnter) {
animateStatus = UNMOUNTED
} else {
animateStatus = EXITED
}
}
// 由于小程序组件首次挂载时 observer 事件总是优先于 attached 事件
// 所以使用 isMounting 来强制优先触发 attached 事件
this.safeSetData({ animateStatus, isMounting: true }, () => {
this.triggerEvent('change', { animateStatus })
this.updateStatus(appearStatus, true)
})
},
detached() {
this.cancelNextCallback()
},
})
\ No newline at end of file
<view class="wux-class {{ animateCss }}" bindtap="onTap" bindtransitionend="onTransitionEnd" bindanimationend="onAnimationEnd" wx:if="{{ animateStatus !== 'unmounted' }}">
<slot></slot>
</view>
\ No newline at end of file
.wux-animate--fadeIn-enter {
-webkit-transition: opacity .3s;
transition: opacity .3s;
opacity: 0;
}
.wux-animate--fadeIn-enter-active,
.wux-animate--fadeIn-enter-done {
opacity: 1;
}
.wux-animate--fadeIn-exit {
-webkit-transition: opacity .3s;
transition: opacity .3s;
opacity: 1;
}
.wux-animate--fadeIn-exit-active,
.wux-animate--fadeIn-exit-done {
opacity: 0;
}
.wux-animate--fadeInDown-enter {
-webkit-transition: opacity .3s, -webkit-transform .3s;
transition: opacity .3s, -webkit-transform .3s;
transition: opacity .3s, transform .3s;
transition: opacity .3s, transform .3s, -webkit-transform .3s;
opacity: 0;
-webkit-transform: translate3d(0, -100%, 0);
transform: translate3d(0, -100%, 0);
}
.wux-animate--fadeInDown-enter-active,
.wux-animate--fadeInDown-enter-done {
opacity: 1;
-webkit-transform: none;
transform: none;
}
.wux-animate--fadeInDown-exit {
-webkit-transition: opacity .3s, -webkit-transform .3s;
transition: opacity .3s, -webkit-transform .3s;
transition: opacity .3s, transform .3s;
transition: opacity .3s, transform .3s, -webkit-transform .3s;
opacity: 1;
-webkit-transform: none;
transform: none;
}
.wux-animate--fadeInDown-exit-active,
.wux-animate--fadeInDown-exit-done {
opacity: 0;
-webkit-transform: translate3d(0, -100%, 0);
transform: translate3d(0, -100%, 0);
}
.wux-animate--fadeInLeft-enter {
-webkit-transition: opacity .3s, -webkit-transform .3s;
transition: opacity .3s, -webkit-transform .3s;
transition: opacity .3s, transform .3s;
transition: opacity .3s, transform .3s, -webkit-transform .3s;
opacity: 0;
-webkit-transform: translate3d(-100%, 0, 0);
transform: translate3d(-100%, 0, 0);
}
.wux-animate--fadeInLeft-enter-active,
.wux-animate--fadeInLeft-enter-done {
opacity: 1;
-webkit-transform: none;
transform: none;
}
.wux-animate--fadeInLeft-exit {
-webkit-transition: opacity .3s, -webkit-transform .3s;
transition: opacity .3s, -webkit-transform .3s;
transition: opacity .3s, transform .3s;
transition: opacity .3s, transform .3s, -webkit-transform .3s;
opacity: 1;
-webkit-transform: none;
transform: none;
}
.wux-animate--fadeInLeft-exit-active,
.wux-animate--fadeInLeft-exit-done {
opacity: 0;
-webkit-transform: translate3d(-100%, 0, 0);
transform: translate3d(-100%, 0, 0);
}
.wux-animate--fadeInRight-enter {
-webkit-transition: opacity .3s, -webkit-transform .3s;
transition: opacity .3s, -webkit-transform .3s;
transition: opacity .3s, transform .3s;
transition: opacity .3s, transform .3s, -webkit-transform .3s;
opacity: 0;
-webkit-transform: translate3d(100%, 0, 0);
transform: translate3d(100%, 0, 0);
}
.wux-animate--fadeInRight-enter-active,
.wux-animate--fadeInRight-enter-done {
opacity: 1;
-webkit-transform: none;
transform: none;
}
.wux-animate--fadeInRight-exit {
-webkit-transition: opacity .3s, -webkit-transform .3s;
transition: opacity .3s, -webkit-transform .3s;
transition: opacity .3s, transform .3s;
transition: opacity .3s, transform .3s, -webkit-transform .3s;
opacity: 1;
-webkit-transform: none;
transform: none;
}
.wux-animate--fadeInRight-exit-active,
.wux-animate--fadeInRight-exit-done {
opacity: 0;
-webkit-transform: translate3d(100%, 0, 0);
transform: translate3d(100%, 0, 0);
}
.wux-animate--fadeInUp-enter {
-webkit-transition: opacity .3s, -webkit-transform .3s;
transition: opacity .3s, -webkit-transform .3s;
transition: opacity .3s, transform .3s;
transition: opacity .3s, transform .3s, -webkit-transform .3s;
opacity: 0;
-webkit-transform: translate3d(0, 100%, 0);
transform: translate3d(0, 100%, 0);
}
.wux-animate--fadeInUp-enter-active,
.wux-animate--fadeInUp-enter-done {
opacity: 1;
-webkit-transform: none;
transform: none;
}
.wux-animate--fadeInUp-exit {
-webkit-transition: opacity .3s, -webkit-transform .3s;
transition: opacity .3s, -webkit-transform .3s;
transition: opacity .3s, transform .3s;
transition: opacity .3s, transform .3s, -webkit-transform .3s;
opacity: 1;
-webkit-transform: none;
transform: none;
}
.wux-animate--fadeInUp-exit-active,
.wux-animate--fadeInUp-exit-done {
opacity: 0;
-webkit-transform: translate3d(0, 100%, 0);
transform: translate3d(0, 100%, 0);
}
.wux-animate--slideInUp-enter {
-webkit-transition: -webkit-transform .3s;
transition: -webkit-transform .3s;
transition: transform .3s;
transition: transform .3s, -webkit-transform .3s;
-webkit-transform: translate3d(0, 100%, 0);
transform: translate3d(0, 100%, 0);
visibility: visible;
}
.wux-animate--slideInUp-enter-active,
.wux-animate--slideInUp-enter-done {
-webkit-transform: translateZ(0);
transform: translateZ(0);
}
.wux-animate--slideInUp-exit {
-webkit-transition: -webkit-transform .3s;
transition: -webkit-transform .3s;
transition: transform .3s;
transition: transform .3s, -webkit-transform .3s;
-webkit-transform: translateZ(0);
transform: translateZ(0);
}
.wux-animate--slideInUp-exit-active,
.wux-animate--slideInUp-exit-done {
-webkit-transform: translate3d(0, 100%, 0);
transform: translate3d(0, 100%, 0);
visibility: visible;
}
.wux-animate--slideInDown-enter {
-webkit-transition: -webkit-transform .3s;
transition: -webkit-transform .3s;
transition: transform .3s;
transition: transform .3s, -webkit-transform .3s;
-webkit-transform: translate3d(0, -100%, 0);
transform: translate3d(0, -100%, 0);
visibility: visible;
}
.wux-animate--slideInDown-enter-active,
.wux-animate--slideInDown-enter-done {
-webkit-transform: translateZ(0);
transform: translateZ(0);
}
.wux-animate--slideInDown-exit {
-webkit-transition: -webkit-transform .3s;
transition: -webkit-transform .3s;
transition: transform .3s;
transition: transform .3s, -webkit-transform .3s;
-webkit-transform: translateZ(0);
transform: translateZ(0);
}
.wux-animate--slideInDown-exit-active,
.wux-animate--slideInDown-exit-done {
-webkit-transform: translate3d(0, -100%, 0);
transform: translate3d(0, -100%, 0);
visibility: visible;
}
.wux-animate--slideInLeft-enter {
-webkit-transition: -webkit-transform .3s;
transition: -webkit-transform .3s;
transition: transform .3s;
transition: transform .3s, -webkit-transform .3s;
-webkit-transform: translate3d(-100%, 0, 0);
transform: translate3d(-100%, 0, 0);
visibility: visible;
}
.wux-animate--slideInLeft-enter-active,
.wux-animate--slideInLeft-enter-done {
-webkit-transform: translateZ(0);
transform: translateZ(0);
}
.wux-animate--slideInLeft-exit {
-webkit-transition: -webkit-transform .3s;
transition: -webkit-transform .3s;
transition: transform .3s;
transition: transform .3s, -webkit-transform .3s;
-webkit-transform: translateZ(0);
transform: translateZ(0);
}
.wux-animate--slideInLeft-exit-active,
.wux-animate--slideInLeft-exit-done {
-webkit-transform: translate3d(-100%, 0, 0);
transform: translate3d(-100%, 0, 0);
visibility: visible;
}
.wux-animate--slideInRight-enter {
-webkit-transition: -webkit-transform .3s;
transition: -webkit-transform .3s;
transition: transform .3s;
transition: transform .3s, -webkit-transform .3s;
-webkit-transform: translate3d(100%, 0, 0);
transform: translate3d(100%, 0, 0);
visibility: visible;
}
.wux-animate--slideInRight-enter-active,
.wux-animate--slideInRight-enter-done {
-webkit-transform: translateZ(0);
transform: translateZ(0);
}
.wux-animate--slideInRight-exit {
-webkit-transition: -webkit-transform .3s;
transition: -webkit-transform .3s;
transition: transform .3s;
transition: transform .3s, -webkit-transform .3s;
-webkit-transform: translateZ(0);
transform: translateZ(0);
}
.wux-animate--slideInRight-exit-active,
.wux-animate--slideInRight-exit-done {
-webkit-transform: translate3d(100%, 0, 0);
transform: translate3d(100%, 0, 0);
visibility: visible;
}
import baseBehavior from '../helpers/baseBehavior'
Component({
behaviors: [baseBehavior],
externalClasses: ['wux-class'],
properties: {
transparent: {
type: Boolean,
value: false,
},
},
methods: {
/**
* 保持锁定
*/
retain() {
if (typeof this.backdropHolds !== 'number' || !this.backdropHolds) {
this.backdropHolds = 0
}
this.backdropHolds = this.backdropHolds + 1
if (this.backdropHolds === 1) {
this.$$setData({ in: true })
}
},
/**
* 释放锁定
*/
release() {
if (this.backdropHolds === 1) {
this.$$setData({ in: false })
}
this.backdropHolds = Math.max(0, this.backdropHolds - 1)
},
/**
* 点击事件
*/
onClick() {
this.triggerEvent('click')
},
},
})
\ No newline at end of file
{
"component": true,
"usingComponents": {
"wux-animation-group": "../animation-group/index"
}
}
\ No newline at end of file
<wux-animation-group wux-class="{{ transparent ? 'wux-backdrop--transparent' : 'wux-backdrop' }}" in="{{ in }}" class-names="wux-animate--fadeIn" bind:click="onClick"></wux-animation-group>
\ No newline at end of file
.wux-backdrop {
background: rgba(0, 0, 0, 0.4);
}
.wux-backdrop,
.wux-backdrop--transparent {
position: fixed;
z-index: 1000;
top: 0;
right: 0;
left: 0;
bottom: 0;
}
.wux-backdrop--transparent {
background: transparent;
}
/**
* Simple bind, faster than native
*
* @param {Function} fn
* @param {Object} ctx
* @return {Function}
*/
const bind = (fn, ctx) => {
return (...args) => {
return args.length ? fn.apply(ctx, args) : fn.call(ctx)
}
}
/**
* Object assign
*/
const assign = (...args) => Object.assign({}, ...args)
export default Behavior({
properties: {
visible: {
type: Boolean,
value: false,
},
},
methods: {
/**
* 合并参数并绑定方法
*
* @param {Object} opts 参数对象
* @param {Object} fns 方法挂载的属性
*/
$$mergeOptionsAndBindMethods(opts = {}, fns = this.fns) {
const options = Object.assign({}, opts)
for (const key in options) {
if (options.hasOwnProperty(key) && typeof options[key] === 'function') {
fns[key] = bind(options[key], this)
delete options[key]
}
}
return options
},
/**
* Promise setData
* @param {Array} args 参数对象
*/
$$setData(...args) {
const params = assign({}, ...args)
return new Promise((resolve) => {
this.setData(params, resolve)
})
},
/**
* 延迟指定时间执行回调函数
* @param {Function} callback 回调函数
* @param {Number} timeout 延迟时间
*/
$$requestAnimationFrame(callback = () => {}, timeout = 1000 / 60) {
return new Promise((resolve) => setTimeout(resolve, timeout)).then(callback)
},
},
/**
* 组件生命周期函数,在组件实例进入页面节点树时执行
*/
created() {
this.fns = {}
},
/**
* 组件生命周期函数,在组件实例被从页面节点树移除时执行
*/
detached() {
this.fns = {}
},
})
\ No newline at end of file
export const colors = {
'light': '#ddd',
'stable': '#b2b2b2',
'positive': '#387ef5',
'calm': '#11c1f3',
'balanced': '#33cd5f',
'energized': '#ffc900',
'assertive': '#ef473a',
'royal': '#886aea',
'dark': '#444',
}
export const isPresetColor = (color) => {
if (!color) {
return false
}
return colors[color] ? colors[color] : color
}
\ No newline at end of file
/**
* 获取触摸点位置信息
*/
export const getTouchPoints = (e, index = 0) => {
const { pageX: x, pageY: y } = e.touches[index] || e.changedTouches[index]
return {
x,
y,
}
}
/**
* 获取触摸点个数
*/
export const getPointsNumber = (e) => e.touches && e.touches.length || e.changedTouches && e.changedTouches.length
/**
* 判断是否为同一点
*/
export const isEqualPoints = (p1, p2) => p1.x === p2.x && p1.y === p2.y
/**
* 判断是否为相近的两点
*/
export const isNearbyPoints = (p1, p2, DOUBLE_TAP_RADIUS = 25) => {
const xMove = Math.abs(p1.x - p2.x)
const yMove = Math.abs(p1.y - p2.y)
return xMove < DOUBLE_TAP_RADIUS & yMove < DOUBLE_TAP_RADIUS
}
/**
* 获取两点之间的距离
*/
export const getPointsDistance = (p1, p2) => {
const xMove = Math.abs(p1.x - p2.x)
const yMove = Math.abs(p1.y - p2.y)
return Math.sqrt(xMove * xMove + yMove * yMove)
}
\ No newline at end of file
/**
* 过滤对象的函数属性
* @param {Object} opts
*/
const mergeOptionsToData = (opts = {}) => {
const options = Object.assign({}, opts)
for (const key in options) {
if (options.hasOwnProperty(key) && typeof options[key] === 'function') {
delete options[key]
}
}
return options
}
export default mergeOptionsToData
\ No newline at end of file
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册