shopList - mingliao/nuxt_elm GitHub Wiki

摘要

组件封装好比函数封装,哪些属性可以暴露,那些需要在内部使用,都需要思考,组件便于重复利用。

  1. 入场动画
  2. 触底滚动加载数据
  3. Number
  4. 待办事项

入场动画

入场动画代码主要在这里

<transition name="loading">
      <loading v-show="showLoading"></loading>
    </transition>

transition参考进入/离开 & 列表过渡

在文档中介绍了

当插入或删除包含在 transition 组件中的元素时,Vue 将会做以下处理

说明,transition是对dom,创建或者删除的时候进行样式操作的。

例如

<transition name="fade">
    <p v-if="show">hello</p>
  </transition>
<style>
.fade-enter-active, .fade-leave-active {
  transition: opacity .5s;
}
.fade-enter, .fade-leave-to /* .fade-leave-active below version 2.1.8 */ {
  opacity: 0;
}
</style>

在文档中有介绍 过渡的类名 这里比如:

v-enter:定义进入过渡的开始状态。在元素被插入时生效,在下一个帧移除。

这是说在dom插入的时候应用样式,如果本来没有dom元素,如上面show=false 元素不显示, 把show=true,就会应用样式了。这个时候应用的是从v-enter--》v-enter-to的样式了。 这里设置的是

.fade-enter/* .fade-leave-active below version 2.1.8 */ {
  opacity: 0;
}

所以从.fade-enter-->.fade-enter-to opacity:0---->opacity:1

自己根据文档写的demo(其实是抄的) 戳这里codepen 可以f12 看下样式变化。

shoplist的 动画封装在loading组件中:

动画运行

  • mounted钩子函数运行,属性positionY一直变化,背景样式也一直变化,使用雪碧图icon_loading.png来显示动画场景中的图片
<div class="load_img" :style="{backgroundPositionY: -(positionY%7)*2.5 + 'rem'}">
	    </div>
....
 mounted () {
        this.timer = setInterval(() => {
          //一直循环运行
          this.positionY++
        }, 600)
      },
....
 	@keyframes load{
		0%   {transform: translateY(0px);}
		50%  {transform: translateY(-50px);}
		100% {transform: translateY(0px);}
	}
 .load_img{
    	@include wh(100%, 100%);
    	background: url('~/assets/images/icon_loading.png') no-repeat 0 0; 
    	background-size: 2.5rem auto;
    	transform: translateY(0px);
    	animation: load .6s infinite ease-in-out; //使用load动画
    	position: relative;
    	z-index: 11;
    }
  • 动画下面的椭圆形背景随之变化
<svg class="load_ellipse" xmlns="http://www.w3.org/2000/svg" version="1.1">
			<ellipse cx="26" cy="10" rx="26" ry="10" style="fill:#ddd;stroke:none;"></ellipse>
</svg>
....
	@keyframes ellipse{
		0%   {transform: scale(1);}
		50%  {transform: scale(0.3);}
		100% {transform: scale(1);}
	}
	.load_ellipse{
		position: absolute;
		@include wh(2.6rem, 2rem);
		top: 2.2rem;
        left: 0.2rem;
		z-index: 10;
		animation: ellipse .6s infinite ease-in-out;
	}
  • beforeDestroy beforeDestroy在组件被卸载,如页面跳转之后,就会被调用,清理掉timer,防止内存占用。
 beforeDestroy () {
        console.log('beforeDestroy in ')
        clearInterval(this.timer)
      }

触底滚动加载数据

这里使用到指令:

有的情况下,你仍然需要对普通 DOM 元素进行底层操作,这时候就会用到自定义指令。

触底加载数据作为一个指令来处理在mixin.js里面

export const loadMore = {
  directives: {
    'load-more': {
      bind: (el, binding) => {
        let windowHeight = window.screen.height
        let height
        let setTop
        let paddingBottom
        let marginBottom
        let requestFram
        let oldScrollTop
        let scrollEl
        let heightEl
        let scrollType = el.attributes.type && el.attributes.type.value // 取得元素自定义属性
        let scrollReduce = 2
        if (scrollType === 2) {
          scrollEl = el
          heightEl = el.children[0]
        } else {
          scrollEl = document.body
          heightEl = el
        }

        el.addEventListener('touchstart', () => {
          height = heightEl.clientHeight
          setTop = el.offsetTop
          paddingBottom = getStyle(el, 'paddingBottom')
          marginBottom = getStyle(el, 'marginBottom')
        }, false)

        el.addEventListener('touchmove', () => {
          loadMore()
        }, false)

        el.addEventListener('touchend', () => {
          oldScrollTop = scrollEl.scrollTop
          moveEnd()
        }, false)

        const moveEnd = () => {
          requestFram = requestAnimationFrame(() => {
            if (scrollEl.scrollTop !== oldScrollTop) {
              oldScrollTop = scrollEl.scrollTop
              moveEnd()
            } else {
              cancelAnimationFrame(requestFram)
              height = heightEl.clientHeight
              loadMore()
            }
          })
        }

        const loadMore = () => {
          if (scrollEl.scrollTop + windowHeight >= height + setTop + paddingBottom + marginBottom - scrollReduce) {
            binding.value()// 这里就是v-load-more="xx",这里的xx就是对外暴露的接口了,可以调用外部的命令
          }
        }
      }
    }
  }
}

在shopList中,代码使用mixins配置项,所以,这个组件就作为配置项(局部指令)融合如shopplist中了。注意,这里mixins.js是可以不是一个vue文件,可以只是一个模块化文件。 在shoplist 就可以使用v-xxx来使用指令了。

<ul v-load-more="loaderMore" v-if="shopListArr.length" type="1">
....
</ul>

Number

<span v-if="Number(item.distance)"> 这里Number() 可以参考MDN Number是一个全局对象,类似java的基本类型的包装类。 Number也有一些全局方法,比如Number.NaN() 类推也有Boolean Boolean有助于条件判断。

待办事项

  • 入场动画
    • 基础用法
  • 触底加载数据
⚠️ **GitHub.com Fallback** ⚠️