WeTouch 开发文档

WeTouch 开发文档

page

页面容器。

WeTouch页面通常以<ui-page>节点为根节点,<ui-page>支持垂直方向的滚动、上拉、下拉、滚动到底加载等功能。

page提供两种页面滚动的方式。默认是区域滚动,通过设置page页面的config的scrollType参数为body来更改为整页滚动。详见文档的“方案>>页面滚动机制”

属性名 类型 默认值 说明
top [Number, String] 46 区域滚动模式下代表滚动条最顶部距离页面顶部的位置,默认为46(留出了nav-bar的高度);整页滚动模式下滚动条始终从0开始,这个属性代表内容部分的padding-top值,默认为46(留出了nav-bar的高度)
scroll-top [Number, String] 0 进入页面时滚动条初始的滚动位置
enable-reach-bottom-load Boolean false 是否到底加载
on-load-more Function 到底时的处理,此时一般用于请求数据并渲染到页面上
pull-up Object 上拉加载的处理
pull-down Object 下拉刷新的处理
bindscroll EventHandle 滚动时触发,返回scrollTop
bindscrollstart EventHandle 开始滚动时触发,返回scrollTop
bindscrollend EventHandle 结束滚动时触发,返回scrollTop
page-load Object 页面加载时的回调函数,和mounted 区别 见文档 “框架 >> 方案 >> 初始化函数”
show-loading Boolean true 是否显示框架loading
auto-hide-loading Boolean true dom加载完毕后是否自动隐藏。默认为自动隐藏。如果有网络请求,可以将此参数设为false,待请求结束后再隐藏。
pull-up属性表
属性 默认值 说明
distance 50 上拉多少高度时触发加载
onBegin EventHandle 上拉时触发,一般可用于自定义上拉动画。 返回值对象包含distance【拉动的距离】、direction【拉动的方向】
onActive EventHandle 上拉开始时触发,一般请求写在这里
onAfter EventHandle 上拉结束后触发,一般用于请求结束后,把数据显示出来。 如果成功触发刷新,返回值为1,否则没有返回值。
disableContentMove [] 触发上拉加载时,是否采用内容固定模式,可选值有三个['android', 'ios','web'] 。未使用的值依然保持内容上拉的模式。
pull-down属性表
属性 默认值 说明
distance 50 下拉多少高度时触发刷新
onBegin EventHandle 下拉时触发,一般可用于自定义下拉动画。 返回值对象包含distance【拉动的距离】、direction【拉动的方向】
onActive EventHandle 下拉开始时触发,一般请求写在这里
onAfter EventHandle 下拉结束后触发,一般用于请求结束后,把数据显示出来。 如果成功触发刷新,返回值为1,否则没有返回值。
disableContentMove [] 触发下拉刷新时,是否采用内容固定模式,可选值有三个['android', 'ios','web'] 。未使用的值依然保持内容下拉的模式。

ui.pageScrollTo()

页面滚动API,用来滚动页面到某位置。有两个参数。

第一个参数可以是元素的id,代表滚动到这个元素的位置;也可以是数值,代表滚动到距离顶部的位置。

第二个参数是滚动的动画时间,当为0时无动画直接到某个位置。

ui.startPullUpLoad()

上拉加载API,用于外部触发上拉加载。

ui.startPullDownRefresh()

下拉刷新API,用于外部触下拉刷新。

Bug&Tip

1、如果要实现当前页面不出现nav-bar,除了设置页面配置项 navigationStyle 为“custom” 还需要为page组件添加top=“0” 的属性。

2、整页滚动模式下所有内容必须都在page组件内,区域滚动模式中某些特殊场景可以在page外放内容,但框架要求每个页面必须只有一个根节点,不能多个根节点并列,例如下面的写法会报错:

<ui-view class="bg_blue"></ui-view>  
<ui-page></ui-page>

需要在最外侧用一个根节点将所有内容包含

<ui-view>
  <ui-view class="bg_blue"></ui-view>  
  <ui-page></ui-page>
</ui-view>

此外,页面的根结点不能被注释,否则会报错。

典型示例

滚动到底自动加载

要点是设置enable-reach-bottom-load,并为on-load-more指定处理函数。

当滚动到底时自动触发on-load-more指定的函数,并出现loading图标。在处理函数发送request网络请求追加数据,界面内容增加后loading会自动消失。

查看示例代码
<!--page2.ui-->
<template>
    <ui-page
    enable-reach-bottom-load="{{loadMore}}"
    on-load-more="{{ handleLoadMore }}">
    <ui-view class="content_list">
      <ui-view ui:for="{{ items }}" class="{{{'grey-bg': index % 2 == 0}}}">
        {{ item }}
      </ui-view>
    </ui-view>
    <ui-view style="width:200px;margin:0 auto;">
      <ui-divider ui:show="{{!loadMore}}">没有新数据了</ui-divider>
    </ui-view>

  </ui-page>
</template>


<script>
// page2.js
export default {
  config: {
    navigationBarTitleText: "滚动到底自动加载"
  },
  data () {
    return {
      loadMore:true,
      items: [],
      bottom: 30,
      count:0
    }
  },
  methods: {
    handleLoadMore () {
      this.count ++
      if(this.count > 2){
        this.loadMore = false
        return false
      }{
        window.setTimeout(() => {
          for (let i = this.bottom + 1; i <= this.bottom + 10; i++) {
            this.items.push(`列表项目${i}`)
          }
          this.bottom += 10
        }, 1500)
      }

    }
  },
  mounted () {
    for (let i = 1; i <= this.bottom; i++) {
      this.items.push(`列表项目${i}`)
    }
  }
}

</script>

<style lang="less">
</style>

底部上拉加载

底部上拉加载和到底自动加载各有应用场景。底部上拉加载是指列表到底后不会自动发起新的请求,将是否查看下一页的权利交给用户。

查看示例代码
<!--page2.ui-->
<template>
    <ui-page
    pull-up="{{ pullUp }}">
    <ui-view class="content_list">
      <ui-view ui:for="{{ items }}" class="{{{'grey-bg': index % 2 == 0}}}">
        {{ item }}
      </ui-view>
    </ui-view>
  </ui-page>
</template>

<script>
// page2.js
export default {
  config: {
     navigationBarTitleText: "底部上拉加载"
  },
  data () {
    return {
      items: [],
      bottom: 30,
      pullUp: {
        distance: 50,
        onBegin: () => {},
        onActive: this.handleActive,
        onAfter: this.handlePullUpAfter
      }
    }
  },
  methods: {
    handleActive () {
      // 将返回的请求接管,实现让请求结果来控制下拉刷新的状态
      return ui.request({
        // promise设置为true,让请求返回promise,这样就可以接管请求
        // 请求结束后页面自动回弹
        promise: true,
        url: '/touchui-backstage/listInfo.do?state=1',
        success: (response) => {
        },
        fail: (err) => {
        }
      })
    },
     // 下拉结束后,执行的函数。因为只要下拉即时没有到达刷新的高度也会触发这个方法
     // flag 为1表示执行了handleActive。为undefined代表handleActive没有执行。
    handlePullDownAfter (flag) {
      if (flag) {
        ui.showToast({
          title: '处理下拉刷新'
        })
      }
    },
    handlePullUpAfter (flag) {
      if (flag) {
        for (let i = this.bottom + 1; i <= this.bottom + 10; i++) {
          this.items.push(`列表项目${i}`)
        }
        this.bottom += 10
      }
    },
    handleLoadMore () {
      window.setTimeout(() => {
        for (let i = this.bottom + 1; i <= this.bottom + 10; i++) {
          this.items.push(`列表项目${i}`)
        }
        this.bottom += 10
      }, 1500)
    }
  },
  mounted () {
    for (let i = 1; i <= this.bottom; i++) {
      this.items.push(`列表项目${i}`)
    }
  }
}

</script>

<style lang="less">
</style>

底部上拉加载(自定义样式)

这里自定义了底部的提示语和loading样式,并且可以点击加载新内容。

查看示例代码
<template>
    <ui-page
    pull-up="{{ pullUp }}">
    <ui-view class="content_list">
      <!-- <ui-button bindtap="getPushInfo">测试</ui-button> -->
      <ui-view ui:for="{{ items }}" class="{{{'grey-bg': index % 2 == 0}}}">
        {{ item }}
      </ui-view>
    </ui-view>
    <ui-view slot="pull-up" bindtap="pullup">
      <ui-view ui:show="state === 0" style="text-align:center;height:40px;line-height:40px;">点击或上拉加载更多</ui-view>
      <ui-view ui:show="state === 1" style="text-align:center;height:40px;line-height:40px;">↑上拉加载</ui-view>
      <ui-view ui:show="state === 2" style="text-align:center;height:40px;line-height:40px;">↓释放加载</ui-view>
      <ui-view ui:show="state === 3" style="text-align:center;height:40px;line-height:40px;">
          <div class='rect_wrap'><div class='rect rect1'></div><div class='rect rect2'></div><div class='rect rect3'></div><div class='rect rect4'></div><div class='rect rect5'></div></div>
      </ui-view>
      <ui-view style="width:200px;margin:0 auto;">
        <ui-divider ui:show="state === 4">没有新数据了</ui-divider>
      </ui-view>
    </ui-view>
  </ui-page>
</template>

<script>
export default {
  config: {
     navigationBarTitleText: "加载自定义样式"
  },
  data () {
    return {
      items: [],
      bottom: 30,
      state: 0,
      proportion: 0,
      pullUp: {
        distance: 50,
        onBegin: this.handleBegin,
        onActive: this.handleActive,
        onAfter: this.handlePullUpAfter
      },
      count:0,
      show:false

    }
  },
  methods: {
    getPushInfo(){
      console.log('getPushInfo')
      ui.getPushInfo({
      success: function (res) {
        console.log('成功', res)
        that.clientid = res.clientid
      },
      fail: function (res) {
        console.log('失败', res)
      }
    })
    },
    handleBegin ({ distance, direction }) {
      this.proportion = Math.abs(distance) / 50
      this.state = 1
      if (this.proportion >= 1) {
        this.state = 2
      }
    },
    handleActive () {
      this.state = 3
      // 将返回的请求接管,实现让请求结果来控制下拉刷新的状态
      return ui.request({
        // promise设置为true,让请求返回promise,这样就可以接管请求
        // 请求结束后页面自动回弹
        promise: true,
        url: '/touchui-backstage/listInfo.do?state=1',
        success: (response) => {
        },
        fail: (err) => {
        }
      })
    },
    handlePullUpAfter (flag) {
      if (flag) {
        this.count ++
        if(this.count > 2){
          this.state = 4
          // this.show = true
          return false
        }else if(this.count <= 2){
          this.state = 0
          // 模拟数据,这里应该从handleActive 里从接口拿到数据
          for (let i = this.bottom + 1; i <= this.bottom + 10; i++) {
            this.items.push(`列表项目${i}`)
          }
          this.bottom += 10
        }else{
        this.state = 0
        }
      }
    },
    pullup () {
      ui.startPullUpLoad()
    }
  },
  mounted () {

    for (let i = 1; i <= this.bottom; i++) {
      this.items.push(`列表项目${i}`)
    }
  }
}
</script>

<style lang="less">
//rect
.rect_wrap {
  margin: 0px auto;
  width: 50px;
  height: 30px;
  text-align: center;
  font-size: 10px;
  margin-top:4px;
  .ui-view {
    background-color: @loading-color;
    height: 100%;
    width: 2px;
    display: inline-block;

    -webkit-animation: stretchdelay 1.2s infinite ease-in-out;
    animation: stretchdelay 1.2s infinite ease-in-out;
  }
  div {
    background-color: @loading-color;
    height: 100%;
    width: 3px;
    display: inline-block;

    -webkit-animation: stretchdelay 1.2s infinite ease-in-out;
    animation: stretchdelay 1.2s infinite ease-in-out;
  }
  .rect{
    margin:2px;
  }
  .rect2 {
    -webkit-animation-delay: -1.1s;
    animation-delay: -1.1s;
  }
  .rect3 {
    -webkit-animation-delay: -1.0s;
    animation-delay: -1.0s;
  }
  .rect4 {
    -webkit-animation-delay: -0.9s;
    animation-delay: -0.9s;
  }
  .rect5 {
    -webkit-animation-delay: -0.8s;
    animation-delay: -0.8s;
  }
}
@-webkit-keyframes stretchdelay {
  0%, 40%, 100% { -webkit-transform: scaleY(0.4) } 
  20% { -webkit-transform: scaleY(1.0) }
}
@keyframes stretchdelay {
  0%, 40%, 100% {
    transform: scaleY(0.4);
    -webkit-transform: scaleY(0.4);
  }  20% {
    transform: scaleY(1.0);
    -webkit-transform: scaleY(1.0);
  }
}
// page10.less
@loading-color: #3399ff;
.ui-fixed-view {
  bottom: 100px;
  right: 20px;
  width: 46px;
  padding: 7px;
  height: 46px;
  line-height: 16px;
  border: 1px solid rgb(243,86,86);
  border-radius: 50%;
  font-size: 12px;
  color: #fff;
  text-align: center;
  box-sizing: border-box;
  background-color: rgb(243,86,86);
  z-index: 99;

  &:active {
    opacity: 0.8;
  }
}

</style>
滚动事件

滚动事件可以实时返回当前距离顶部的位置。

这里在开始滚动事件中记录当前距离顶部位置,滚动事件中判断当滚动距离大于100时,让小球收回,滚动结束事件中让小球再次出现。

查看示例代码
<template>
    <ui-page
    bindscroll="handleScroll"
    bindscrollstart="handleScrollStart"
    bindscrollend="handleScrollEnd">
    <ui-view class="content_list">
      <ui-view ui:for="{{ items }}" class="{{{'grey-bg': index % 2 == 0}}}">
        {{ item }}
      </ui-view>
    </ui-view>
    <ui-fixed-view class="{{ className }}">
      <ui-icon type="service" size="28" color="#fff"></ui-icon>
    </ui-fixed-view>
  </ui-page>
</template>

<script>
// page3.js
export default {
  config: {
     navigationBarTitleText: "滚动事件"
  },
  data () {
    return {
      items: [],
      className: '',
      scrollChange: 0
    }
  },
  mounted () {
    for (let i = 1; i <= 50; i++) {
      this.items.push(`列表项目${i}`)
    }
  },
  methods: {
    handleScrollStart (scrollTop) {
      this.scrollChange = scrollTop
    },
    handleScroll (scrollTop) {
      if (Math.abs(scrollTop - this.scrollChange) > 100) {
        this.className = 'active'
      }
    },
    handleScrollEnd (scrollTop) {
      this.className = ''
    }
  }
}

</script>

<style lang="less">
.ui-fixed-view {
  bottom: 100px;
  right: 15px;
  width: 40px;
  height: 40px;
  line-height: 40px;
  text-align: center;
  border-radius: 50%;
  overflow: hidden;
  background-color: #F76346;
  z-index: 99;
  transition: all .25s ease-in;
  box-shadow: 0px 0px 0px 5px #FCD4B9;
  opacity: 1;
  &.active {
    right: -60px;
    opacity: 0;
  }
}
</style>

外部控制滚动

通过bindscroll来根据当前滚动位置显示不同的按钮。点击按钮调用页面滚动api进行控制。

查看示例代码
<template>
    <ui-page 
    bindscroll="handleScroll">
    <ui-view class="content_list">
      <ui-view ui:for="{{ items }}" class="{{{'grey-bg': index % 2 == 0}}}">
        {{ item }}
      </ui-view>
    </ui-view>
    <ui-view class="wrapper">
      <div id="suggestion-title">推荐列表</div>
    </ui-view>
    <ui-view class="content_list">
      <ui-view ui:for="{{ items2 }}" class="{{{'grey-bg': index % 2 == 0}}}">
        {{ item }}
      </ui-view>
    </ui-view>
    <ui-fixed-view bindtap="gotoSuggestions" ui:show="{{ show1 }}">查看推荐</ui-fixed-view>
    <ui-fixed-view class="back-to-top" bindtap="gotoTop" ui:show="{{ show2 }}">返回顶部</ui-fixed-view>
  </ui-page>
</template>

<script>
  // page4.js
export default {
  config: {
     navigationBarTitleText: "外部控制滚动"
  },
  data () {
    return {
      items: [],
      items2: [],
      bottom: 30,
      show1: true,
      show2: false
    }
  },
  mounted () {
    for (let i = 1; i <= this.bottom; i++) {
      this.items.push(`列表项目${i}`)
    }
    for (let i = this.bottom + 1; i <= 60; i++) {
      this.items2.push(`列表项目${i}`)
    }
  },
  methods: {
    gotoSuggestions (scrollTop) {
      ui.pageScrollTo('#suggestion-title')
    },
    gotoTop () {
      ui.pageScrollTo(0)
    },
    handleScroll (scrollTop) {
      if (scrollTop > 1600) {
        this.show2 = true
        this.show1 = false
      } else {
        this.show2 = false
        this.show1 = true
      }
    }
  }
}
</script>

<style lang="less">
#suggestion-title {
  background: #fff;
  height: 50px;
  line-height: 50px;
  text-align: center;
  color: #333;
  background-color: lightyellow;
}

.ui-fixed-view {
  bottom: 100px;
  right: 20px;
  width: 46px;
  padding: 7px;
  height: 46px;
  line-height: 16px;
  border: 1px solid rgb(243,86,86);
  border-radius: 50%;
  font-size: 12px;
  color: #fff;
  text-align: center;
  box-sizing: border-box;
  background-color: rgb(243,86,86);
  z-index: 99;

  &:active {
    opacity: 0.8;
  }
}


.back-to-top {
  // bottom: 150px;
  border: 1px solid #666;
  background-color: #666;
}

.wrapper {
  position: relative;
}
</style>
滚动后记住位置

监听滚动结束事件,将当前位置存入localstorage,下次进入页面读取该位置通过scroll-top进行滚动定位。

查看示例代码
<template>
    <ui-page
    scroll-top="{{ scrollPosition }}"
    bindscrollend="handleScrollEnd">
    <ui-view class="content_list">
      <ui-view ui:for="{{ items }}" class="{{{'grey-bg': index % 2 == 0}}}">
        {{ item }}
      </ui-view>
    </ui-view>
  </ui-page>
</template>

<script>
  export default {
    config: {
     navigationBarTitleText: "滚动后记住位置"
    },
    data () {
      return {
        items: [],
        bottom: 30,
        scrollPosition: 0,
        key: 'scrollEnd'
      }
    },
    mounted () {
      var value = ui.getStorageSync(this.key)
      this.scrollPosition = value || 0

      for (let i = 1; i <= this.bottom; i++) {
        this.items.push(`列表项目${i}`)
      }
    },
    methods: {
      handleScrollEnd (scrollTop) {
        ui.setStorageSync(this.key, scrollTop)
      }
    }
  }

</script>

<style lang="less">

</style>

下拉刷新:基本使用

要点是下拉刷新的处理,仔细阅读注释内容。

查看示例代码
<template>
    <ui-page pull-down="{{ pullDown }}">
      <ui-view class="content_list">
        <ui-view ui:for="{{ items }}" class="{{{'grey-bg': index % 2 == 0}}}">
          {{ item }}
        </ui-view>
      </ui-view>
  </ui-page>
</template>

<script>
export default {
  config: {
    navigationBarTitleText: "基本下拉刷新"
  },
  data () {
    return {
      items: [],
      top: 0,
      bottom: 30,
      pullDown: {
        distance: 50,
        disableContentMove: [''],
        onBegin: () => {},
        onActive: this.handleActive,
        onAfter: this.handleAfter
      }
    }
  },
  mounted () {
    for (let i = 1; i <= this.bottom; i++) {
      this.items.push(`列表项目${i}`)
    }
  },
  methods: {
    handleActive () {
      // 将返回的请求接管,实现让请求结果来控制下拉刷新的状态
      return ui.request({
        // promise设置为true,让请求返回promise,这样就可以接管请求
        // 请求结束后页面自动回弹
        promise: true,
        url: '/touchui-backstage/listInfo.do?state=1',
        success: (response) => {
        },
        fail: (err) => {
        }
      })
    },
     // 下拉结束后,执行的函数。因为只要下拉即时没有到达刷新的高度也会触发这个方法
     // flag 为1表示执行了handleActive。为undefined代表handleActive没有执行。
    handleAfter (flag) {
      if (flag) {
        for (let i = this.top - 1; i >= this.top - 10; i--) {
          this.items.unshift(`列表项目${i}`)
        }
        this.top -= 10
      }
    }
  }
}

</script>

<style lang="less">

</style>

下拉刷新:自定义样式

通过下拉刷新的相关参数结合CSS动画可以自定义任何的下拉刷新动画。

这需要比较高的CSS功底和对下拉刷新机制的理解。这里的示例可以仔细研究一下。

查看示例代码
<template>
    <ui-page pull-down="{{ pullDown }}">
      <ui-view slot="pull-down" class="custom-pull-down-content">
        <ui-view class="img-layer" ui:if="{{proportion < 1}}">
          <ui-view class="img_content" style="{{{ height : proportion * 100+'px' }}}"></ui-view>
        </ui-view>

        <ui-view class="img-layer" ui:else>
          <ui-view class="mt-ready" ui:if="{{state === 2}}"></ui-view>
          <ui-view class="mt-loading" ui:show="{{state === 3 || state === 4}}"></ui-view>
        </ui-view>
      </ui-view>
      <ui-view class="content_list">
        <ui-view ui:for="{{ items }}" class="{{{'grey-bg': index % 2 == 0}}}">
          {{ item }}
        </ui-view>
      </ui-view>
    </ui-page>
</template>

<script>
  // page7.js
export default {
  config: {
    navigationBarTitleText: "下拉刷新自定义样式"
  },
  data () {
    return {
      items: [],
      top: 0,
      bottom: 30,
      proportion: 0,
      // 下拉刷新(初始状态)
      state: 1,
      showLoading: false,
      imgSrc: require('#/images/mt_01.png'),
      pullDown: {
        distance: 60,
        onBegin: this.handleBegin,
        onActive: this.handleActive,
        onAfter: this.handleAfter
      }
    }
  },
  methods: {
    handleBegin ({ distance, direction }) {
      this.proportion = distance / 60
      // 拉满60px
      if (this.proportion >= 1) {
        if (this.state === 1 && direction === 'down') {
          // 释放刷新
          this.state = 2

          // 300ms吉祥物翻转时间
          window.setTimeout(() => {
            // 刷新中...
            this.state = 3
          }, 300)
        }
      } else {
        this.state = 1
      }
    },
    handleActive () {
      // 将返回的请求接管,实现让请求结果来控制下拉刷新的状态
      return ui.request({
        // promise设置为true,让请求返回promise,这样就可以接管请求
        // 请求结束后页面自动回弹
        promise: true,
        url: '/touchui-backstage/listInfo.do?state=1',
        success: (response) => {
          // 刷新成功...
          this.state = 4
        },
        fail: (err) => {
        }
      })
    },
    handleAfter (flag) {
      this.proportion = 0
      this.state = 1

      if (flag) {
        for (let i = this.top - 1; i >= this.top - 10; i--) {
          this.items.unshift(`列表项目${i}`)
        }
        this.top -= 10
      }
    }
  },
  mounted () {
    for (let i = 1; i <= this.bottom; i++) {
      this.items.push(`列表项目${i}`)
    }
  }
}

</script>

<style lang="less">
.custom-pull-down-content {
  height: 60px;
  margin-top: -60px;
  display: flex;
  align-items:flex-end;
  padding-bottom: 8px;
}


.img-layer {
  flex: 1;
  display: flex;
  justify-content: center;
  align-items: center;
  .img_content{
    width: 82px;
    background: url('~images/mt_run.png') no-repeat;
    background-position: -2px center;
    background-size: 1149px 100%;
    zoom: 0.5;
  }
}

.mt-ready {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 82px;
  height: 107px;
  background: url('~images/mt_run.png') no-repeat;
  animation: mt-ready steps(5, end) 300ms;
  zoom: 0.5;
}

.mt-loading {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 82px;
  height: 107px;
  background: url('~images/mt_run.png') no-repeat;
  animation: mt-loading steps(1, end) 300ms infinite;
  zoom: 0.5;
}

.content_list {
  z-index: -1;
}

@keyframes mt-ready {

  100% {
    background-position: -410px center;
  }
}

@keyframes mt-loading {
  0%{
    background-position: -495px center;
  }

  20%{
    background-position: -576px center;
  }

  40%{
    background-position: -658px center;
  }
  50%{
    background-position: -740px center;
  }
  60%{
    background-position: -823px center;
  }
  80%{
    background-position: -905px center;
  }
  90%{
    background-position: -986px center;
  }

  100% {
    background-position: -1068px center;
  }
}

</style>

下拉刷新:外部触发

要点是在page组件之外放置内容,并且设置page滚动条的起始位置。

这种布局适合区域滚动模式,如果是整页滚动模式,请查看文档的“组件>>基础>>整页滚动案例”

查看示例代码
<template>
  <ui-view>
    <ui-view class="top_content" style="{{{ top: headerTop }}}">
        <ui-tags
        data="{{list00}}"
        bindchange="singleTap"
        fixed-width
        col-number="4"></ui-tags>
    </ui-view>
    <ui-page top="176" backgroundColor="#F5F5F5" pull-down="{{ pullDown }}" >
        <!-- <ui-tags
        data="{{list00}}"
        bindchange="singleTap"
        fixed-width
        col-number="4"></ui-tags> -->
      <ui-view class="content_list">
        <ui-view ui:for="{{ items }}" class="{{{'grey-bg': index % 2 == 0}}}">
          {{ tagName }}:{{ item }}
        </ui-view>
      </ui-view>
    </ui-page>
  </ui-view>
</template>

<script>
export default {
  config: {
    navigationBarTitleText: "外部触发下拉刷新",
    "scrollType": "div"
  },
  data () {
    return {
      headerTop: ui.DEFAULT_HEADER_HEIGHT + 'px',
      items: [],
      bottom: 30,
      tempName: '新媒体运营',
      tagName: '新媒体运营',
      list00: [{
        text: '新媒体运营',
        tagClass: 'tag-before-00',
        tagSelectedClass: 'select-class',
        checked: true
      }, {
        text: '文案写作',
        tagClass: 'tag-before-00',
        tagSelectedClass: 'select-class',
        checked: false
      }, {
        text: '营销策划',
        tagClass: 'tag-before-00',
        tagSelectedClass: 'select-class',
        checked: false
      }, {
        text: '品牌公关',
        tagClass: 'tag-before-00',
        tagSelectedClass: 'select-class',
        checked: false
      }, {
        text: '市场推广',
        tagClass: 'tag-before-00',
        tagSelectedClass: 'select-class',
        checked: false
      }, {
        text: '用户运营',
        tagClass: 'tag-before-00',
        tagSelectedClass: 'select-class',
        checked: false
      }, {
        text: '团队管理',
        tagClass: 'tag-before-00',
        tagSelectedClass: 'select-class',
        checked: false
      }, {
        text: '全程课程',
        tagClass: 'tag-before-00',
        tagSelectedClass: 'select-class',
        checked: false
      }],
      pullDown: {
        distance: 60,
        onBegin: this.handleBegin,
        onActive: this.handleActive,
        onAfter: this.handleAfter
      }
    }
  },
  methods: {
    singleTap (opt) {
      this.tempName = this.list00[opt.index].text
      this.list00.forEach((item, index) => {
        item.checked = (index === opt.index)
      })
      ui.startPullDownRefresh()
    },
    handleAfter (flag) {
      if (flag) {
        this.tagName = this.tempName
      }
      this.tagName = this.tempName
    },

    handleLoadMore () {
      window.setTimeout(() => {
        for (let i = this.bottom + 1; i <= this.bottom + 10; i++) {
          this.items.push(`列表项目${i}`)
        }
        this.bottom += 10
      }, 1500)
    },
    handleActive () {
      // 将返回的请求接管,实现让请求结果来控制下拉刷新的状态
      return ui.request({
        // promise设置为true,让请求返回promise,这样就可以接管请求
        // 请求结束后页面自动回弹
        promise: true,
        url: '/touchui-backstage/listInfo.do?state=1',
        success: (response) => {
        },
        fail: (err) => {
        }
      })
    }
    // 下拉结束后,执行的函数。因为只要下拉即时没有到达刷新的高度也会触发这个方法
    // flag 为1表示执行了handleActive。为undefined代表handleActive没有执行。

  },
  mounted () {
    for (let i = 1; i <= this.bottom; i++) {
      this.items.push(`列表项目${i}`)
    }
  }
}

</script>

<style lang="less">

.top_content{
  padding: 10px 5px;
  position: absolute;
}

.tag-before-00{
  background: #F5F5F5;
  color: #525252;
  padding: 5 10px;
  border-radius: 20px;
  text-align: center;
  // height: 25px;
  display: flex;
  justify-content: center;
  align-items: center;
  line-height: 30px;
  font-size: 12px;
  margin: 10px 0;
}

.select-class {
  padding: 5 10px;
  border-radius: 20px;
  text-align: center;
  // height: 25px;
  display: flex;
  justify-content: center;
  align-items: center;
  line-height: 30px;
  font-size: 12px;
  margin: 10px 0;
  background: #EBF2FB;
  color: #3374AD;
}
</style>

下拉刷新:内容固定模式

通过disableContentMove来设置不同环境下是否采用内容固定模式。例如可以只让安卓端是内容固定的下拉刷新以提高性能。

查看示例代码
<template>
    <ui-page pull-down="{{ pullDown }}">
      <ui-view class="content_list">
        <ui-view ui:for="{{ items }}" class="{{{'grey-bg': index % 2 == 0}}}">
          {{ item }}
        </ui-view>
      </ui-view>
  </ui-page>
</template>

<script>
export default {
  config: {
    navigationBarTitleText: "内容固定下拉刷新",
    scrollType:"body"
  },
  data () {
    return {
      items: [],
      top:0,
      bottom: 30,
      pullDown: {
        distance: 84,
        onBegin: () => {},
        onActive: this.handleActive,
        onAfter: this.handleAfter,
        disableContentMove: ['android', 'ios', 'web']
      }
    }
  },
  mounted () {
    for (let i = 1; i <= this.bottom; i++) {
      this.items.push(`列表项目${i}`)
    }
  },
  methods: {
    handleActive () {
      // 将返回的请求接管,实现让请求结果来控制下拉刷新的状态
      return ui.request({
        // promise设置为true,让请求返回promise,这样就可以接管请求
        // 请求结束后页面自动回弹
        promise: true,
        url: '/touchui-backstage/listInfo.do?state=1',
        success: (response) => {
        },
        fail: (err) => {
        }
      })
    },
     // 下拉结束后,执行的函数。因为只要下拉即时没有到达刷新的高度也会触发这个方法
     // flag 为1表示执行了handleActive。为undefined代表handleActive没有执行。
    handleAfter (flag) {
      if (flag) {
        for (let i = this.top - 1; i >= this.top - 10; i--) {
          this.items.unshift(`列表项目${i}`)
        }
        this.top -= 10
      }
    }
  }
}

</script>

<style lang="less">

</style>
下拉刷新:内容固定模式自定义样式

查看示例代码
<template>
    <ui-page pull-down="{{ pullDown }}">
      <ui-view slot="pull-down" class="pull-down-content" >
        <ui-view class="refresh">
            <ui-image
            src="{{ require('#/images/friendCircle.png') }}"
            width="25"
            class="refresh_bg {{ className }}"
            style="{{{ transform: `rotate(${rotate}deg)` }}}"
            ></ui-image>
        </ui-view>
      </ui-view>
      <ui-view class="content_list">
        <ui-view ui:for="{{ items }}" class="{{{'grey-bg': index % 2 == 0}}}">
          {{ item }}
        </ui-view>
      </ui-view>
    </ui-page>
</template>


<script>
export default {
  config: {
    navigationBarTitleText: "刷新自定义样式",
    scrollType:"body"
  },
  data () {
    return {
      items: [],
      top: 0,
      bottom: 30,
      proportion: 0,
      // 下拉刷新(初始状态)
      state: 1,
      showLoading: false,
      className: '',
      rotate: 0,
      pullDown: {
        distance: 60,
        onBegin: this.handleBegin,
        onActive: this.handleActive,
        onAfter: this.handleAfter,
        disableContentMove: ['android', 'ios', 'web']
      }
    }
  },
  methods: {
    handleBegin ({ distance, direction }) {
      console.log(1231231231)
      this.proportion = distance / 60
      // 拉满60px
      if (this.proportion >= 1) {
        if (this.state === 1 && direction === 'down') {
          // 释放刷新
          this.state = 2

          // 300ms下拉动画时间
          // window.setTimeout(() => {
          //   // 下拉过程...
          //   this.state = 3
          // }, 300)
        }
      } else {
        this.state = 1
      }
      this.rotate = parseInt(distance * 5)
    },

    handleActive () {
      // 刷新中
      this.state = 4
      this.className = 'after'
      // 将返回的请求接管,实现让请求结果来控制下拉刷新的状态
      return ui.request({
        // promise设置为true,让请求返回promise,这样就可以接管请求
        // 请求结束后页面自动回弹
        promise: true,
        url: '/touchui-backstage/listInfo.do?state=1',
        success: (response) => {
        },
        fail: (err) => {
        }
      })

      // this.config.refresh = true
    },
    handleAfter (flag) {
      this.proportion = 0
      this.state = 1
      if (flag) {
        for (let i = this.top - 1; i >= this.top - 10; i--) {
          this.items.unshift(`列表项目${i}`)
        }
        this.top -= 10
      }
      this.className = ''
    }
  },
  mounted () {
    for (let i = 1; i <= this.bottom; i++) {
      this.items.push(`列表项目${i}`)
    }
  }
}

</script>

<style lang="less">
  .slotpulldown{
  -webkit-animation: img 1s steps(12, end) infinite;
  animation: img 1s steps(12, end) infinite;
}

@-webkit-keyframes img {
  0% {
    -webkit-transform: rotate3d(0, 0, 1, 0deg);
    transform: rotate3d(0, 0, 1, 0deg);
  }

  100% {
    -webkit-transform: rotate3d(0, 0, 1, 360deg);
    transform: rotate3d(0, 0, 1, 360deg);
  }
}

@keyframes img {
  0% {
    -webkit-transform: rotate3d(0, 0, 1, 0deg);
    transform: rotate3d(0, 0, 1, 0deg);
  }

  100% {
    -webkit-transform: rotate3d(0, 0, 1, 360deg);
    transform: rotate3d(0, 0, 1, 360deg);
  }
}

.custom-pull-down-content {
  height: 60px;
  margin-top: -60px;
  display: flex;
  align-items:flex-end;
  padding-bottom: 8px;
}

.content_list {
  z-index: -1;
}


.pull-down-content {
    height: 60px;
    margin-top: -60px;
    display: flex;
    align-items: flex-end; // padding-bottom: 8px;
    position: relative;
    z-index: 480;
    .mix-flex-y-center();
    .refresh {
        padding-left: 25px;
    }
    .refresh_bg {
        // width: 25px;
        // height: 25px;
        // background: url('~images/friendCircle.png') no-repeat center center;
        // background-size: 25px;
        transform: rotate(0deg);
        animation-duration: 0.2s;
    }
    .refresh_bg.after {
        animation: circling 1s linear 0s infinite;
    }
}

@keyframes circling {
    from {
        transform: rotate(0deg);
    }
    to {
        transform: rotate(360deg);
    }
}

</style>
顶部下拉彩蛋

对于不需要下拉刷新的页面,可以通过下拉刷新的方式实现一个下拉彩蛋。

查看示例代码
<template>
    <ui-page pull-down="{{ pullDown }}">

    <ui-view slot="pull-down" class="pull-down-content">

      <ui-view class="img-layer">
        <ui-view class="touch_ui" ></ui-view>
      </ui-view>
    </ui-view>
    <ui-view class="content_list">
      <ui-view ui:for="{{ items }}" class="{{{'grey-bg': index % 2 == 0}}}">
        {{ item }}
      </ui-view>
    </ui-view>
  </ui-page>
</template>

<script>
export default {
  config: {
    navigationBarTitleText: "下拉彩蛋"
  },
  data () {
    return {
      items: [],
      bottom: 30,
      pullDown: {
        distance: 150
      }
    }
  },
  methods: {

  },
  mounted () {
    for (let i = 1; i <= this.bottom; i++) {
      this.items.push(`列表项目${i}`)
    }
  }
}

</script>

<style lang="less">
.pull-down-content {
  height: 60px;
  margin-top: -60px;
  .mix-flex-center();
}


.img-layer {
  flex: 1;
  display: flex;
  justify-content: center;
  align-items: center;
  .touch_ui{
    width: 100px;
    height:100px;
    background: url('~images/logo-light.png') no-repeat;
    background-position: center 0;
    background-size: 100%;
  }
}
</style>
下拉刷新接管多请求示例

在下拉时同时接管多个请求

查看示例代码
<template>
    <ui-page pull-down="{{ pullDown }}">
      <ui-view class="content_list">
        <ui-view ui:for="{{ items }}" class="{{{'grey-bg': index % 2 == 0}}}">
          {{ item }}
        </ui-view>
      </ui-view>
  </ui-page>
</template>

<script>
export default {
  config: {
    navigationBarTitleText: "多请求示例"
  },
  data () {
    return {
      items: [],
      top: 0,
      bottom: 30,
      pullDown: {
        distance: 50,
        disableContentMove: [''],
        onBegin: () => {},
        onActive: this.handleActive,
        onAfter: this.handleAfter
      }
    }
  },
  mounted () {
    for (let i = 1; i <= this.bottom; i++) {
      this.items.push(`列表项目${i}`)
    }
  },
  methods: {
    handleActive () {
      // 将返回的请求接管,实现让请求结果来控制下拉刷新的状态
      let request1 = ui.request({
        // promise设置为true,让请求返回promise,这样就可以接管请求
        // 请求结束后页面自动回弹
        promise: true,
        url: '/touchui-backstage/listInfo.do?state=1',
        success: (response) => {
          console.log('request1 success!')
          // 刷新成功...
          this.state = 4
        },
        fail: (err) => {
        }
      })

      let request2 = ui.request({
        promise: true,
        url: '/touchui-backstage/listInfo.do?state=2',
        success: (response) => {
          console.log('request2 success!')
        },
        fail: (err) => {
        }
      })

      return Promise.all([request1, request2])


    },
     // 下拉结束后,执行的函数。因为只要下拉即时没有到达刷新的高度也会触发这个方法
     // flag 为1表示执行了handleActive。为undefined代表handleActive没有执行。
    handleAfter (flag) {
      if (flag) {
        for (let i = this.top - 1; i >= this.top - 10; i--) {
          this.items.unshift(`列表项目${i}`)
        }
        this.top -= 10
      }
    }
  }
}

</script>

<style lang="less">

</style>

下拉刷新在after事件中得到请求结果