vue轮播组件实现$children和$parent 附带好用的gif录制工具


Posted in Javascript onSeptember 26, 2019

1、先提前预祝大家国庆节玩的愉快,我国庆要见家长去了(忐忑)

2、忍不住想要为小米正名,虽然我是米粉但是我是理智粉。

24号不是mix alpha发布会啊,看了真滴是惊艳(现场直接有人喊“ 牛逼 ”,看过好多发布会,就没有看到这样直接喊出来“牛逼”的)。不知道大家还记不记得13年那会吹苹果的时候的一块ppt手机(其实是媒体做的图),但是现在小米做出来了,甚至更好。但是我最近在uc上面那真是到处黑。以前我不相信水军说法,现在信了。如果关注小米mix alpha新闻的在uc下面经常能看到一个叫“决胜千里”的人,每次都是千篇一律的复制黏贴黑。

我想说,没买过没资格。就像写代码,没写过别说懂。写了你才知道这里面有哪些细节和关键因素。

写这个组件起因

记得就这两天有掘友发一个沸点说找女票千万别找同行,好了,曾经我是erp软件实施,现在转前端。女票也是前端。然后她发我一个链接(打不开看gif图):http://ipark.jsboon.com/static/dashboard/yjw/yjw.html

这个链接的最右侧有一个轮播的效果。说起来这整个页面是不咋的,不过里面涉及的东西都比较复杂。 附带gif录制工具:http://www.zdfans.com/html/1754.html

回到刚才说的,女票,对女票。不懂问我,就像之前评论的,干脆让我写得了。这下好了报应来了。(说起来真是无语,她比我早干一年,结果还不如我写了1年前端)

说起来我还没写过这种轮播组件,但是之前去看过源码,并且了解过。如果是写死的那种确实比较简单。但是我们今天用vue封装一个组件。

一、知识点涉及

1、vue组件化开发

2、vue组件嵌套组,就是两个组件相互耦合,然后必须配合使用的那种。参考elementUI里面的表单组件(分为from组件,item组件)或者轮播组件。

vue的 $children和 $parent

3、css动画和形变

二、开始写组件

1、先写你的框,主组件

这个是容器,负责组件定位和组件的整体运作的

html部分

<div
 @mouseenter.stop="handleMouseEnter"
 @mouseleave.stop="handleMouseLeave"
 class="dht-swiper-side"
 :style="{ zIndex: zIndex }"
>
 <slot></slot>
</div>

主要两个鼠标事件: mouseenter和 mouseleave

第一个就是鼠标在元素上负责停止定时器,第二个就是鼠标离开重启定时器

对应的props和监听

props: {
 // 时间间隔
 interval: {
  type: Number,
  default: 8000
 },
 //是否自动播放
 autoplay: {
  type: Boolean,
  default: true
 },
 zIndex: {
  type: Number,
  default: 2000
 },
 // x轴变化
 axisx: {
  type: Number,
  default: 1000
 }
},
watch: {
 autoplay(val) {
  val ? this.startTimer() : this.stopTimer();
 }
},
data() {
 return {
  // 计时器
  timer: "",
  //子元素
  items: [],
  // 当前显示的元素
  active: 0
 };
},

看看就好,没啥多说的,我感觉挺清晰的

2、写你的子组件

这里必须跳跃一下,为什么呢?

因为:主组件主要负责动画运作和容器的作用。定义好你要的参数之后,其实主组件你直接看代码是不不符合编写逻辑的

有了主组件之后,我需要有子元素才能动起来,所以先把子元素加载进来

html部分

<div class="dht-swiper-side-item" :style="itemStyle">
 <slot></slot>
</div>

js核心部分

created() {
 //元素创建和需要更新父元素属性
 this.$parent && this.$parent.updateItems();
},
beforeMount() {},
mounted() {},
destroyed() {
 //元素销毁和需要更新父元素属性
 this.$parent && this.$parent.updateItems();
},

这里主要是创建元素的时候需要把元素加入主组件的items中,销毁的时候同样进行更新

主组件的更新代码

// 更新元素
updateItems() {
 this.items = this.$children.filter(
  // 更新元素需要确认为指定的子元素
  child => child.$options.name === "dhtSwiperSideItem"
 );
},

css核心部分

css部分主要是定义动画效果,和基础css,主要是看动画部分

.dht-swiper-side-item {
 position: absolute;
 transition: all 1s ease;
 transform: translateX(1000px);
 // 抖动动画
 @keyframes mymove {
  0% {
   left: 0;
  }
  50% {
   left: 15px;
  }
  100% {
   left: 0;
  }
 }
}

3、一般弹窗动画之类的编写原理讲解

1、不能用display:none,因为那样元素是直接显示出来的,动画是无法有的。

2、举例:下方弹窗划出

其实在写这些弹窗的时候元素已经在页面上面加载好了,只是被我们隐藏到显示器之外了。

所以我们要做的是在点击显示的时候把元素位移回来

3、所以其实页面上基本的动画都是先放在你看不到的地方,然后再通过 transform

形变css给移动回来的。我这次的组件也是一样的。

4、主组件操作

1、回顾一下,刚才我们先写了主组件,主组件加载子组件,子组件会调用主组件函数,让主组件去更新自己的items,提前存好。方便使用

2、既然我们主组件拿到了子组件了,那么就可以直接操作子组件进行操作,其实核心原理在于主组件之间操作子组件。(我看了elementUI源码的走马灯部分,写的比我复杂。)

3、定时器部分

//开始计时器
startTimer() {
 //预先执行一次,保证不会出现第一次运行延迟双倍实际
 this.play();
 // 拦截处理
 if (this.interval <= 0 || !this.autoplay || this.timer) return;
 this.timer = setInterval(() => {
  this.play();
 }, this.interval);
},

这块其实没啥,除了预先的拦截剩下的就是启动定时器,然后运行动画播放函数

4、核心播放函数部分

//播放实际运行函数
play() {
 let len = this.items.length - 1;
 let now = this.active > len ? 0 : this.active;
 let old = this.active - 1 < 0 ? 0 : this.active - 1;
 //console.log("当前", now, "老的", old);
 //关闭老元素
 this.items[old].show = false;
 this.items[old].itemStyle = {
  transition: "all 1.5s ease",
  transform: `translateX(${this.axisx}px)`
 };
 //显示新元素
 this.items[now].show = true;
 this.items[now].itemStyle = {
  transition: "all 1.5s ease",
  transform: "translateX(0)",
  animation: "mymove 1.5s 2"
 };
 //记录数据
 this.active = now + 1;
}

这个其实很简单,每次运行的时候处理一下数据,拿到当前要运行的子元素id和老的元素,当前的展示,老的移动回去。最后记录一下新的id

这里有一个坑点:就是animation部分,记得运行2次,不然只是一次会导致下面的元素看不到抖动效果。原因是在移动的时候就抖动完毕了。

5、主组件css部分

.dht-swiper-side {
 position: absolute;
 z-index: 2000;
 right: 0;
 display: flex;
 flex-flow: row;
 width: 100%;
}

三、组件文档

dht-swiper-side 侧边轮播组件 interval Number 5000 时间间隔,默认5秒转换一次 必须给该组件指定宽度,否则无法正常显示。 内部子元素展示做最侧位置主要由该组件的宽度定义
autoplay Boolean TRUE 是否自动播放,咱不支持false
zIndex Number 2000 组件层级
axisx Number 1000 隐藏的子元素位置,px单位,默认1000。当内部元素宽度过大时可以调节该参数
dht-swiper-side-item dht-swiper-side dht-swiper-side的子组件,用于存放内容

四、个人组件效果展示

<dht-swiper-side class="main">
 <dht-swiper-side-item>
  <div class="item">我是组件1</div>
 </dht-swiper-side-item>
 <dht-swiper-side-item>
  <div class="item">我是组件2</div>
 </dht-swiper-side-item>
 <dht-swiper-side-item>
  <div class="item">我是组件3</div>
 </dht-swiper-side-item>
 <dht-swiper-side-item>
  <div class="item">我是组件4</div>
 </dht-swiper-side-item>
</dht-swiper-side>

.main {
 width: 500px;
 .item {
  width: 100px;
  height: 100px;
  background: #009966;
  border: #409eff 1px solid;
  text-align: center;
  line-height: 100px;
 }
}

主组件全部代码

<template>
 <div
  @mouseenter.stop="handleMouseEnter"
  @mouseleave.stop="handleMouseLeave"
  class="dht-swiper-side"
  :style="{ zIndex: zIndex }"
 >
  <slot></slot>
 </div>
</template>

<script>
export default {
 name: "dhtSwiperSide",
 props: {
  // 时间间隔
  interval: {
   type: Number,
   default: 8000
  },
  //是否自动播放
  autoplay: {
   type: Boolean,
   default: true
  },
  zIndex: {
   type: Number,
   default: 2000
  },
  // x轴变化
  axisx: {
   type: Number,
   default: 1000
  }
 },
 watch: {
  autoplay(val) {
   val ? this.startTimer() : this.stopTimer();
  }
 },
 data() {
  return {
   // 计时器
   timer: "",
   //子元素
   items: [],
   // 当前显示的元素
   active: 0
  };
 },
 beforeCreate() {},
 created() {
  this.$nextTick(() => {
   this.updateItems();
   this.startTimer();
   this.$children[0].show = true;
  });
 },
 beforeMount() {},
 mounted() {},
 destroyed() {
  clearInterval(this.timer);
 },
 methods: {
  handleMouseEnter() {
   this.stopTimer();
  },

  handleMouseLeave() {
   this.startTimer();
  },
  //开始计时器
  startTimer() {
   //预先执行一次,保证不会出现第一次运行延迟双倍实际
   this.play();
   // 拦截处理
   if (this.interval <= 0 || !this.autoplay || this.timer) return;
   this.timer = setInterval(() => {
    this.play();
   }, this.interval);
  },
  // 停止计时器
  stopTimer() {
   clearInterval(this.timer);
  },
  // 更新元素
  updateItems() {
   this.items = this.$children.filter(
    // 更新元素需要确认为指定的子元素
    child => child.$options.name === "dhtSwiperSideItem"
   );
  },
  //播放实际运行函数
  play() {
   let len = this.items.length - 1;
   let now = this.active > len ? 0 : this.active;
   let old = this.active - 1 < 0 ? 0 : this.active - 1;
   //console.log("当前", now, "老的", old);
   //关闭老元素
   this.items[old].show = false;
   this.items[old].itemStyle = {
    transition: "all 1.5s ease",
    transform: `translateX(${this.axisx}px)`
   };
   //显示新元素
   this.items[now].show = true;
   this.items[now].itemStyle = {
    transition: "all 1.5s ease",
    transform: "translateX(0)",
    animation: "mymove 1.5s 2"
   };
   //记录数据
   this.active = now + 1;
  }
 }
};
</script>

<style lang="scss">
.dht-swiper-side {
 position: absolute;
 z-index: 2000;
 right: 0;
 display: flex;
 flex-flow: row;
 width: 100%;
}
</style>

子组件全部代码

<template>
 <div class="dht-swiper-side-item" :style="itemStyle">
  <slot></slot>
 </div>
</template>

<script>
export default {
 name: "dhtSwiperSideItem",
 data() {
  return {
   show: false,
   defaultStyle: {},
   itemStyle: {}
  };
 },
 watch: {},
 beforeCreate() {},
 created() {
  //元素创建和需要更新父元素属性
  this.$parent && this.$parent.updateItems();
 },
 beforeMount() {},
 mounted() {},
 destroyed() {
  //元素销毁和需要更新父元素属性
  this.$parent && this.$parent.updateItems();
 },
 methods: {}
};
</script>

<style lang="scss">
.dht-swiper-side-item {
 position: absolute;
 transition: all 1s ease;
 transform: translateX(1000px);
 // 抖动动画
 @keyframes mymove {
  0% {
   left: 0;
  }
  50% {
   left: 15px;
  }
  100% {
   left: 0;
  }
 }
}
</style>

致谢

感谢elementUI开源代码,本组件有部分是直接拷贝的elementUI的Carousel的代码。

总结

以上所述是小编给大家介绍的vue轮播组件实现$children和$parent 附带好用的gif录制工具,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对三水点靠木网站的支持!
如果你觉得本文对你有帮助,欢迎转载,烦请注明出处,谢谢!

Javascript 相关文章推荐
在IE下:float属性会影响offsetTop的取值
Dec 22 Javascript
使用自定义setTimeout和setInterval使之可以传递参数和对象参数
Apr 24 Javascript
boxy基于jquery的弹出层对话框插件扩展应用 弹出层选择器
Nov 21 Javascript
JS定义回车事件(实现代码)
Jul 08 Javascript
JavaScript判断浏览器类型的方法
Feb 10 Javascript
简述AngularJS的控制器的使用
Jun 16 Javascript
浅谈Sublime Text 3运行JavaScript控制台
Jun 06 Javascript
AngularJS在IE下取数据总是缓存问题的解决方法
Aug 05 Javascript
JavaScript使用forEach()与jQuery使用each遍历数组时return false 的区别
Aug 26 Javascript
Bootstrap3下拉菜单的实现
Feb 22 Javascript
JQuery事件委托原理与用法实例分析
May 13 jQuery
JavaScript实现多球运动效果
Sep 07 Javascript
小程序调用微信支付的方法
Sep 26 #Javascript
细说webpack6 Babel的使用详解
Sep 26 #Javascript
微信小程序实现拖拽功能
Sep 26 #Javascript
vue用BMap百度地图实现即时搜索功能
Sep 26 #Javascript
layui.tree组件的使用以及搜索节点功能的实现
Sep 26 #Javascript
微信小程序点击列表跳转到对应详情页过程解析
Sep 26 #Javascript
vue+element tabs选项卡分页效果
Jun 29 #Javascript
You might like
收音机史话 - 1960年代前后的DIY
2021/03/02 无线电
php 文件状态缓存带来的问题
2008/12/14 PHP
使用URL传输SESSION信息
2015/07/14 PHP
PHP设计模式之迭代器模式
2016/06/17 PHP
PHPExcel导出2003和2007的excel文档功能示例
2017/01/04 PHP
用jquery生成二级菜单的实例代码
2013/06/24 Javascript
JavaScript改变HTML元素的样式改变CSS及元素属性
2013/11/12 Javascript
javascript+HTML5的canvas实现七夕情人节3D玫瑰花效果代码
2015/08/04 Javascript
AngularJS基础 ng-keyup 指令简单示例
2016/08/02 Javascript
Ionic默认的Tabs模板使用实例
2016/08/29 Javascript
ES6下React组件的写法示例代码
2017/05/04 Javascript
JavaScript实现简单图片轮播效果
2017/08/21 Javascript
zTree异步加载展开第一级节点的实现方法
2017/09/05 Javascript
详解使用PM2管理nodejs进程
2017/10/24 NodeJs
vue-i18n结合Element-ui的配置方法
2019/05/20 Javascript
layui添加动态菜单与选项卡 AJAX请求的例子
2019/09/25 Javascript
js实现轮播图特效
2020/05/28 Javascript
vue-cli3项目配置eslint代码规范的完整步骤
2020/09/10 Javascript
python 中的int()函数怎么用
2017/10/17 Python
使用apidoc管理RESTful风格Flask项目接口文档方法
2018/02/07 Python
解决python3 HTMLTestRunner测试报告中文乱码的问题
2018/12/17 Python
python实现AES加密与解密
2019/03/28 Python
浅谈django2.0 ForeignKey参数的变化
2019/08/06 Python
详解django实现自定义manage命令的扩展
2019/08/13 Python
Pycharm 安装 idea VIM插件的图文教程详解
2020/02/21 Python
python如何求100以内的素数
2020/05/27 Python
Python 串口通信的实现
2020/09/29 Python
Django项目在pycharm新建的步骤方法
2021/03/02 Python
自荐书格式
2013/12/01 职场文书
通信工程专业毕业生推荐信
2013/12/25 职场文书
机械设计及其自动化专业求职信
2014/06/09 职场文书
节能环保家庭事迹材料
2014/08/27 职场文书
五四演讲稿范文
2014/09/03 职场文书
2014年纠风工作总结
2014/12/08 职场文书
浅谈vue2的$refs在vue3组合式API中的替代方法
2021/04/18 Vue.js
python中的class_static的@classmethod的巧妙用法
2021/06/22 Python