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 相关文章推荐
jquery中dom操作和事件的实例学习 下拉框应用
Dec 01 Javascript
基于jquery的放大镜效果
May 30 Javascript
jQuery实现冻结表格行和列
Apr 29 Javascript
Javascript中的return作用及javascript return关键字用法详解
Nov 05 Javascript
Node.js实现JS文件合并小工具
Feb 02 Javascript
微信小程序 聊天室简单实现
Apr 19 Javascript
JavaScript动态绑定详解
Sep 14 Javascript
原生JavaScript实现remove()和recover()功能示例
Jul 24 Javascript
node.js中ws模块创建服务端和客户端,网页WebSocket客户端
Mar 06 Javascript
使用VScode 插件debugger for chrome 调试react源码的方法
Sep 13 Javascript
redux处理异步action解决方案
Mar 22 Javascript
Vue检测屏幕变化来改变不同的charts样式实例
Oct 26 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
php数组函数序列之krsort()- 对数组的元素键名进行降序排序,保持索引关系
2011/11/02 PHP
php中用socket模拟http中post或者get提交数据的示例代码
2013/08/08 PHP
PHP函数preg_match_all正则表达式的基本使用详细解析
2013/08/31 PHP
php检测数组长度函数sizeof与count用法
2014/11/17 PHP
zen_cart实现支付前生成订单的方法
2016/05/06 PHP
ThinkPHP使用Ueditor的方法详解
2016/05/20 PHP
js中的hasOwnProperty和isPrototypeOf方法使用实例
2014/06/06 Javascript
基于jQuery实现Div窗口震动特效代码-代码简单
2015/08/28 Javascript
javascript中的作用域和闭包详解
2016/01/13 Javascript
jQuery中的each()详细介绍(推荐)
2016/05/25 Javascript
详解jquery easyui之datagrid使用参考
2016/12/05 Javascript
jQuery内存泄露解决办法
2016/12/13 Javascript
爬虫利器Puppeteer实战
2019/01/09 Javascript
layui 实现table翻页滚动条位置保持不变的例子
2019/09/05 Javascript
layui实现checkbox的目录树tree的例子
2019/09/12 Javascript
JS动态显示倒计时效果
2019/12/12 Javascript
谈一谈vue请求数据放在created好还是mounted里好
2020/07/27 Javascript
Vue+Element UI 树形控件整合下拉功能菜单(tree + dropdown +input)
2020/08/28 Javascript
python异步任务队列示例
2014/04/01 Python
使用Python的urllib2模块处理url和图片的技巧两则
2016/02/18 Python
Python做文本按行去重的实现方法
2016/10/19 Python
Python使用matplotlib绘制三维参数曲线操作示例
2019/09/10 Python
python代码实现TSNE降维数据可视化教程
2020/02/28 Python
Python3 assert断言实现原理解析
2020/03/02 Python
python实现图片转换成素描和漫画格式
2020/08/19 Python
PyTorch 导数应用的使用教程
2020/08/31 Python
python解压zip包中文乱码解决方法
2020/11/27 Python
俄罗斯在线水暖商店:Perfecto.ru
2019/10/25 全球购物
办理信用卡工作证明
2014/01/11 职场文书
关于赌博的检讨书
2014/01/24 职场文书
初一家长会邀请函
2014/01/31 职场文书
感恩之星事迹材料
2014/05/03 职场文书
2014年业务工作总结
2014/11/17 职场文书
先进教育工作者事迹材料
2014/12/23 职场文书
校园环境卫生倡议书
2015/04/29 职场文书
Win11黑色桌面背景怎么办?Win11黑色壁纸解决方法汇总
2022/04/05 数码科技