前言:之前赶项目,都是直接用框架,对于touch事件是模拟两可,趁着有心情,用es6写一个原生移动轮播插件。
用了es6的新特性,确实挺爽的,说到es6,就不得不说到babel,博主已经码好了,直接用就好了。下面简单说一下如何“搭环境”。
用Gulp、Babel等为浏览器构建ES6环境
[注意:该环节默认你电脑已经有node,gulp环境]
- 项目目录下,运行 npm init
- 找到package.json文件,找到dependencies,修改如下
1 "dependencies": { 2 "babel-preset-es2015": "^6.5.0", 3 "gulp-load-plugins": "^1.1.0", 4 "gulp-babel": "^6.1.2", 5 "gulp-plumber": "^1.0.1", 6 "gulp-rename": "^1.2.2", 7 "gulp": "^3.9.1", 8 "gulp-jshint": "^2.0.0", 9 "gulp-concat": "^2.6.0", 10 "gulp-uglify": "^1.4.1", 11 "gulp-util": "^3.0.1" 12 }
- 命令行 运行npm install [该命令会安装package里面所有的依赖包,所以开发项目时,最好使用npm install --save '' ,方便其他合作者安装项目所需要的包]
- 在根目录下 新建gulpfile.js
1 const gulp = require('gulp'), 2 concat = require('gulp-concat'), 3 rename = require('gulp-rename'), 4 jshint = require('gulp-jshint'), 5 uglify = require('gulp-uglify'); 6 7 8 // Load plugins 9 const $ = require('gulp-load-plugins')(); 10 11 /* es6 */ 12 gulp.task('es6', function () { 13 return gulp.src('src/js/*.js') 14 .pipe($.plumber()) 15 .pipe($.babel({ 16 presets: ['es2015'] 17 })) 18 .pipe(gulp.dest('dist/js/')); 19 }); 20 21 gulp.task('watch', ['es6'], function () { 22 gulp.watch(['src/js/*.js'], ['es6']); 23 }); 24 25 // 默认任务 26 gulp.task('default', function () { 27 gulp.run('watch'); 28 });
[注意:上面的目录需要 更改为实际项目 的目录]
- 命令行 运行 gulp 编译 即可。
项目整体架构
1 class Slider { 2 /*构造函数*/ 3 constructor(opts) { 4 this.wrap = opts.dom; 5 this.list = opts.list; 6 this.init(); 7 } 8 /*初始化*/ 9 init() {} 10 /*绘制dom*/ 11 renderDOM() {} 12 goIndex(n) {} 13 bindDOM() {} 14 }
调用方式
1 var list = [{ 2 img: "src/imgs/1.jpg" 3 }, { 4 img: "src/imgs/2.jpg" 5 }, { 6 img: "src/imgs/3.jpg" 7 }, { 8 img: "src/imgs/4.jpg" 9 }, { 10 img: "src/imgs/5.jpg", 11 }, { 12 img: "src/imgs/6.jpg", 13 }, { 14 img: "src/imgs/7.jpg", 15 }]; 16 17 var x = new Slider({ 18 'dom': document.getElementById('canvas'), 19 'list': list 20 });
项目实现原理
- 绘制dom结构
1 renderDOM() { 2 let wrap = this.wrap, 3 data = this.list, 4 i = 0, 5 html = []; 6 this.outer = document.createElement('ul'); 7 8 for (let val of data) { 9 if (val) { 10 html.push(`<li style="transform: translate3d(${i * this.scaleW}px ,0,0)"> 11 <img src="${val['img']}" alt="img" width="${window.innerWidth}px" height="180px" /> 12 </li>`); 13 } 14 i++; 15 } 16 this.outer.innerHTML = html.join(''); 17 wrap.appendChild(this.outer); 18 }
- 根据手指移动方向 判断向左(右)移动
1 /*手指开始的事件*/ 2 let startHandle = (evt)=> {} 3 /*手指移动的处理事件*/ 4 let moveHandler = (evt)=> {} 5 /*手指抬起的事件*/ 6 let endHandler = (evt)=> {}
1 let endHandler = (evt)=> { 2 evt.preventDefault(); 3 let boundary = scaleW / 6, 4 endTime = new Date() * 1; 5 /* 6 * 手指滑动距离超过 boundary 翻页 7 * 当手指移动时间超过300ms的时候,按位移算 8 * */ 9 if (endTime - this.startTime > 300) { 10 if (this.offsetX >= boundary) {/*进入上一页*/ 11 this.goIndex('-1'); 12 } else if (this.offsetX < 0 && this.offsetX < -boundary) {/*进入下一页*/ 13 this.goIndex('+1'); 14 } else {/*留在本页*/ 15 this.goIndex('0'); 16 } 17 } else { 18 /*快速滑动的时候,较少滑动的间隔,即可滑动*/ 19 if (this.offsetX > 50) { 20 this.goIndex('-1'); 21 } else if (this.offsetX < -50) { 22 this.goIndex('+1'); 23 } else { 24 this.goIndex('0'); 25 } 26 } 27 };
绑定事件
1 outer.addEventListener('touchstart', startHandle); 2 outer.addEventListener('touchmove', moveHandler); 3 outer.addEventListener('touchend', endHandler);
使用es6开发有什么显著优势?
- 使用es6新增的类class,不需要像下面这样的写法去模拟类
1 function Slider(opts) { 2 this.wrap = opts.dom; 3 this.list = opts.list; 4 this.init(); 5 } 6 Slider.prototype = { 7 init: function () {}, 8 renderDOM: function () {}, 9 bindDOM: function () {}, 10 goIndex: function (n) {} 11 }
优点:直观上,es6更容易理解,写法也更为简单。
1.constructor: 构造方法,构造方法里面的this,指向的是该类实例化后的对象。
constructor是一个类必须要有的方法,也是唯一的。如果你没有编写constructor方法,执行的时候也会被加上一个默认的空的constructor方法。
2.类似于java,它也有静态方法,顾名思义,就是不需要实例化就可以直接调用该方法,直接看例子更容易理解
1 class Animal { 2 //构造方法 3 constructor(name){ 4 this.name = name; 5 } 6 //自定义一个静态方法 7 static friends(a1,a2){ 8 console.log(`${a1} and ${a2} are friends`); 9 } 10 sayHello(){ 11 console.log('hello'); 12 } 13 } 14 //调用静态方法 15 Animal.friends('dog','cat');//dog and cat are friends 16 Animal.sayHello(); //出错 17 var animal = new Animal('dog'); 18 animal.sayHello(); //hello
- 该例子中还使用了es6的另一个特性——模版字符串
上面的例子,如果用之前的实现方式,就要
1 (a1 + 'and' + a2 + 'are friends');
注意:
1.在``中,换行也会被保存,[``是不是有点像markdown 哈哈 ]如果不想要换行,使用trim
方法消除它,同样的,举个例子
1 $('#list').html(` 2 <ul> 3 <li>first</li> 4 <li>second</li> 5 </ul> 6 `.trim());
2.嵌入变量,将变量名写在${}
之中,{}中可以进行运算,还可以调用函数
- 函数 默认传参
传统实现方式:
1 function person(n,a){ 2 var name = n || 'Zhangsan'; 3 var age = a || 25; 4 }
缺点:參数对应的布尔值不能false(比如:数字0,空字符串等转换成布尔值就是false)
新新方式:
1 function person(name = 'Zhangsan',age = 25){ 2 console.log(name,age); 3 } 4 5 person();//结果:Zhangsan 25 6 person('Lisi',18);//结果:Lisi 18
注意:设定默认值的参数一定要放在最后,不然会出错
- 箭头函数
1 //传统实现方法 2 var obj = { 3 x:100, 4 show(){ //对象方法的简单写法 5 setTimeout( 6 function(){console.log(this.x);}, 7 500 8 ); 9 } 10 }; 11 obj.show();//打印结果:undefined 12 //es6箭头函数 13 var obj = { 14 x:100, 15 show(){ 16 setTimeout( 17 //不同处:箭头函数 18 () => { console.log(this.x)}, 19 500 20 ); 21 } 22 }; 23 obj.show();//打印结果:100
仔细看看上面的例子,为什么第一个输出的是undefined?
问题出在了this上,当代码执行到了setTimeout( )的时候,此时的this已经变成了window对象(setTimeout( )是window对象的方法),已经不再是obj对象了,所以我们用this.x获取的时候,获取的不是obj.x的值,而是window.x的值,再加上window上没有定义属性x,所以得到的结果就是:undefined。
不懂this指向的可以看看我的另一篇博客:http://www.cnblogs.com/beidan/p/5371275.html
再对比箭头函数
同样的一段代码,唯一的不用就是setTimeout中,原本的匿名函数用箭头函数代替了。神奇的是因为
let,const,for of,继承,rest参数,模块,解构,promise…………
还有哪些属性比较常使用,请告诉我,谢谢~~~
github地址:https://github.com/beidan/slide
如果这篇博文对你有帮助,请给我star或者fork,谢谢~