123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395 |
- import baseComponent from '../helpers/baseComponent'
- import classNames from '../helpers/classNames'
- const defaultStyle = 'transition: transform .4s; transform: translate3d(0px, 0px, 0px) scale(1);'
- baseComponent({
- properties: {
- prefixCls: {
- type: String,
- value: 'wux-refresher',
- },
- pullingIcon: {
- type: String,
- value: '',
- },
- pullingText: {
- type: String,
- value: '下拉刷新',
- },
- refreshingIcon: {
- type: String,
- value: '',
- },
- refreshingText: {
- type: String,
- value: '正在刷新',
- },
- disablePullingRotation: {
- type: Boolean,
- value: false,
- },
- distance: {
- type: Number,
- value: 30,
- },
- prefixLCls: {
- type: String,
- value: 'wux-loader'
- },
- isShowLoadingText: {
- type: Boolean,
- value: false
- },
- loadingText: {
- type: String,
- value: '正在加载'
- },
- loadNoDataText: {
- type: String,
- value: '没有更多数据'
- },
- scrollTop: {
- type: Number,
- value: 0,
- observer: function (n) {
- let that = this
- // 获取节点高度
- const query = wx.createSelectorQuery();
- query.select(`#${this.id}`).boundingClientRect(function (res) {
- that.setData({
- newContentHeight: res.height
- })
- }).exec()
- const {
- newContentHeight,
- oldContentHeight,
- windowHeight,
- distance,
- loading,
- noData
- } = this.data
-
- if (windowHeight && !this.isRefreshing()) {
- // 到临界点时触发上拉加载
- // 防止节点高度一致时引发重复加载
- if (
- n > newContentHeight - windowHeight - (distance * 1.5) &&
- loading === false &&
- noData === false && newContentHeight !== oldContentHeight
- ) {
- this.setData({
- loading: true,
- refreshing: false,
- oldContentHeight: newContentHeight
- })
- this.triggerEvent('loadmore')
- } else if (
- loading === false &&
- noData === false
- ) {
- // 隐藏上拉加载动画
- this.hide()
- } else if(loading === true) {
- // 如果在加载中,保持内容的高度一致,以此来防止临界点重复加载
- this.setData({
- oldContentHeight: newContentHeight
- })
-
- }
- this.deactivate()
- }
- }
- },
- },
- data: {
- style: defaultStyle,
- visible: false,
- active: false,
- refreshing: false,
- tail: false,
- lVisible: false,
- noData: false, // 是否没有更多数据
- windowHeight: 0, // 窗口高度
- newContentHeight: 0, // 新节点内容高度
- oldContentHeight: 0, // 旧节点内容高度
- loading: false, // 判断是否正在加载
- },
- computed: {
- classes() {
- const {
- prefixCls,
- pullingText,
- pullingIcon,
- disablePullingRotation,
- refreshingText,
- refreshingIcon,
- visible,
- active,
- refreshing,
- tail,
- prefixLCls,
- loading,
- noData,
- } = this.data
- const wrap = classNames(prefixCls, {
- [`${prefixCls}--hidden`]: !visible,
- [`${prefixCls}--visible`]: visible,
- [`${prefixCls}--active`]: active,
- [`${prefixCls}--refreshing`]: refreshing,
- [`${prefixCls}--refreshing-tail`]: tail,
- })
- const content = classNames(`${prefixCls}__content`, {
- [`${prefixCls}__content--text`]: pullingText || refreshingText,
- })
- const iconPulling = classNames(`${prefixCls}__icon-pulling`, {
- [`${prefixCls}__icon-pulling--disabled`]: disablePullingRotation,
- })
- const textPulling = `${prefixCls}__text-pulling`
- const iconRefreshing = `${prefixCls}__icon-refreshing`
- const textRefreshing = `${prefixCls}__text-refreshing`
- const pIcon = pullingIcon || `${prefixCls}__icon--arrow-down`
- const rIcon = refreshingIcon || `${prefixCls}__icon--refresher`
- const lWrap = classNames(prefixLCls, {
- [`${prefixLCls}--hidden`]: !loading,
- [`${prefixLCls}--visible`]: loading,
- [`${prefixLCls}--end`]: noData,
- })
- const lContent = `${prefixLCls}__content`
- return {
- wrap,
- content,
- iconPulling,
- textPulling,
- iconRefreshing,
- textRefreshing,
- pIcon,
- rIcon,
- lWrap,
- lContent,
- }
- },
- },
- methods: {
- /**
- * 显示
- */
- activate() {
- this.setData({
- style: defaultStyle,
- visible: true,
- })
- },
- /**
- * 隐藏
- */
- deactivate() {
- if (this.activated) this.activated = false
- this.setData({
- style: defaultStyle,
- visible: false,
- active: false,
- refreshing: false,
- tail: false,
- })
- },
- /**
- * 正在刷新
- */
- refreshing() {
- this.setData({
- style: 'transition: transform .4s; transform: translate3d(0, 50px, 0) scale(1);',
- visible: true,
- active: true,
- refreshing: true,
- // 刷新时重新初始化加载状态
- loading: false,
- noData: false,
- newContentHeight: 0,
- oldContentHeight: 0,
- lVisible: false,
- })
- },
- /**
- * 刷新后隐藏动画
- */
- tail() {
- this.setData({
- visible: true,
- active: true,
- refreshing: true,
- tail: true,
- })
- },
- /**
- * 加载后隐藏动画
- */
- hide() {
- this.setData({
- lVisible: false,
- })
- },
- /**
- * 正在下拉
- * @param {Number} diffY 距离
- */
- move(diffY) {
- const style = `transition-duration: 0s; transform: translate3d(0, ${diffY}px, 0) scale(1);`
- const className = diffY < this.data.distance ? 'visible' : 'active'
- this.setData({
- style,
- [className]: true,
- })
- },
- /**
- * 判断是否正在刷新
- */
- isRefreshing() {
- return this.data.refreshing
- },
- /**
- * 判断是否正在加载
- */
- isLoading() {
- return this.data.loading
- },
- /**
- * 获取触摸点坐标
- */
- getTouchPosition(e) {
- return {
- x: e.changedTouches[0].pageX,
- y: e.changedTouches[0].pageY,
- }
- },
- /**
- * 创建定时器
- */
- requestAnimationFrame(callback) {
- let currTime = new Date().getTime()
- let timeToCall = Math.max(0, 16 - (currTime - this.lastTime))
- let timeout = setTimeout(() => {
- callback.bind(this)(currTime + timeToCall)
- }, timeToCall)
- this.lastTime = currTime + timeToCall
- return timeout
- },
- /**
- * 清空定时器
- */
- cancelAnimationFrame(timeout) {
- clearTimeout(timeout)
- },
- /**
- * 下拉刷新完成后的函数
- */
- finishPullToRefresh() {
- setTimeout(() => {
- this.requestAnimationFrame(this.tail)
- setTimeout(() => this.deactivate(), 200)
- }, 200)
- },
- /**
- * 上拉加载完成后的函数
- */
- finishLoadmore(bool) {
- if (bool === true) {
- setTimeout(() => {
- this.setData({
- noData: true,
- loading: false,
- })
- }, 200)
- } else {
- setTimeout(() => {
- this.setData({
- loading: false
- })
- this.requestAnimationFrame(this.hide)
- setTimeout(() => this.deactivate(), 200)
- }, 200)
- }
- },
- /**
- * 手指触摸动作开始
- */
- bindtouchstart(e) {
- if (this.isRefreshing() || this.isLoading()) return false
- const p = this.getTouchPosition(e)
- this.start = p
- this.diffX = this.diffY = 0
- this.activate()
- },
- /**
- * 手指触摸后移动
- */
- bindtouchmove(e) {
- if (!this.start || this.isRefreshing() || this.isLoading()) return false
- const p = this.getTouchPosition(e)
- this.diffX = p.x - this.start.x
- this.diffY = p.y - this.start.y
- if (this.diffY < 0) return false
- this.diffY = Math.pow(this.diffY, 0.8)
- if (!this.activated && this.diffY > this.data.distance) {
- this.activated = true
- this.triggerEvent('pulling')
- } else if (this.activated && this.diffY < this.data.distance) {
- this.activated = false
- }
- this.move(this.diffY)
- },
- /**
- * 手指触摸动作结束
- */
- bindtouchend(e) {
- this.start = false
- if (this.diffY <= 0 || this.isRefreshing() || this.isLoading()) return false
- this.deactivate()
- if (Math.abs(this.diffY) >= this.data.distance) {
- this.refreshing()
- this.triggerEvent('refresh')
- }
- },
- },
- created() {
- this.lastTime = 0
- this.activated = false
- },
- attached() {
- let that = this
- wx.getSystemInfo({
- success: function (res) {
- that.setData({
- windowHeight: res.windowHeight
- })
- }
- });
- }
- })
|