[学习小程序Vant-weapp 过渡组件的开发(1)]

1,932 阅读5分钟

简单的css过渡

我是小白1号,加油💪

transtion 组件是最为基础的组价

移动端里面,我们为了是生动一点,我们要做一个基础的组价,过渡 transition 组件,overlay(mask) 组价,我们可能会在很多大地方用到,但是我们不能每一次都写一遍,于是基础组件的重要性就体现出来,一个初级前端,还是要学会这写基础组件的封装。理解组件化的思想。

在 transition 组件里通过插槽来添加其他的内容,达到 transition 的效果。

以小程序为例,创建小程序过渡行为。

  1. 过渡元素的长度属性: width
  2. 监听过渡结束事件: transitionend
  3. 实现一个简单的 transition 组件
  4. 使用过渡如何实现: 进/出动画
  5. 实现一个类似 Vue transition 组件,具备 enter/leave,enter-active-to/leave-leave-to
  6. 小程序的 externalClasses 的理解

补充知识

  • transition-property, 要过渡的属性,可以是所有的属性
  • transition-duration, 过渡要持续的时间
  • transition-timing-function,// 过渡时的缓动函数
  • transition-delay // 过渡的持续时间

厂商前缀的添加,适应不同的浏览器,我们在使用过渡动画的时候,一般都会控制着几个属性。

补充基础:externalClasses 接受从组件外部传入的 class

externalClasses 类似于数据绑定,是直接从外部传入 class,然后直接使用

<transition show="{{show}}" haha="xixi"></transition>
.xixi {
    color: #fff;
    background: red
}

xixi 是当前要传入 transition 组件内部的 class, 里面 使用 externalClasses接收,在组件内部使用的时候,我们就采用 haha, 相当于转换了 class 的name;

<!--transition component-->
<view class="haha">haha class 来自外部类</view>

过渡元素的长度属性: width

<!--index.wxml-->
<view 
    bind:transitionend="onTransitionEnd" 
    class="wrap {{needChange ? 'wrap--active' : ''}}">
</view>

<button bindtap="change">transition</button>
// index.js
Page({
  data: {
    needChange: false,
  },
  change() {
    this.setData({
      needChange: !this.data.needChange
    })
  },
  onTransitionEnd() {
    wx.showToast({
      title: '过渡结束了...'
    })
  }
})

/*index.wxss*/
.wrap {
  width: 200rpx;
  height: 200rpx;
  background: red;
  /* transition 理解为监听属性的变化*/
  transition: width 2s;
}
<!--小程序中使用变量来控制class的变化,来触发 transition 过渡-->
.wrap--active {
  /* 过渡就是属性的变化 */
  width: 500rpx;
}

实现一个简单的 transition 组件

1- 通过传入 show 来控制,监听数据变化

原理: 组件传入的数据 show, 控制控制页面的 展示隐藏, 监听 show 的变化,可以从外部组件显示隐藏;

<view 
  bind:transitionend="onTransitionEnd" 
  class="wrap {{ show ? classes : ''}}">
</view>
// components/transition.js
Component({
  /**
   * 组件的属性列表
   */
  properties: {
    //  通过 show 控制,可以通过 observer 监听外部的变化
    show: {
      type: Boolean,
      value: false,
      observer: 'onShow'
    }
  },

  /**
   * 组件的初始数据
   */
  data: {
    needChange: false,
    classes: ''
  },
  // 组件在创建的时候,显示调用 enter
  attached() {
    if (this.data.show) {
      this.enter();
    }
  },

  /**
   * 组件的方法列表
   */
  methods: {
    onTransitionEnd() {
      wx.showToast({
        title: '过渡结束了...'
      })
    },
    // 进入
    enter()  {
      this.setData({
        classes: 'wrap--active'
      })
    },
    leave() {
      this.setData({
        classes: ''
      })
    },
    // 监听显示和隐藏
    onShow(value) {
      wx.showToast({
        title: '监听触发',
      })

      if(value) {
        this.enter()
      } else {
        this.leave()
      }
    }
  },
})

一个相对比较完整的小程序 transition 组件我们需要考虑什么东西?

  • 显示/隐藏:外部变量show控制,内部函数调用 this.enter() / this.leave(),在函数里面控制样式,使用了类 Vue 的写法
  • 持续时间: 过渡的持续时间
  • 过渡动画的形式:fade 系列 和 slide 系列
  • 基础的样式
  • 自定义样式: custom-class
  • setData 数据更新,为什么 nextTick:setData是异步的,vant-ui 里面使用 的nextTick 是一个 promise 的 setTimeout 的执行,使用 Promise.resolve 来处理链式任务。类似于 拦截器 的实现,整体是一个 promise 化一个 url 参考,然后使用拦截器等等,来处理请求。
const nextTick = () => new Promise(resolve => setTimeout(resolve, 1000 / 30));
// 也就是 33.333 ms 来处理相关的数据。

enter() {
        const { duration, name } = this.data;
        const classNames = getClassNames(name);
        const currentDuration = isObj(duration) ? duration.enter : duration;

        this.status = 'enter';

        Promise.resolve()
          .then(nextTick)
          .then(() => {
            this.checkStatus('enter');

            this.setData({
              inited: true,
              display: true,
              classes: classNames.enter,
              currentDuration
            });

          })
          .then(nextTick)
          .then(() => {
            this.checkStatus('enter');

            this.setData({
              classes: classNames['enter-to']
            });
          })
          .catch(() => {});
      },

我们如何切换 class 来达到过渡的效果

我们定义四种class, 类似于简化版 Vue 的 transition 系统,这里学习了也能更好的理解 Vue 关于 transition 的部分

  • enter 系
  • enter-to 系
  • leave - 系
  • leave-to -系

enter、leave-to 分别是 刚进入的时候,leave-to 最后离开的时候。

enter-to、leave-to 分别是激活、失活的状态

那我们进厂动画和出厂动画,如何描述???

进厂(开始)

class变化值:

  1. van-{name}-enter(变化的属性)

  2. van-{name}-enter-active(属性监听器transition)

进厂(结束)

class变化值:

  1. van-{name}-enter-to(变化的属性)

  2. van-{name}-enter-active(属性监听器transition)

出厂(开始)

  1. van-{name}-leave

  2. van-{name}-leave-active(属性监听器transition)

出厂(开始)

  1. van-{name}-leave-to

  2. van-{name}-leave-active(属性监听器transition)

总结

过渡的时候,监听器属性transition 在一个阶段的不会变的

name = fade 的时候,我们过渡的监听器属性是 opacity属性,监听的opacity的前后转态是 opacity 的转态是 0;

也就是说,我们使用在过渡的时候,监听器transition部分是不变的,然后前后的属性变化,一般也是不变的,符合对称的过渡行为, 对称的过渡进出。

在 vant 内部提供了两种过渡形式

  1. fade形式的
  2. slide形式的

fade 形式的是 opacity(注意 opacity 的默认值是 1,所以可以省略) 的过渡变化 slide形式的是 translate3d 形式的变化,使用的是百分比的形式,百分比是相对自己形式。

被置空的变化属性

  • van-${name}-enter-to
  • van-${name}-leave

还有一个要点的是:样式置空,就是 opacity 变化的之后写了一个没有实际内容的class,使得样式变了样式默认值,transition 属性监听到变化的时候,产生过渡。van-{name}-enter-to 就是一个置空,使得 transition 监听到原来的属性使用了默认的值,此时发生过渡变化。同理 van-${name}-leave 也是一个空(或者默认属性),transition 属性的变化的时候,发生过渡。

参考

  1. vant-weapp vant-weapp@0.5.20: https://github.com/youzan/vant-weapp/tree/dev/packages/transition