├── .babelrc
├── .eslintrc
├── .gitignore
├── CHANGELOG.md
├── LICENSE
├── README.md
├── examples-dist
├── carousel.9540da0e7b385842da32.bundle.js
├── carousel.9540da0e7b385842da32.bundle.js.map
├── carousel.html
├── css
│ ├── carousel.d7c89e08b5abfb774f54.css
│ ├── carousel.d7c89e08b5abfb774f54.css.map
│ ├── header-footer.aa697a21f7857d4c1560.css
│ ├── header-footer.aa697a21f7857d4c1560.css.map
│ ├── index.36fbdaffa0fdd50aa664.css
│ ├── index.36fbdaffa0fdd50aa664.css.map
│ ├── pull-carousel.168d7ef0a8deaade6c73.css
│ ├── pull-carousel.168d7ef0a8deaade6c73.css.map
│ ├── pull-carousel2.d50988f2dea6085f1002.css
│ ├── pull-carousel2.d50988f2dea6085f1002.css.map
│ ├── pull.1cdce4fcd519ccb16612.css
│ ├── pull.1cdce4fcd519ccb16612.css.map
│ ├── simple.cd5bd1d575b7cc335111.css
│ ├── simple.cd5bd1d575b7cc335111.css.map
│ ├── tabs-carousel.65b224ba332c3c8c1bb4.css
│ └── tabs-carousel.65b224ba332c3c8c1bb4.css.map
├── eruda.min.js
├── header-footer.9540da0e7b385842da32.bundle.js
├── header-footer.9540da0e7b385842da32.bundle.js.map
├── header-footer.html
├── index.9540da0e7b385842da32.bundle.js
├── index.9540da0e7b385842da32.bundle.js.map
├── index.html
├── pull-carousel.9540da0e7b385842da32.bundle.js
├── pull-carousel.9540da0e7b385842da32.bundle.js.map
├── pull-carousel.html
├── pull-carousel2.9540da0e7b385842da32.bundle.js
├── pull-carousel2.9540da0e7b385842da32.bundle.js.map
├── pull-carousel2.html
├── pull.9540da0e7b385842da32.bundle.js
├── pull.9540da0e7b385842da32.bundle.js.map
├── pull.html
├── simple.9540da0e7b385842da32.bundle.js
├── simple.9540da0e7b385842da32.bundle.js.map
├── simple.html
├── tabs-carousel.9540da0e7b385842da32.bundle.js
├── tabs-carousel.9540da0e7b385842da32.bundle.js.map
└── tabs-carousel.html
├── examples
├── carousel.js
├── eruda.min.js
├── header-footer.js
├── index.js
├── pull-carousel.js
├── pull-carousel2.js
├── pull.js
├── sass
│ └── example.scss
├── simple.js
├── tabs-carousel.js
└── templates
│ └── layout.html
├── gulp
├── example.babel.js
├── publish.babel.js
└── scss.babel.js
├── gulpfile.babel.js
├── js
├── AlloyTouch.js
├── ReactAlloyTouch.js
├── ReactCarousel.js
├── ReactPull.js
├── ReactSwiper.js
└── index.js
├── package-lock.json
├── package.json
├── publish
└── package.json
├── sass
├── carousel.scss
├── index.scss
└── pull.scss
├── webpack.config.babel.js
├── webpack.config.example.babel.js
└── webpack.config.example.dist.babel.js
/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": [
3 | ["env", {
4 | "targets": {
5 | "browsers": ["last 2 versions"]
6 | }
7 | }],
8 | "react"
9 | ],
10 | "plugins": [
11 | "transform-object-rest-spread", // 支持对象 rest 预发
12 | "transform-class-properties" //解析类属性,静态和实例的属性
13 | ]
14 | }
15 |
--------------------------------------------------------------------------------
/.eslintrc:
--------------------------------------------------------------------------------
1 | /**
2 | "off" or 0 - turn the rule off
3 | "warn" or 1 - turn the rule on as a warning (doesn’t affect exit code)
4 | "error" or 2 - turn the rule on as an error (exit code is 1 when triggered)
5 | **/
6 | {
7 | "rules": {
8 | // Possible Errors
9 | "no-await-in-loop": 2, // Disallow await inside of loops
10 | "no-compare-neg-zero": 2, // 不要出现负零,即 -0
11 | "no-cond-assign": 2, // 条件语句中,不应该出现 = ,比如 if (x = 2) { } 是会报错的
12 | "no-console": 0, // 是否允许 console
13 | "no-constant-condition": 2, // 是否允许使用常量式表达式 if (false) { }
14 | "no-control-regex": 2, // 是否允许在正则表达式中使用控制字符
15 | "no-debugger": 2, // 是否允许使用 debugger
16 | "no-dupe-args": 2, // 函数参数是否允许有重复的,如果设置了严格模式,可以不用设置该选项
17 | "no-dupe-keys": 2, // 是否允许对象中有相同的key
18 | "no-duplicate-case": 2, // 检测case语句中,是否有重复的case变量值
19 | "no-empty": 2, // 是否允许空的表达式,if (foo) {}
20 | "no-empty-character-class": 2, // 是否允许空的正则表达式,比如 var foo = /^abc[]/;
21 | /**
22 | 异常时给ex赋值是不允许的
23 | try {
24 | // code
25 | } catch (e) {
26 | e = 12; //error Do not assign to the exception parameter.
27 | }
28 | **/
29 | "no-ex-assign": 2,
30 | "no-extra-boolean-cast": 2, // 在条件语句中不允许使用!! 比如 if (!!foo) { } /*error Redundant double negation in an if statement condition.*/
31 | "no-extra-parens": 0, // 不要使用冗余的括号,比如 a = (b * c);
32 | "no-extra-semi": 2, // 不要使用多余的分号; 比如 var x = 5;;
33 | "no-func-assign": 2, // 不允许给函数重新赋值 function foo() {} foo = bar; /*error 'foo' is a function.*/
34 | "no-inner-declarations": 2, // 不要在函数体或程序块(if或循环)中声明函数
35 | "no-invalid-regexp": 2, // 不允许定义无效的正则表达式
36 | "no-irregular-whitespace": 2, // 不允许使用除空格和制表位意外的空白字符,比如 \u222B
37 | "no-obj-calls": 2, // 不允许调用全局的函数对象,比如 Math 和 JSON var x = Math(); /*error 'Math' is not a function.*/ var y = JSON(); /*error 'JSON' is not a function.*/
38 | "no-prototype-builtins": 0, // 不建议直接使用 Object.prototypes ,而使用 call 来调用,比如 var hasBarProperty = {}.hasOwnProperty.call(foo, "bar");
39 | "no-regex-spaces": 2, // 正则表达式中不允许有空格
40 | "no-sparse-arrays": 2, // 此开关控制是否可以用稀疏数组
41 | "no-template-curly-in-string": 2, // 不允许字符串的模板,比如 "Hello ${name}!" 会报错
42 | "no-unexpected-multiline": 2, // 避免多行的表达式
43 | "no-unreachable": 2, // 避免书写不可达的代码,比如在return后添加新的代码,或抛出异常,中断语句后
44 | "no-unsafe-finally": 2, // 不用在 finally 语句中使用 return 或抛出异常(throw)
45 | "no-unsafe-negation": 2, // 在in 或 instanceof表达式中不要否定变量 if(!a in b) {} 是错误的,应该写成 if(!(a in b)){}
46 | "use-isnan": 2, // 不要用NaN跟变量作比较,而是应该调用 isNaN()
47 | "valid-jsdoc": 0, // 如果我们使用jsdoc[http://usejsdoc.org/]来生成js文档,可以开启该规则来检测注释的正确性
48 | "valid-typeof": 2, // 验证typeof与比较的值,是否为以下几种情况,"undefined", "object", "boolean", "number", "string", and "function"
49 |
50 | // Best Practices
51 | "accessor-pairs": 2, // 定义对象属性时,setter和getter应该成对出现,如果不是成对的,会出现警告信息的
52 | "array-callback-return": 2, // 在数组方法中,回调函数应该加上 return,比如在 array.reduce中
53 | "block-scoped-var": 2, // 在快作用于中不允许使用var来定义变量
54 | "class-methods-use-this": 0, //在 class 定义的方法中,没有使用 this,会认为是不应该的
55 | "complexity": 2, // 判断语句复杂度,关闭该规则
56 | "consistent-return": 0, // 不同的分支返回的类型应该一样
57 | "curly": [2, "multi-line"], // 在循环或判断语句中是否需要加花括号
58 | "default-case": 2, // 在 switch语句中,检测是否有默认分支
59 | "dot-location": [2, "property"], // 在换行时,用来检测对象的点是换行之前还是之后,这里设为放在下一行
60 | "dot-notation": 2, // 对于对象属性应该用点表达式,不应该用[] var x = foo["bar"]; 是错误的,应该 var x = foo.bar; 但 var x = foo[bar]; 是正确的,因为bar是变量
61 | "eqeqeq": [2, "allow-null"], // 使用恒等来比较两个变量
62 | "guard-for-in": 2, // 在 for in 表达式中需要调用 hasOwnProperty 来判断是否为自有的属性
63 | "no-alert": 2, // 不允许用alert语句
64 | "no-caller": 2, // 不允许用 arguments.caller 和 arguments.callee
65 | "no-case-declarations": 2, // 在 case 语句中使用声明式语句时,需要用 {} 括起来
66 | "no-div-regex": 0, // 消除除法运算符迷惑用户使用 例如 return /=foo/; 应该写成 return /\=foo/;
67 | "no-else-return": 2, // 如果在if语句中有return,则在else中可以不用return,可以放到最外面返回
68 | "no-empty-function": 0, //不要定义空函数
69 | "no-empty-pattern": 2, // 不允许空的解构赋值,例如 var {a: {}} = foo;
70 | "no-eq-null": 0, // 对于null比较也应该使用 === 来比较
71 | "no-eval": 2, // 不允许使用 eval()
72 | "no-extend-native": 2, // 不允许修改扩展内置对象的属性,比如 Object.prototype.a = "a";
73 | "no-extra-bind": 0, // 可以规范代码,防止滥用 bind 方法
74 | "no-extra-label": 2, // 当使用 label 表达式时,检测不必要的 label 表达式
75 | "no-fallthrough": 2, // 是否检测switch语句中 case 后没有break,return或throw
76 | "no-floating-decimal": 2, // 对于浮点数,不能省略.前或.后的数字2
77 | "no-global-assign": [2, {"exceptions": ["Object"]}], // 不要给全局变量赋值,需要先定义在赋值
78 | "no-implicit-coercion": [2, {"string": false}], // 不要使用隐身转换,应该使用直接转换,如果针对 boolean number string ,比如 var n = +foo; 应该为 var n = Number(foo); 代替
79 | "no-implicit-globals": 0,
80 | "no-implied-eval": 2, // 不要使用隐式调用eval的语句,比如 setInterval("alert('Hi!');", 122);
81 | "no-invalid-this": 0, // 用来检测 this 关键字使用的地方是否正确,我们可以设置关闭该规则
82 | "no-iterator": 2, // 在ES6中有__iterator__属性,建议不要修改该属性值
83 | "no-labels": 2, // 不建议使用 label 表达式
84 | "no-lone-blocks": 2, // 禁止内部不必要的嵌套块
85 | "no-loop-func": 2, // 不要在循环中定义函数,并且该函数中调用了循环变量
86 | "no-magic-numbers": [0, { // 一些系数最好定义为常量
87 | "ignore": [-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 16],
88 | "ignoreArrayIndexes": true
89 | }
90 | ],
91 | "no-multi-spaces": [0, { // 表达式中是否允许有多余的空格
92 | "exceptions": {
93 | "AssignmentExpression": true,
94 | "ArrowFunctionExpression": true,
95 | "CallExpression": true,
96 | "VariableDeclarator": true
97 | }
98 | }
99 | ],
100 | "no-multi-str": 2, // 是否允许多行字符串
101 | "no-new": 0, // 不允许实例化类,而没有赋给任何变量
102 | "no-new-func": 2, // 不建议使用 new Function 来声明函数
103 | "no-new-wrappers": 2, // 对于String, Number, 和 Boolean,不建议使用 new,即 new String 等
104 | "no-octal": 2, // 不允许使用八进制数字
105 | "no-octal-escape": 2, // 不允许使用八进制转义字符串
106 | "no-param-reassign": 0, // 如果开启,则不允许重新修改函数参数值,或者参数属性值
107 | "no-proto": 2, // 不建议使用该属性 __proto__
108 | "no-redeclare": 2, // 不允许重复声明同一个变量
109 | "no-restricted-properties": [2, { // 定义不允许的对象属性
110 | "object": "disallowedObjectName",
111 | "property": "disallowedPropertyName",
112 | "message": "Please use allowedObjectName.allowedPropertyName."
113 | }],
114 | "no-return-assign": 2, // 不允许在return语句中有赋值语句
115 | "no-return-await": 2, // disallow unnecessary return await
116 | "no-script-url": 2, // 不要使用javascript:url,比如 location.href = "scripts:void(2)";是错误的
117 | "no-self-assign": [2, {"props": false}],// 不建议自己给自己赋值,比如 foo = foo
118 | "no-self-compare": 2, // 不允许变量自己跟自己做比较
119 | "no-sequences": 2, // 需要正确的使用逗号操作符
120 | "no-throw-literal": 2, // 抛出异常时,请使用 new Error()
121 | "no-unmodified-loop-condition": 2, // 用来检测循环中的条件值始终没有改变
122 | "no-unused-expressions": 2, // 不允许出现未使用的表达式
123 | "no-unused-labels": 2, // 定义了 label 而没有被调用
124 | "no-useless-call": 2, // 对于不必要使用call或apply,建议不要使用,直接调用即可
125 | "no-useless-concat": 2, // 不必要的字符串连接最好去掉,写在一起
126 | "no-useless-escape": 2, // 不必要的转义就不要转义了
127 | "no-useless-return": 2, // 不允许出现不必要的 return 语句
128 | "no-void": 2, // 不建议使用void操作符
129 | "no-warning-comments": 0, // 对于注释中的 TODO FIXME XXX 等,是否给出提示,建议开发中设置为1,部署的时候设置为 2
130 | "no-with": 2, // 不允许使用with表达式语句
131 | "prefer-promise-reject-errors": 2, // 对于Promise.reject,参数必须是一个 Error 对象,比如 Promise.reject(5); 是不允许的,应该写成 Promise.reject(new Error("something bad happened"));
132 | "radix": 2, // 在调用 parseInt 应该指定基数
133 | "require-await": 2, // 对于 async 表达式,必须有对应的 await 表达式
134 | "vars-on-top": 0, // 所有变量声明是否都放在函数最上面或过程快最上面
135 | "wrap-iife": [2, "any"], // 立即执行函数是里面包裹还是外面包裹,默认是外面包裹,即 outside
136 | "yoda": 2, // 不允许使用 yoda 条件表达式,常量值在前的比较表达式,比如: if(1 === a){ }
137 |
138 | // Variables
139 | "init-declarations": 0, // 声明变量的时候赋值,还是在其他地方赋值,我们可以关闭该规则
140 | "no-catch-shadow": 2, // 在IE8或更早的浏览器中,在catch语句中引入的变量 e 会调用全局已定义的变量 e
141 | "no-delete-var": 2, // 不能删除变量,而只能删除属性
142 | "no-label-var": 2, // 使用标签label语句时,不要跟变量同名,建议不要使用标签
143 | "no-restricted-globals": 2, // 不要使用全局变量
144 | "no-shadow": 0, // 全局和局部变量名不要用相同的名称
145 | "no-shadow-restricted-names": 2, // 不要使用 NaN, Infinity, undefined 等内部定义的变量来声明变量
146 | "no-undef": 2, // 不要使用还没有定义的变量或函数,如果引用第三方定义的变量,可以用 /*global */ 来标注,例如 /*global require define:true*/
147 | "no-undef-init": 2, // 定义变量的时候,如果没有合适的赋值,不用显式设置 undefined ,因为默认声明而未赋值的变量,其默认值为 undefined
148 | "no-undefined": 0, // 代码中不建议使用 undefined ,包括命令和赋值等
149 | /**
150 | 定义了,但没有使用该变量,vars 有两种选择 all 和 local;args 有三种选择,all after-used 和 none
151 | 我们可以只检测变量而不检测函数参数,可以把 args 设为 none
152 | **/
153 | "no-unused-vars": [0, {"vars": "all", "args": "none"}],
154 | "no-use-before-define": [0, "nofunc"], // 变量和函数的声明需要在使用之前,可以设置 [2, "nofunc"],只检测变量,而不检测函数
155 |
156 | //Node.scripts and CommonJS
157 | "callback-return": 0, // 调用callback时需要加上return语句
158 | "global-require": 0, // require加载依赖应该放在代码最上边显示,比如 var fs = require("fs");
159 | "handle-callback-err": 2, // 如果回调函数中有错误变量(比如err),我们需要判断处理错误的情况
160 | "no-mixed-requires": 2, // require与其他变量声明应该不要放在一起
161 | "no-new-require": 2, // 不用对表达式 require 直接使用 new,例如 var appHeader = new require('app-header');
162 | "no-path-concat": 2, // 不要使用 __dirname 或 __filename 与字符串连接生成路径,应该使用 path.join(__dirname, "foo.scripts"); 或 path.resolve(__dirname, "foo.scripts");
163 | "no-process-env": 0, // 在node环境中,不建议使用 process.env ,而使用 config 来配置
164 | "no-process-exit": 2, // 不要直接调用 process.exit();
165 | "no-restricted-modules": 2, // 限制使用某些模块,比如 no-restricted-modules: [2, "fs"] ,不能使用fs模块
166 | "no-sync": 2, // 我们尽量使用异步方法来代替同步方法,比如操作文件等,
167 |
168 | // Stylistic Issues
169 | "array-bracket-spacing": 2, // 数组元素前后是否要加一空格,默认为不必要加,如 var arr = [ 'foo', 'bar' ]; 是不正确的写法
170 | "block-spacing": 2, // 花括号与语句间应该有空格
171 | "brace-style": 2, // 条件或循环语句中,花括号是另起一行,还是与当前语句在同一行,默认跟当前语句在同一行
172 | "camelcase": 2, // 驼峰式命名变量或属性
173 | "capitalized-comments": 0, // 注释的大小写格式限制
174 | "comma-dangle": 0, // 对象最后一个属性,是否需要逗号
175 | "comma-spacing": 2, // 逗号表达式前后空格情况,默认前面没有,后边应该添加
176 | "comma-style": 2, // 当换行时,逗号是在当前行还是下一行,默认是当前行
177 | "computed-property-spacing": 2, // 用[]取属性值时,是否应该有空格
178 | "consistent-this": [2, "self"], // 闭包的时候,this 用变量声明上下文应该统一,该变量就不用用在其他定义变量上
179 | "eol-last": 2, // 在行的末尾至少空上一行
180 | "func-call-spacing": 2, // 函数名与括号之间是否需要一个空格
181 | "func-name-matching": 2, // 定义函数变量时,匿名名称是否应该跟变量名称一致,默认一致
182 | "func-names": 0, // 函数表达式需要一个名称,包括匿名函数,该规则可以关闭
183 | "func-style": [0, "declaration", { // 是声明式的函数,还是定义变量式的函数,我们采用声明式,但箭头函数允许变量式
184 | "allowArrowFunctions": true
185 | }],
186 | "id-blacklist": 2, // 指定一些黑名单变量,这些变量不能出现在代码中,比如 "id-blacklist": [2, "data", "err", "e", "cb", "callback"],
187 | "id-length": 0, // 定义变量名或属性名的最小最大长度
188 | "id-match": 2, // 规范变量名或属性名的命名规范
189 | "indent": [0, 2, {"SwitchCase": 1},
190 | { "VariableDeclarator": { "var": 2, "let": 2, "const": 3 }},
191 | ], // 缩进,我们采用2个空格来缩进
192 | "jsx-quotes": 0, // jsx属性值应该用双引号
193 | "key-spacing": 2, // 键值之间的空格
194 | "keyword-spacing": 2, // 关键字 if, else, for, while, do, switch, try, catch, finally, and with 要求有空格
195 | "linebreak-style": 0, // 验证 unix (LF) or windows (CRLF)
196 | "lines-around-comment": 0, // 注释的规范写法,在旁边或上方
197 | "lines-around-directive": 2, // 不同的语句中间是否加一空行
198 | "max-depth": [2, 12], // 限制语句块最大嵌套深度
199 | "max-len": [ // 限定每行最大长度
200 | 2, 200, {
201 |
202 | }
203 | ],
204 | "max-lines": [2, {"max": 800, "skipBlankLines": true, "skipComments": true}], // 指定每个文件最大行
205 | "max-nested-callbacks": [1, 3], // 限定回调函数最大深度
206 | "max-params": [2, 8], // 限定函数参数最大个数
207 | "max-statements": [2, 80, {"ignoreTopLevelFunctions": true}], // 在一个函数中限定声明表达式最多个数,内部函数会或略
208 | "max-statements-per-line": [2, {"max": 2}], // 每行最大表达式
209 | "multiline-ternary": 0, // 三元表达式,是否需要多行书写
210 | "new-cap": 0, // 构造函数首字母应该大写
211 | "new-parens": 2, // 实例化构造函数时,需要加入(),即使没有参数值,所以比如 new Person 是不允许的
212 | "newline-after-var": 0, // 用var声明变量时,是否允许换行
213 | "newline-before-return": 0,
214 | "newline-per-chained-call": 0,
215 | "no-array-constructor": 0, // 不允许使用 new Array(2, 1, 2) 来创建数组,而改用 []
216 | "no-bitwise": 0, // 禁止使用位运算符,包括以下情况 var x = y | z; var x = y & z; var x = y ^ z; var x = ~ z; var x = y << z; var x = y >> z; var x = y >>> z; x |= y; x &= y; x ^= y; x <<= y; x >>= y; x >>>= y;
217 | "no-continue": 0, // 是否允许使用 continue语句
218 | "no-inline-comments": 0,// 注释是否允许在代码的后面,开启则不允许
219 | "no-lonely-if": 0, // 应该使用 else if ,而不要使用 else { if(){} }
220 | "no-mixed-operators": 2, // 不要把多个操作符写在一起使用,最好用括号括起来
221 | "no-mixed-spaces-and-tabs": 2, // 不允许空格和制表位混合使用
222 | "no-multi-assign": 0, // 不要连续赋值,比如 var a = b = c = 5;
223 | "no-multiple-empty-lines": 2, // 代码中不要出现太多空行,默认最多为2行
224 | "no-negated-condition": 0, // 是否允许使用否定表达式 if (!a)
225 | "no-nested-ternary": 2, // 是否允许使用嵌套的三元表达式
226 | "no-new-object": 2, // 实例化对象时,不要用 new Object(); 而用 {}
227 | "no-plusplus": [0, {"allowForLoopAfterthoughts": true }], // 是否允许使用 ++ 或 --
228 | "no-restricted-syntax": [2, "WithStatement"], // 可以指定不允许的语法
229 | "no-tabs": 2, // 是否允许使用制表符
230 | "no-ternary": 0, // 是否允许三元操作符
231 | "no-trailing-spaces": 0, // 不允许行尾有空白字符
232 | "no-underscore-dangle": 0, // 是否允许变量名前后有 _
233 | "no-unneeded-ternary": 2, // 请不要使用不必要的三元表达式,比如 var isYes = answer === 1 ? true : false;
234 | "no-whitespace-before-property": 0,
235 | "nonblock-statement-body-position": 2, // 如果在条件或循环表达式中,只有一行的表达式,并且没有使用 {} ,最好跟条件写在一行
236 | "object-curly-newline": 0,
237 | "object-curly-spacing": 0, // 验证花括号内的空格
238 | "object-property-newline": 0, // 对象属性在新行显示
239 | "one-var": 0, // 多个变量声明是否用一个var语句
240 | "one-var-declaration-per-line": [0, "always"], // 定义多个变量时,是否需要每个变量在一行显示
241 | "operator-assignment": 2, // 对于赋值表达式,应该使用其简略式写法,比如 x = x + y 应该用 x += y
242 | "operator-linebreak": 0, // 有操作符时,是否检测打断的行
243 | "padded-blocks": 0, // 是否验证空白块
244 | "quote-props": [2, "as-needed"], // 属性加单引号或双引号,个人建议不用加的最好不加
245 | "quotes": [2, "single"], // 字符串引号,建议使用单引号
246 | "require-jsdoc": 0, // 是否需要 jsdoc 来注释代码
247 | "semi": [0, "always"], // 总是要求加上分号
248 | "semi-spacing": 2, // 分号与代码之间的间隔
249 | "sort-keys": 0, // 属性是否需要排序
250 | "sort-vars": 0, // 定义多个变量时,是否按字符顺序来排序,不建议开启该规则
251 | "space-before-blocks": 2, // 在每一块后面需要添加一空格
252 | "space-before-function-paren": 0, // 在函数名和() 之间有一空格
253 | "space-in-parens": 0, // 括号和参数之间应该没有空格
254 | "space-infix-ops": 2, // 表达式中间应该添加空白
255 | "space-unary-ops": 2, // 在一元操作符前或后不应该有空白
256 | "spaced-comment": [0, "always", {
257 | "line": {
258 | "markers": ["/"],
259 | "exceptions": ["-", "+"]
260 | },
261 | "block": {
262 | "markers": ["!"],
263 | "exceptions": ["*"],
264 | "balanced": true
265 | }
266 | }], // 如果开启,则会检测注释符后是否有空白,always必须有,而never则没有
267 | "template-tag-spacing": 2, // 标记模板内容,中间是否需要加空格,默认不需要加
268 | "unicode-bom": 2, //
269 | "wrap-regex": 2, // 字面正则表达式需要用括号括起来
270 |
271 | // es6
272 | "arrow-body-style": [2, "always"],// 箭头函数是否需要加上{}
273 | "arrow-parens": 2,//对于箭头函数,需要添加括号,比如(a) => {}; 而不应该简写为 a => {};
274 | "arrow-spacing": 2,//箭头函数中,箭头运算符前后需要添加空白
275 | "constructor-super": 2,//父类构造函数不应该调用 super() ,但派生类必须要调用 super()
276 | "generator-star-spacing": 2,//generator functions 中 * 前应该添加空白,后面不应该有空白
277 | "no-class-assign": 2,//不能再修改已经声明的类,即不能重现给已经声明的类赋其他值
278 | "no-confusing-arrow": 2, //箭头函数中不建议使用引起疑惑的表达式,比如 var x = a => 1 ? 2 : 3,如果使用需要用{} 括起来
279 | "no-const-assign": 2,//不能修改常量值
280 | "no-dupe-class-members": 2,//类成员不能重复定义
281 | "no-duplicate-imports": 2,
282 | "no-new-symbol": 2, //对于 Symbol,不要使用 new,例如 var foo = new Symbol("foo");
283 | "no-restricted-imports": 2,// 禁止特定的导入
284 | "no-this-before-super": 2,//不允许在 super() 之前使用 this/super 语句
285 | "no-useless-computed-key": 2, //禁止不必要的属性计算表达式
286 | "no-useless-constructor": 2, //禁止不必要的构造方法,比如空的构造器
287 | "no-useless-rename": 2, // 禁止不必要的别名表达式,比如 export { foo as bar } from 'foo';
288 | "no-var": 2,//在需要使用const 或 let 声明时不要使用var
289 | "object-shorthand": 2,//利用简写法来定义对象属性,如 var foo = {x, y, z}; 表示 var foo = {x:x, y:y, z:z};
290 | "prefer-arrow-callback": 2,//建议使用箭头函数作为回调函数
291 | "prefer-const": 2,//能使用常量的地方尽量使用const
292 | "prefer-destructuring": 2, // 尽量使用解构表达式,比如 const [foo] = array; 或 const {bar: foo} = object;
293 | "prefer-numeric-literals": 2, // 不允许直接使用 parseInt 解析字面量变量,比如 parseInt("111110111", 2),而 parseInt(foo); 是允许的
294 | "prefer-rest-params": 2, // 建议使用 rest (...args) 参数来代替 arguments
295 | "prefer-spread": 2,//不要使用apply,应该使用扩展操作符来调用 Math.max(...args);
296 | "prefer-template": 2,//建议使用模板符来替代引号,比如 var str = `Hello, ${name}!`;
297 | "require-yield": 2,//generator functions 应该有 yield
298 | "rest-spread-spacing": 2,//rest 表达式中间是否加空格,默认不加
299 | "sort-imports": 0, // improt 的变量名称导入应该按顺序排位
300 | "symbol-description": 2, // 使用 Symbol 定义变量时,需要传入 Symbol description
301 | "template-curly-spacing": [2, "never"], // 模板表达式中 {} 前后是否需要空格
302 | "yield-star-spacing": [2, {"before": true, "after": false}], // yield * 号前后是否需要空格
303 |
304 |
305 | // react rules,默认设置为报错 https://github.com/yannickcr/eslint-plugin-react
306 |
307 | "react/display-name": 0, // 是否检测需要为React Component 设置一个 displayName
308 | "react/forbid-component-props": 0, // 禁止某些在组件上的属性,比如 className 等
309 | "react/forbid-elements": [2, {"forbid": [""] }], // 禁止使用某些标签
310 | "react/forbid-prop-types": 0, // 是否检测使用了React.PropTypes.any React.PropTypes.array 或 React.PropTypes.object,如果开启该规则,则不允许使用React.PropTypes 指定的类型,而用具体的类型来说明,默认该规则是关闭的
311 | "react/forbid-foreign-prop-types": 2, // 不要使用不相关的 PropTypes
312 | "react/no-array-index-key": 2, // 最好不用使用数组的 index 作为 key
313 | "react/no-children-prop": 2, // 不需要把 children 作为 prop 传递
314 | "react/no-danger": 2, // 不要使用不安全的名称来定义属性,比如 dangerouslySetInnerHTML __html,看 https://facebook.github.io/react/tips/dangerously-set-inner-html.html
315 | "react/no-danger-with-children": 2, // 对于属性dangerouslySetInnerHTML存在的话,不需要再书写 children
316 | "react/no-deprecated": 2, // 建议不要使用不赞成的方法,比如 React.render(, root); React.unmountComponentAtNode(root);
317 | "react/no-did-mount-set-state": 2, // 在componentDidMount 中不要使用 setState 方法
318 | "react/no-did-update-set-state": 2, // componentDidUpdate 中不要使用 setState 方法
319 | "react/no-direct-mutation-state": 2, // 不要直接使用 this.state 来改变值,而应该用 this.setState
320 | "react/no-find-dom-node": 2, // 不建议使用 findDOMNode,因为最终该方法会被废弃
321 | "react/no-is-mounted": 2, // 不建议使用方法 this.isMounted()
322 | "react/no-multi-comp": [2, { "ignoreStateless": true }], // 不建议在一个文件中定义多个组件,但无状态的组件被或略
323 | "react/no-render-return-value": 2, // 使用ReactDOM.render()不应该有返回值
324 | "react/no-set-state": 0, // 在 Flux 或 redux 中是使用 store 维持 state 的,在这些框架中可以不使用 state
325 | "react/no-string-refs": 0, // 不建议使用字符串的 ref 而应该使用变量
326 | "react/no-unescaped-entities": 2, // 不要出现没有转义的字符直接量
327 | "react/no-unknown-property": 2, // 不要使用扁平或不接受的属性名称,比如class,而用className,属性名应该是驼峰式命名
328 | "react/no-unused-prop-types": 2, // 声明了 props 而没有被使用
329 | "react/prefer-es6-class": 2, // 应该使用 es6 来创建 class
330 | "react/prefer-stateless-function": 2, // 对于无状态的组件尽量使用函数来声明组件,比如 const Foo = function(props) {return
{props.foo}
;};
331 | "react/prop-types": 2, // 对于没有设置 propType 的 prop 给出警告
332 | "react/react-in-jsx-scope": 2, // 对于使用了 JSX,要使用 React 组件
333 | "react/require-default-props": 0, // 对于每个 prop ,是否需要设置一下其 defaultProps 值
334 | "react/require-optimization": 0, // 检测每个组件是否有 shouldComponentUpdate 方法
335 | "react/require-render-return": 2, // render 方法中需要 return
336 | "react/self-closing-comp": 0, // 对于没有子元素的组件应该是这样的 而不应该
337 | "react/sort-comp": 2, // 组件方法是否按一定的顺序书写,默认为: 1 static methods and properties 2 lifecycle methods: displayName, propTypes, contextTypes, childContextTypes, mixins, statics,defaultProps, constructor, getDefaultProps, getInitialState, state, getChildContext, componentWillMount, componentDidMount, componentWillReceiveProps, shouldComponentUpdate, componentWillUpdate, componentDidUpdate, componentWillUnmount (in this order). 3 custom methods 4 render method
338 | "react/sort-prop-types": 0, // propType 是否按字母顺序来排列
339 | "react/style-prop-object": 2, // style 必须是对象
340 | "react/void-dom-elements-no-children": 2, // 不要给没有子节点的 dom 标签设置 childern 内容,比如
Children
, 这些都是错误的写法
341 |
342 | // JSX-specific rules 以下为 jsx 规则
343 | "react/jsx-boolean-value": 2, // 该规则可以设置为两种情况,always 和 never ,设置为 always 如果 attribute 没有设置值,会警告;设为 never,如果 attribute 有一个 true 值,会警告 https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-boolean-value.md
344 | "react/jsx-closing-bracket-location": 0, // 检测jsx tag 闭合书写规范
345 | "react/jsx-curly-spacing": 2, // 检测赋值是否有空格,默认是不应该有空格的,但换行不检测,比如 ;
346 | "react/jsx-equals-spacing": [2, "never"], // 再给属性赋值时,是否在 = 前后加上空格
347 | "react/jsx-filename-extension": 0, // 后缀名,是否必须是 jsx
348 | "react/jsx-first-prop-new-line": 0, // 第一个属性名是否在新的一行书写
349 | "react/jsx-handler-names": 2, // 按照惯例,事件方法名前是否加上 handle
350 | "react/jsx-indent": [2, 2], // jsx 嵌套包裹缩进,默认用2个
351 | "react/jsx-indent-props": [0, 2],// jsx语法换行缩进几个空格(或制表符)
352 | "react/jsx-key": 2, // 在循环中,组件应该设置不同的 key
353 | "react/jsx-max-props-per-line": 0, // jsx 每个属性应该写在单独一行(默认),也可以设置每行的个数
354 | "react/jsx-no-bind": 2, // 不必要的地方不使用bind
355 | "react/jsx-no-comment-textnodes": 2, // 检测注释的正确性
356 | "react/jsx-no-duplicate-props": 2, // 给jsx设置同名的属性会警告
357 | "react/jsx-no-literals": 0, // 不要设置字面的值,比如 var Hello = test
; 而用 var Hello = {'test'}
;
358 | "react/jsx-no-target-blank": 0,
359 | "react/jsx-no-undef": 2, // 检测定义了jsx component 而没有被调用
360 | "react/jsx-pascal-case": 2, // 应该使用 pascal 来命名组件名
361 | "react/jsx-sort-props": 0, // 属性名是否按字母排序
362 | "react/jsx-space-before-closing": 0, // 在关闭标签前是否加一空格
363 | "react/jsx-tag-spacing": 0, // 检测标签空格
364 | "react/jsx-uses-react": 2,// React声明了而没有被调用
365 | "react/jsx-uses-vars": 2, // jsx组件被定义而没有被调用
366 | "react/jsx-wrap-multilines": 2 // 多行 jsx 表达式应该用 () 包裹起来
367 | },
368 | "parser": "babel-eslint", // 指定默认解析器
369 | "env": {
370 | "es6": true,
371 | "node": true,
372 | "browser": true
373 | },
374 | "parserOptions": {
375 | "ecmaVersion": 8,
376 | "sourceType": "module",
377 | "ecmaFeatures": {
378 | "jsx": true // enable JSX
379 | }
380 | },
381 | "globals": { // 定义全局的变量
382 |
383 | },
384 | "extends": [ // 推荐使用默认配置好的
385 | "eslint:recommended", "plugin:react/recommended"
386 | ],
387 | "plugins": [//定义第三方插件
388 | "react"
389 | ],
390 | "settings": {// 设置
391 | "react": {
392 | "createClass": "createReactClass", // Regex for Component Factory to use, default to "createReactClass"
393 | "pragma": "React", // Pragma to use, default to "React"
394 | "version": "16.0.0" // React version, default to the latest React stable release
395 | },
396 | "sharedData": "sharedName"
397 | },
398 | "root": true // 设置他后,子的js文件找到该 eslint配置文件后,则不再向上查找其他eslint配置文件
399 | }
400 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Ignore files
2 | .idea
3 | node_modules
4 | publish
5 | !publish/package.json
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # React AlloyTouch 更新日志
2 |
3 | ## version 0.4.1
4 |
5 | * 修复了 bug #4 ref 采用建议的回调函数写法而非字符串
6 |
7 | ## version 0.4.0
8 |
9 | * 去掉了 babel-preset-es2015,改用 babel-preset-env
10 | * 升级到 react 16
11 | * 默认下拉刷新和上拉加载隐藏显示,当需要的时候再显示
12 |
13 | ## version 0.3.2
14 |
15 | * 修改了下拉刷新,有时不能正常滑到底部的 bug
16 | * 新增了两个可选项
17 | * loadedRecoilTime: PropTypes.number, // 加载完更多数据回弹时间
18 | * moveForwardOffset: PropTypes.number, // 加载完更多数据时,向前推进的距离
19 | * 修改了对应的下拉刷新,上拉加载更多例子
20 |
21 | ## version 0.2.0
22 |
23 | * 修改下拉刷新组件,当数据只有一行时的 bug
24 |
25 | ## version 0.1.8
26 |
27 | * 添加自定义轮播图内容,并添加tabs接口
28 |
29 | ## version 0.1.6
30 |
31 | * 为轮播图增加自定义事件
32 |
33 | ## version 0.1.4
34 |
35 | * 新增下拉刷新中显示轮播图例子
36 |
37 | ## version 0.1.0 开启 React AlloyTouch 之旅
38 |
39 |
40 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2016 reactjs-ui
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # React AlloyTouch
2 |
3 | This is a react component for AlloyTouch.
4 |
5 | ## Install
6 |
7 | ```
8 | npm install react-alloytouch --save
9 | ```
10 |
11 | ## Usage
12 |
13 | ### Pull Component
14 |
15 | #### example code
16 |
17 | ```javascript
18 | import React, {Component} from 'react';
19 | import {render} from 'react-dom';
20 | import injectTapEventPlugin from 'react-tap-event-plugin';
21 | import {ReactPull} from 'react-alloytouch';
22 | import 'react-alloytouch/sass/pull.scss'; // 或者 import 'react-alloytouch/css/pull.css';
23 | import './sass/example.scss'; // 自定义样式
24 |
25 | // 初始化 tapEvent 事件, 移动端
26 | injectTapEventPlugin();
27 |
28 | class ReactPullExample extends Component {
29 | constructor(props) {
30 | super(props);
31 | this.state = {
32 | items: 30,
33 | disablePullUp: false
34 | };
35 | }
36 |
37 | refreshCallback = () => {
38 | return new Promise((resolve, reject) => {
39 | setTimeout(() => {
40 | let result = false;
41 | if (Math.random() > 0.2) {
42 | result = true;
43 | }
44 | if (result) {
45 | this.setState({
46 | items: 30,
47 | disablePullUp: false
48 | }, () => {
49 | resolve();
50 | });
51 | } else {
52 | reject(new Error('错误'));
53 | }
54 | }, 1000);
55 | }).then(() => {
56 | console.info('刷新成功!');
57 | }, () => {
58 | console.info('刷新失败!');
59 | });
60 | };
61 |
62 | loadMoreCallback = () => {
63 | return new Promise((resolve, reject) => {
64 | setTimeout(() => {
65 | let result = false;
66 | if (Math.random() > 0.2) {
67 | result = true;
68 | }
69 | if (result) {
70 | this.setState({
71 | items: this.state.items + 10,
72 | disablePullUp: this.state.items >= 60
73 | }, () => {
74 | resolve();
75 | });
76 | } else {
77 | reject(new Error('错误'));
78 | }
79 | }, 1000);
80 | }).then(() => {
81 | console.info('加载更多成功!');
82 | }, () => {
83 | console.info('加载更多失败!');
84 | });
85 | };
86 |
87 | handleTouchTap = (e) => {
88 | console.info('测试下拉刷新插件是否与 Tap 事件冲突');
89 | };
90 |
91 | render() {
92 | const contents = [];
93 | const {items, disablePullUp} = this.state;
94 |
95 | for (let i = items; i > 0; i--) {
96 | if (i < 10) {
97 | contents.push(这里放置真实显示的DOM内容 {i});
98 | } else {
99 | contents.push(这里放置真实显示的DOM内容 {i});
100 | }
101 | }
102 |
103 | const props = {
104 | refreshCallback: this.refreshCallback,
105 | loadMoreCallback: this.loadMoreCallback,
106 | refresh: true,
107 | loadMore: true,
108 | disablePullUp,
109 | };
110 |
111 | return (
112 |
113 |
114 | {contents.map((item) => {
115 | return item;
116 | })}
117 |
118 |
119 | );
120 | }
121 | }
122 |
123 | render(
124 | , document.getElementById('layout')
125 | );
126 |
127 | ```
128 |
129 | #### Options
130 |
131 | | 选项 | 类型 | 功能 |
132 | | -------- | ----- | ---- |
133 | | children | PropTypes.node| 待渲染的内容|
134 | | className | PropTypes.string| 自定义 className|
135 | | header | PropTypes.element| 头部|
136 | | footer | PropTypes.element| 底部|
137 | | options | PropTypes.object| AlloyTouch 组件选项|
138 | | lockInTime | PropTypes.number| 延迟刷新或加载|
139 | | enableText | PropTypes.bool| 是否显示滚动条|
140 | | refresh | PropTypes.bool| 是否下拉刷新|
141 | | refreshThreshold | PropTypes.number| 设置刷新页面时,距离顶部临界值 |
142 | | refreshCallback | PropTypes.func| 刷新回调函数|
143 | | pullDownText | PropTypes.array | 下拉显示文本内容 |
144 | | loadMore | PropTypes.bool | 是否加载更多 |
145 | | loadMoreThrottle | PropTypes.number | 设置加载更多,距离最底部临界值 |
146 | | loadMoreCallback | PropTypes.func | 加载更多回调函数 |
147 | | pullUpText | PropTypes.array | 上拉显示文本内容 |
148 | | loadMoreProcessIcon | PropTypes.bool | 加载更多过程图标 |
149 | | disablePullUp | PropTypes.bool | 对于上拉加载更多时,如果没有更多记录时,禁止上滑 |
150 | | loadedRecoilTime| PropTypes.number| 加载完更多数据回弹时间|
151 | | moveForwardOffset| PropTypes.number| 加载完更多数据时,向前推进的距离|
152 |
153 | 对于 AlloyTouch 组件选项 options 设置,看[官方说明](https://github.com/AlloyTeam/AlloyTouch)
154 |
155 | ### Carousel Component
156 |
157 | #### example code
158 |
159 | ```javascript
160 | import React, {Component} from 'react';
161 | import {render} from 'react-dom';
162 | import {ReactCarousel} from 'react-alloytouch';
163 | import 'react-alloytouch/sass/carousel.scss'; // 或者 import 'react-alloytouch/css/carousel.css';
164 | import './sass/example.scss'; // 自定义样式
165 |
166 | const ReactCarouselExample = () => {
167 |
168 | const items = [{
169 | image: 'http://alloyteam.github.io/AlloyTouch/example/asset/ci1.jpg',
170 | link: 'http://jd.com'
171 | }, {
172 | image: 'http://alloyteam.github.io/AlloyTouch/example/asset/ci2.jpg',
173 | }, {
174 | image: 'http://alloyteam.github.io/AlloyTouch/example/asset/ci3.jpg',
175 | link: 'http://jd.com'
176 | }, {
177 | image: 'http://alloyteam.github.io/AlloyTouch/example/asset/ci4.jpg'
178 | }];
179 | const events = {
180 | onTouchTap: () => {
181 | console.info('这是个测试!');
182 | }
183 | };
184 |
185 | return (
186 |
187 | );
188 | };
189 |
190 | render(
191 | , document.getElementById('layout')
192 | );
193 |
194 | ```
195 |
196 | #### Options
197 |
198 | | 选项 | 类型 | 功能 |
199 | | -------- | ----- | ---- |
200 | | className | PropTypes.string| 自定义 className|
201 | | prefix | PropTypes.string| 样式前缀|
202 | | options | PropTypes.object| AlloyTouch 组件选项|
203 | | items | PropTypes.array| 轮播图|
204 | | active | PropTypes.number| 当前活动轮播图|
205 | | autoPlay | PropTypes.oneOfType([PropTypes.bool, PropTypes.number])| 是否自动播放|
206 | | events | PropTypes.object| 自定义各种事件|
207 |
208 | ## Example
209 |
210 | ```
211 | npm install
212 | npm start
213 | ```
214 |
215 | http://localhost:9090
216 |
217 |
218 | ## Online Example
219 |
220 | http://reactjs-ui.github.io/react-alloytouch/
221 |
222 | ## Build Example
223 | 第一次需要先执行前两步操作,再执行第三步。以后修改例子后,只需要执行第三步即可
224 |
225 | 1. 创建 gh-pages 分支,**在执行 git subtree add 命令之前,需确保 gh-pages 分支下至少存在一个文件**
226 | ```
227 | git checkout -b gh-pages
228 | rm -rf * //隐藏文件需要单独删除,结合命令 ls -a
229 | vim .gitignore //输入一些内容
230 | git add .
231 | git commit -m "init branch gh-pages"
232 | git push --set-upstream origin gh-pages
233 | git checkout master
234 | ```
235 |
236 | 2. 把分支 gh-pages 添加到本地 subtree 中,执行该命令前,请确保 examples-dist 文件夹不存在
237 |
238 | ```
239 | git subtree add --prefix=examples-dist origin gh-pages --squash
240 | ```
241 |
242 | 3. 生成在线 examples
243 |
244 | ```
245 | npm run build:examples
246 | git add examples-dist
247 | git commit -m "Update online examples"
248 | git subtree pull --prefix=examples-dist origin gh-pages
249 | git subtree push --prefix=examples-dist origin gh-pages --squash
250 | git push
251 | ```
252 |
253 | 4 使用以下命令一键发布在线例子
254 | ```bash
255 | npm run examples:publish
256 | ```
257 |
258 | ## Build
259 |
260 | ```
261 | npm run build
262 | ```
263 |
264 | ## Publish
265 |
266 | ```
267 | npm run build:publish
268 | ```
269 |
270 | ## Issue
271 |
272 | https://github.com/reactjs-ui/react-alloytouch/issues
273 |
274 | ## Change Log
275 |
276 | Please view [here](./CHANGELOG.md)
277 |
--------------------------------------------------------------------------------
/examples-dist/carousel.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 轮播
5 |
6 |
8 |
9 |
24 |
25 |
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/examples-dist/css/carousel.d7c89e08b5abfb774f54.css:
--------------------------------------------------------------------------------
1 | body{margin:0}a{color:#00c176}a:active,a:focus,a:hover{color:#88c100}.example{margin:50px auto;width:80%}.example-list>li{padding:10px}.footer,.header{padding:5px;background-color:#00c176;color:#fff;text-align:center}.pull-carousel .pull-refresh{top:-50px;padding-bottom:10px}.carousel-scroller .swiper-panel{text-align:center;height:200px;font-size:28px;background:#f0f0f0}.carousel-wrapper{margin:0 auto;overflow:hidden;position:relative}.carousel-scroller{position:relative;font-size:0;user-select:none;text-size-adjust:none;-webkit-tap-highlight-color:transparent;-webkit-touch-callout:none}.carousel-scroller .swiper-panel{float:left}.carousel-tabs-menu{display:flex}.carousel-tabs-menu .carousel-tabs-item{flex:1;text-align:center;line-height:2.2;bordr-bottom:2px solid transparent}.carousel-tabs-menu .active{color:#cf121b;border-bottom:2px solid #cf121b}.carousel-nav{position:absolute;bottom:6px;right:10px}.carousel-nav>a{display:inline-block;background-color:#fff;cursor:pointer;width:6px;height:6px;border-radius:5px;border:1px solid gray;transition:all .5s ease-in}.carousel-nav>a.active{background-color:#ffd800;width:10px}
2 | /*# sourceMappingURL=carousel.d7c89e08b5abfb774f54.css.map*/
--------------------------------------------------------------------------------
/examples-dist/css/carousel.d7c89e08b5abfb774f54.css.map:
--------------------------------------------------------------------------------
1 | {"version":3,"sources":[],"names":[],"mappings":"","file":"css/carousel.d7c89e08b5abfb774f54.css","sourceRoot":""}
--------------------------------------------------------------------------------
/examples-dist/css/header-footer.aa697a21f7857d4c1560.css:
--------------------------------------------------------------------------------
1 | body{margin:0}a{color:#00c176}a:active,a:focus,a:hover{color:#88c100}.example{margin:50px auto;width:80%}.example-list>li{padding:10px}.footer,.header{padding:5px;background-color:#00c176;color:#fff;text-align:center}.pull-carousel .pull-refresh{top:-50px;padding-bottom:10px}.carousel-scroller .swiper-panel{text-align:center;height:200px;font-size:28px;background:#f0f0f0}.pull-header{top:0}.pull-footer,.pull-header{position:absolute;z-index:2;left:0;right:0}.pull-footer{bottom:0}.pull-body,.pull-wrapper{position:absolute;top:0;bottom:0;left:0;right:0}.pull-wrapper{z-index:1;overflow:hidden}.pull-scroller{z-index:1;user-select:none;text-size-adjust:none;-webkit-tap-highlight-color:transparent;-webkit-touch-callout:none}.pull-refresh,.pull-scroller{position:absolute;left:0;right:0}.pull-refresh{top:-40px;display:block;overflow:hidden}.pull-refresh-icon-wrapper{position:relative;width:40px;margin:auto;text-align:center;height:25px}.pull-refresh-icon{position:absolute;top:0;left:12px;width:14px;height:25px;background-size:contain;background-position:50%;background-repeat:no-repeat;background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyMCIgaGVpZ2h0PSIyMCIgdmlld0JveD0iMCAwIDIwIDIwIj48cGF0aCBkPSJNOS44NTQgMTkuMzU0bDYtNmEuNS41IDAgMCAwLS43MDctLjcwN0wxMCAxNy43OTNWMS41YS41LjUgMCAwIDAtMSAwdjE2LjI5M2wtNS4xNDUtNS4xNDZhLjUuNSAwIDAgMC0uNzA3LjcwOGw2IDZhLjUuNSAwIDAgMCAuNzA3IDB6Ii8+PC9zdmc+)}.pull-refresh-icon.rotate{transform:translateZ(0) rotate(180deg)}.pull-refresh-icon.loading{animation:pull-loading .8s infinite linear;background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI5MzIiIGhlaWdodD0iOTMyIiB2aWV3Qm94PSIwIDAgOTMyIDkzMiI+PHBhdGggZD0iTTQ2NiA5MzJjLTEyNC40NzMgMC0yNDEuNDk1LTQ4LjQ3My0zMjkuNTEzLTEzNi40ODdDNDguNDczIDcwNy40OTUgMCA1OTAuNDczIDAgNDY2YzAtODguMTM4IDI0Ljc0LTE3My45NjIgNzEuNTQ0LTI0OC4xOTIgNDUuNTA4LTcyLjE3MiAxMDkuODIzLTEzMC40OSAxODUuOTk2LTE2OC42NTJsMzkuMTM3IDc4LjEyQzIzNC43NTIgMTU4LjMgMTgyLjQ2IDIwNS43MiAxNDUuNDU1IDI2NC40MSAxMDcuNDYgMzI0LjY3IDg3LjM3NSAzOTQuMzc4IDg3LjM3NSA0NjZjMCAyMDguNzc0IDE2OS44NTMgMzc4LjYyNiAzNzguNjI2IDM3OC42MjZTODQ0LjYyNyA2NzQuNzc0IDg0NC42MjcgNDY2YzAtNzEuNjItMjAuMDg0LTE0MS4zMy01OC4wNzctMjAxLjU5LTM3LjAwOC01OC42OS04OS4zLTEwNi4xMS0xNTEuMjIzLTEzNy4xMzNsMzkuMTM3LTc4LjEyYzc2LjE3MyAzOC4xNiAxNDAuNDkgOTYuNDggMTg1Ljk5NiAxNjguNjVDOTA3LjI2MiAyOTIuMDQgOTMyLjAwMiAzNzcuODY0IDkzMi4wMDIgNDY2YzAgMTI0LjQ3My00OC40NzMgMjQxLjQ5NS0xMzYuNDg3IDMyOS41MTNDNzA3LjQ5NyA4ODMuNTI3IDU5MC40NzUgOTMyIDQ2Ni4wMDIgOTMyeiIvPjwvc3ZnPg==)}@keyframes pull-loading{0%{transform:translateZ(0) rotate(0deg)}to{transform:translateZ(0) rotate(1turn)}}.pull-refresh-text{color:#666;font-size:12px;text-align:center}.pull-load-more{position:absolute;bottom:5px;left:0;right:0;visibility:hidden}.pull-load-more-icon{height:20px;width:20px;margin:0 auto;color:#666;background-size:contain;background:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyMCIgaGVpZ2h0PSIyMCIgdmlld0JveD0iMCAwIDIwIDIwIj48cGF0aCBkPSJNOS44NTQgMTkuMzU0bDYtNmEuNS41IDAgMCAwLS43MDctLjcwN0wxMCAxNy43OTNWMS41YS41LjUgMCAwIDAtMSAwdjE2LjI5M2wtNS4xNDUtNS4xNDZhLjUuNSAwIDAgMC0uNzA3LjcwOGw2IDZhLjUuNSAwIDAgMCAuNzA3IDB6Ii8+PC9zdmc+) 50% no-repeat;transform:rotate(180deg)}.pull-load-more-icon.hide{display:none}.pull-load-more-icon.rotate{transform:rotate(0deg)}.pull-load-more-icon.loading{display:block;background:transparent url("data:image/svg+xml;charset=utf-8,%3Csvg viewBox='0 0 120 120' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink'%3E%3Cdefs%3E%3Cpath id='a' stroke='%236c6c6c' stroke-width='11' stroke-linecap='round' d='M60 7v20'/%3E%3C/defs%3E%3Cuse xlink:href='%23a' opacity='.27'/%3E%3Cuse xlink:href='%23a' opacity='.27' transform='rotate(30 60 60)'/%3E%3Cuse xlink:href='%23a' opacity='.27' transform='rotate(60 60 60)'/%3E%3Cuse xlink:href='%23a' opacity='.27' transform='rotate(90 60 60)'/%3E%3Cuse xlink:href='%23a' opacity='.27' transform='rotate(120 60 60)'/%3E%3Cuse xlink:href='%23a' opacity='.27' transform='rotate(150 60 60)'/%3E%3Cuse xlink:href='%23a' opacity='.37' transform='rotate(180 60 60)'/%3E%3Cuse xlink:href='%23a' opacity='.46' transform='rotate(210 60 60)'/%3E%3Cuse xlink:href='%23a' opacity='.56' transform='rotate(240 60 60)'/%3E%3Cuse xlink:href='%23a' opacity='.66' transform='rotate(270 60 60)'/%3E%3Cuse xlink:href='%23a' opacity='.75' transform='rotate(300 60 60)'/%3E%3Cuse xlink:href='%23a' opacity='.85' transform='rotate(330 60 60)'/%3E%3C/svg%3E") 50% no-repeat;background-size:20px 20px;animation:pull-load-more 1s step-end infinite}.pull-load-more-text{font-size:12px;margin-top:5px;color:#666;text-align:center}@keyframes pull-load-more{0%{transform:rotate(0deg)}8.33333333%{transform:rotate(30deg)}16.66666667%{transform:rotate(60deg)}25%{transform:rotate(90deg)}33.33333333%{transform:rotate(120deg)}41.66666667%{transform:rotate(150deg)}50%{transform:rotate(180deg)}58.33333333%{transform:rotate(210deg)}66.66666667%{transform:rotate(240deg)}75%{transform:rotate(270deg)}83.33333333%{transform:rotate(300deg)}91.66666667%{transform:rotate(330deg)}to{transform:rotate(1turn)}}
2 | /*# sourceMappingURL=header-footer.aa697a21f7857d4c1560.css.map*/
--------------------------------------------------------------------------------
/examples-dist/css/header-footer.aa697a21f7857d4c1560.css.map:
--------------------------------------------------------------------------------
1 | {"version":3,"sources":[],"names":[],"mappings":"","file":"css/header-footer.aa697a21f7857d4c1560.css","sourceRoot":""}
--------------------------------------------------------------------------------
/examples-dist/css/index.36fbdaffa0fdd50aa664.css:
--------------------------------------------------------------------------------
1 | body{margin:0}a{color:#00c176}a:active,a:focus,a:hover{color:#88c100}.example{margin:50px auto;width:80%}.example-list>li{padding:10px}.footer,.header{padding:5px;background-color:#00c176;color:#fff;text-align:center}.pull-carousel .pull-refresh{top:-50px;padding-bottom:10px}.carousel-scroller .swiper-panel{text-align:center;height:200px;font-size:28px;background:#f0f0f0}
2 | /*# sourceMappingURL=index.36fbdaffa0fdd50aa664.css.map*/
--------------------------------------------------------------------------------
/examples-dist/css/index.36fbdaffa0fdd50aa664.css.map:
--------------------------------------------------------------------------------
1 | {"version":3,"sources":[],"names":[],"mappings":"","file":"css/index.36fbdaffa0fdd50aa664.css","sourceRoot":""}
--------------------------------------------------------------------------------
/examples-dist/css/pull-carousel.168d7ef0a8deaade6c73.css:
--------------------------------------------------------------------------------
1 | body{margin:0}a{color:#00c176}a:active,a:focus,a:hover{color:#88c100}.example{margin:50px auto;width:80%}.example-list>li{padding:10px}.footer,.header{padding:5px;background-color:#00c176;color:#fff;text-align:center}.pull-carousel .pull-refresh{top:-50px;padding-bottom:10px}.carousel-scroller .swiper-panel{text-align:center;height:200px;font-size:28px;background:#f0f0f0}.pull-header{top:0}.pull-footer,.pull-header{position:absolute;z-index:2;left:0;right:0}.pull-footer{bottom:0}.pull-body,.pull-wrapper{position:absolute;top:0;bottom:0;left:0;right:0}.pull-wrapper{z-index:1;overflow:hidden}.pull-scroller{z-index:1;user-select:none;text-size-adjust:none;-webkit-tap-highlight-color:transparent;-webkit-touch-callout:none}.pull-refresh,.pull-scroller{position:absolute;left:0;right:0}.pull-refresh{top:-40px;display:block;overflow:hidden}.pull-refresh-icon-wrapper{position:relative;width:40px;margin:auto;text-align:center;height:25px}.pull-refresh-icon{position:absolute;top:0;left:12px;width:14px;height:25px;background-size:contain;background-position:50%;background-repeat:no-repeat;background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyMCIgaGVpZ2h0PSIyMCIgdmlld0JveD0iMCAwIDIwIDIwIj48cGF0aCBkPSJNOS44NTQgMTkuMzU0bDYtNmEuNS41IDAgMCAwLS43MDctLjcwN0wxMCAxNy43OTNWMS41YS41LjUgMCAwIDAtMSAwdjE2LjI5M2wtNS4xNDUtNS4xNDZhLjUuNSAwIDAgMC0uNzA3LjcwOGw2IDZhLjUuNSAwIDAgMCAuNzA3IDB6Ii8+PC9zdmc+)}.pull-refresh-icon.rotate{transform:translateZ(0) rotate(180deg)}.pull-refresh-icon.loading{animation:pull-loading .8s infinite linear;background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI5MzIiIGhlaWdodD0iOTMyIiB2aWV3Qm94PSIwIDAgOTMyIDkzMiI+PHBhdGggZD0iTTQ2NiA5MzJjLTEyNC40NzMgMC0yNDEuNDk1LTQ4LjQ3My0zMjkuNTEzLTEzNi40ODdDNDguNDczIDcwNy40OTUgMCA1OTAuNDczIDAgNDY2YzAtODguMTM4IDI0Ljc0LTE3My45NjIgNzEuNTQ0LTI0OC4xOTIgNDUuNTA4LTcyLjE3MiAxMDkuODIzLTEzMC40OSAxODUuOTk2LTE2OC42NTJsMzkuMTM3IDc4LjEyQzIzNC43NTIgMTU4LjMgMTgyLjQ2IDIwNS43MiAxNDUuNDU1IDI2NC40MSAxMDcuNDYgMzI0LjY3IDg3LjM3NSAzOTQuMzc4IDg3LjM3NSA0NjZjMCAyMDguNzc0IDE2OS44NTMgMzc4LjYyNiAzNzguNjI2IDM3OC42MjZTODQ0LjYyNyA2NzQuNzc0IDg0NC42MjcgNDY2YzAtNzEuNjItMjAuMDg0LTE0MS4zMy01OC4wNzctMjAxLjU5LTM3LjAwOC01OC42OS04OS4zLTEwNi4xMS0xNTEuMjIzLTEzNy4xMzNsMzkuMTM3LTc4LjEyYzc2LjE3MyAzOC4xNiAxNDAuNDkgOTYuNDggMTg1Ljk5NiAxNjguNjVDOTA3LjI2MiAyOTIuMDQgOTMyLjAwMiAzNzcuODY0IDkzMi4wMDIgNDY2YzAgMTI0LjQ3My00OC40NzMgMjQxLjQ5NS0xMzYuNDg3IDMyOS41MTNDNzA3LjQ5NyA4ODMuNTI3IDU5MC40NzUgOTMyIDQ2Ni4wMDIgOTMyeiIvPjwvc3ZnPg==)}@keyframes pull-loading{0%{transform:translateZ(0) rotate(0deg)}to{transform:translateZ(0) rotate(1turn)}}.pull-refresh-text{color:#666;font-size:12px;text-align:center}.pull-load-more{position:absolute;bottom:5px;left:0;right:0;visibility:hidden}.pull-load-more-icon{height:20px;width:20px;margin:0 auto;color:#666;background-size:contain;background:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyMCIgaGVpZ2h0PSIyMCIgdmlld0JveD0iMCAwIDIwIDIwIj48cGF0aCBkPSJNOS44NTQgMTkuMzU0bDYtNmEuNS41IDAgMCAwLS43MDctLjcwN0wxMCAxNy43OTNWMS41YS41LjUgMCAwIDAtMSAwdjE2LjI5M2wtNS4xNDUtNS4xNDZhLjUuNSAwIDAgMC0uNzA3LjcwOGw2IDZhLjUuNSAwIDAgMCAuNzA3IDB6Ii8+PC9zdmc+) 50% no-repeat;transform:rotate(180deg)}.pull-load-more-icon.hide{display:none}.pull-load-more-icon.rotate{transform:rotate(0deg)}.pull-load-more-icon.loading{display:block;background:transparent url("data:image/svg+xml;charset=utf-8,%3Csvg viewBox='0 0 120 120' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink'%3E%3Cdefs%3E%3Cpath id='a' stroke='%236c6c6c' stroke-width='11' stroke-linecap='round' d='M60 7v20'/%3E%3C/defs%3E%3Cuse xlink:href='%23a' opacity='.27'/%3E%3Cuse xlink:href='%23a' opacity='.27' transform='rotate(30 60 60)'/%3E%3Cuse xlink:href='%23a' opacity='.27' transform='rotate(60 60 60)'/%3E%3Cuse xlink:href='%23a' opacity='.27' transform='rotate(90 60 60)'/%3E%3Cuse xlink:href='%23a' opacity='.27' transform='rotate(120 60 60)'/%3E%3Cuse xlink:href='%23a' opacity='.27' transform='rotate(150 60 60)'/%3E%3Cuse xlink:href='%23a' opacity='.37' transform='rotate(180 60 60)'/%3E%3Cuse xlink:href='%23a' opacity='.46' transform='rotate(210 60 60)'/%3E%3Cuse xlink:href='%23a' opacity='.56' transform='rotate(240 60 60)'/%3E%3Cuse xlink:href='%23a' opacity='.66' transform='rotate(270 60 60)'/%3E%3Cuse xlink:href='%23a' opacity='.75' transform='rotate(300 60 60)'/%3E%3Cuse xlink:href='%23a' opacity='.85' transform='rotate(330 60 60)'/%3E%3C/svg%3E") 50% no-repeat;background-size:20px 20px;animation:pull-load-more 1s step-end infinite}.pull-load-more-text{font-size:12px;margin-top:5px;color:#666;text-align:center}@keyframes pull-load-more{0%{transform:rotate(0deg)}8.33333333%{transform:rotate(30deg)}16.66666667%{transform:rotate(60deg)}25%{transform:rotate(90deg)}33.33333333%{transform:rotate(120deg)}41.66666667%{transform:rotate(150deg)}50%{transform:rotate(180deg)}58.33333333%{transform:rotate(210deg)}66.66666667%{transform:rotate(240deg)}75%{transform:rotate(270deg)}83.33333333%{transform:rotate(300deg)}91.66666667%{transform:rotate(330deg)}to{transform:rotate(1turn)}}.carousel-wrapper{margin:0 auto;overflow:hidden;position:relative}.carousel-scroller{position:relative;font-size:0;user-select:none;text-size-adjust:none;-webkit-tap-highlight-color:transparent;-webkit-touch-callout:none}.carousel-scroller .swiper-panel{float:left}.carousel-tabs-menu{display:flex}.carousel-tabs-menu .carousel-tabs-item{flex:1;text-align:center;line-height:2.2;bordr-bottom:2px solid transparent}.carousel-tabs-menu .active{color:#cf121b;border-bottom:2px solid #cf121b}.carousel-nav{position:absolute;bottom:6px;right:10px}.carousel-nav>a{display:inline-block;background-color:#fff;cursor:pointer;width:6px;height:6px;border-radius:5px;border:1px solid gray;transition:all .5s ease-in}.carousel-nav>a.active{background-color:#ffd800;width:10px}
2 | /*# sourceMappingURL=pull-carousel.168d7ef0a8deaade6c73.css.map*/
--------------------------------------------------------------------------------
/examples-dist/css/pull-carousel.168d7ef0a8deaade6c73.css.map:
--------------------------------------------------------------------------------
1 | {"version":3,"sources":[],"names":[],"mappings":"","file":"css/pull-carousel.168d7ef0a8deaade6c73.css","sourceRoot":""}
--------------------------------------------------------------------------------
/examples-dist/css/pull-carousel2.d50988f2dea6085f1002.css:
--------------------------------------------------------------------------------
1 | body{margin:0}a{color:#00c176}a:active,a:focus,a:hover{color:#88c100}.example{margin:50px auto;width:80%}.example-list>li{padding:10px}.footer,.header{padding:5px;background-color:#00c176;color:#fff;text-align:center}.pull-carousel .pull-refresh{top:-50px;padding-bottom:10px}.carousel-scroller .swiper-panel{text-align:center;height:200px;font-size:28px;background:#f0f0f0}.pull-header{top:0}.pull-footer,.pull-header{position:absolute;z-index:2;left:0;right:0}.pull-footer{bottom:0}.pull-body,.pull-wrapper{position:absolute;top:0;bottom:0;left:0;right:0}.pull-wrapper{z-index:1;overflow:hidden}.pull-scroller{z-index:1;user-select:none;text-size-adjust:none;-webkit-tap-highlight-color:transparent;-webkit-touch-callout:none}.pull-refresh,.pull-scroller{position:absolute;left:0;right:0}.pull-refresh{top:-40px;display:block;overflow:hidden}.pull-refresh-icon-wrapper{position:relative;width:40px;margin:auto;text-align:center;height:25px}.pull-refresh-icon{position:absolute;top:0;left:12px;width:14px;height:25px;background-size:contain;background-position:50%;background-repeat:no-repeat;background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyMCIgaGVpZ2h0PSIyMCIgdmlld0JveD0iMCAwIDIwIDIwIj48cGF0aCBkPSJNOS44NTQgMTkuMzU0bDYtNmEuNS41IDAgMCAwLS43MDctLjcwN0wxMCAxNy43OTNWMS41YS41LjUgMCAwIDAtMSAwdjE2LjI5M2wtNS4xNDUtNS4xNDZhLjUuNSAwIDAgMC0uNzA3LjcwOGw2IDZhLjUuNSAwIDAgMCAuNzA3IDB6Ii8+PC9zdmc+)}.pull-refresh-icon.rotate{transform:translateZ(0) rotate(180deg)}.pull-refresh-icon.loading{animation:pull-loading .8s infinite linear;background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI5MzIiIGhlaWdodD0iOTMyIiB2aWV3Qm94PSIwIDAgOTMyIDkzMiI+PHBhdGggZD0iTTQ2NiA5MzJjLTEyNC40NzMgMC0yNDEuNDk1LTQ4LjQ3My0zMjkuNTEzLTEzNi40ODdDNDguNDczIDcwNy40OTUgMCA1OTAuNDczIDAgNDY2YzAtODguMTM4IDI0Ljc0LTE3My45NjIgNzEuNTQ0LTI0OC4xOTIgNDUuNTA4LTcyLjE3MiAxMDkuODIzLTEzMC40OSAxODUuOTk2LTE2OC42NTJsMzkuMTM3IDc4LjEyQzIzNC43NTIgMTU4LjMgMTgyLjQ2IDIwNS43MiAxNDUuNDU1IDI2NC40MSAxMDcuNDYgMzI0LjY3IDg3LjM3NSAzOTQuMzc4IDg3LjM3NSA0NjZjMCAyMDguNzc0IDE2OS44NTMgMzc4LjYyNiAzNzguNjI2IDM3OC42MjZTODQ0LjYyNyA2NzQuNzc0IDg0NC42MjcgNDY2YzAtNzEuNjItMjAuMDg0LTE0MS4zMy01OC4wNzctMjAxLjU5LTM3LjAwOC01OC42OS04OS4zLTEwNi4xMS0xNTEuMjIzLTEzNy4xMzNsMzkuMTM3LTc4LjEyYzc2LjE3MyAzOC4xNiAxNDAuNDkgOTYuNDggMTg1Ljk5NiAxNjguNjVDOTA3LjI2MiAyOTIuMDQgOTMyLjAwMiAzNzcuODY0IDkzMi4wMDIgNDY2YzAgMTI0LjQ3My00OC40NzMgMjQxLjQ5NS0xMzYuNDg3IDMyOS41MTNDNzA3LjQ5NyA4ODMuNTI3IDU5MC40NzUgOTMyIDQ2Ni4wMDIgOTMyeiIvPjwvc3ZnPg==)}@keyframes pull-loading{0%{transform:translateZ(0) rotate(0deg)}to{transform:translateZ(0) rotate(1turn)}}.pull-refresh-text{color:#666;font-size:12px;text-align:center}.pull-load-more{position:absolute;bottom:5px;left:0;right:0;visibility:hidden}.pull-load-more-icon{height:20px;width:20px;margin:0 auto;color:#666;background-size:contain;background:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyMCIgaGVpZ2h0PSIyMCIgdmlld0JveD0iMCAwIDIwIDIwIj48cGF0aCBkPSJNOS44NTQgMTkuMzU0bDYtNmEuNS41IDAgMCAwLS43MDctLjcwN0wxMCAxNy43OTNWMS41YS41LjUgMCAwIDAtMSAwdjE2LjI5M2wtNS4xNDUtNS4xNDZhLjUuNSAwIDAgMC0uNzA3LjcwOGw2IDZhLjUuNSAwIDAgMCAuNzA3IDB6Ii8+PC9zdmc+) 50% no-repeat;transform:rotate(180deg)}.pull-load-more-icon.hide{display:none}.pull-load-more-icon.rotate{transform:rotate(0deg)}.pull-load-more-icon.loading{display:block;background:transparent url("data:image/svg+xml;charset=utf-8,%3Csvg viewBox='0 0 120 120' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink'%3E%3Cdefs%3E%3Cpath id='a' stroke='%236c6c6c' stroke-width='11' stroke-linecap='round' d='M60 7v20'/%3E%3C/defs%3E%3Cuse xlink:href='%23a' opacity='.27'/%3E%3Cuse xlink:href='%23a' opacity='.27' transform='rotate(30 60 60)'/%3E%3Cuse xlink:href='%23a' opacity='.27' transform='rotate(60 60 60)'/%3E%3Cuse xlink:href='%23a' opacity='.27' transform='rotate(90 60 60)'/%3E%3Cuse xlink:href='%23a' opacity='.27' transform='rotate(120 60 60)'/%3E%3Cuse xlink:href='%23a' opacity='.27' transform='rotate(150 60 60)'/%3E%3Cuse xlink:href='%23a' opacity='.37' transform='rotate(180 60 60)'/%3E%3Cuse xlink:href='%23a' opacity='.46' transform='rotate(210 60 60)'/%3E%3Cuse xlink:href='%23a' opacity='.56' transform='rotate(240 60 60)'/%3E%3Cuse xlink:href='%23a' opacity='.66' transform='rotate(270 60 60)'/%3E%3Cuse xlink:href='%23a' opacity='.75' transform='rotate(300 60 60)'/%3E%3Cuse xlink:href='%23a' opacity='.85' transform='rotate(330 60 60)'/%3E%3C/svg%3E") 50% no-repeat;background-size:20px 20px;animation:pull-load-more 1s step-end infinite}.pull-load-more-text{font-size:12px;margin-top:5px;color:#666;text-align:center}@keyframes pull-load-more{0%{transform:rotate(0deg)}8.33333333%{transform:rotate(30deg)}16.66666667%{transform:rotate(60deg)}25%{transform:rotate(90deg)}33.33333333%{transform:rotate(120deg)}41.66666667%{transform:rotate(150deg)}50%{transform:rotate(180deg)}58.33333333%{transform:rotate(210deg)}66.66666667%{transform:rotate(240deg)}75%{transform:rotate(270deg)}83.33333333%{transform:rotate(300deg)}91.66666667%{transform:rotate(330deg)}to{transform:rotate(1turn)}}.carousel-wrapper{margin:0 auto;overflow:hidden;position:relative}.carousel-scroller{position:relative;font-size:0;user-select:none;text-size-adjust:none;-webkit-tap-highlight-color:transparent;-webkit-touch-callout:none}.carousel-scroller .swiper-panel{float:left}.carousel-tabs-menu{display:flex}.carousel-tabs-menu .carousel-tabs-item{flex:1;text-align:center;line-height:2.2;bordr-bottom:2px solid transparent}.carousel-tabs-menu .active{color:#cf121b;border-bottom:2px solid #cf121b}.carousel-nav{position:absolute;bottom:6px;right:10px}.carousel-nav>a{display:inline-block;background-color:#fff;cursor:pointer;width:6px;height:6px;border-radius:5px;border:1px solid gray;transition:all .5s ease-in}.carousel-nav>a.active{background-color:#ffd800;width:10px}
2 | /*# sourceMappingURL=pull-carousel2.d50988f2dea6085f1002.css.map*/
--------------------------------------------------------------------------------
/examples-dist/css/pull-carousel2.d50988f2dea6085f1002.css.map:
--------------------------------------------------------------------------------
1 | {"version":3,"sources":[],"names":[],"mappings":"","file":"css/pull-carousel2.d50988f2dea6085f1002.css","sourceRoot":""}
--------------------------------------------------------------------------------
/examples-dist/css/pull.1cdce4fcd519ccb16612.css:
--------------------------------------------------------------------------------
1 | body{margin:0}a{color:#00c176}a:active,a:focus,a:hover{color:#88c100}.example{margin:50px auto;width:80%}.example-list>li{padding:10px}.footer,.header{padding:5px;background-color:#00c176;color:#fff;text-align:center}.pull-carousel .pull-refresh{top:-50px;padding-bottom:10px}.carousel-scroller .swiper-panel{text-align:center;height:200px;font-size:28px;background:#f0f0f0}.pull-header{top:0}.pull-footer,.pull-header{position:absolute;z-index:2;left:0;right:0}.pull-footer{bottom:0}.pull-body,.pull-wrapper{position:absolute;top:0;bottom:0;left:0;right:0}.pull-wrapper{z-index:1;overflow:hidden}.pull-scroller{z-index:1;user-select:none;text-size-adjust:none;-webkit-tap-highlight-color:transparent;-webkit-touch-callout:none}.pull-refresh,.pull-scroller{position:absolute;left:0;right:0}.pull-refresh{top:-40px;display:block;overflow:hidden}.pull-refresh-icon-wrapper{position:relative;width:40px;margin:auto;text-align:center;height:25px}.pull-refresh-icon{position:absolute;top:0;left:12px;width:14px;height:25px;background-size:contain;background-position:50%;background-repeat:no-repeat;background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyMCIgaGVpZ2h0PSIyMCIgdmlld0JveD0iMCAwIDIwIDIwIj48cGF0aCBkPSJNOS44NTQgMTkuMzU0bDYtNmEuNS41IDAgMCAwLS43MDctLjcwN0wxMCAxNy43OTNWMS41YS41LjUgMCAwIDAtMSAwdjE2LjI5M2wtNS4xNDUtNS4xNDZhLjUuNSAwIDAgMC0uNzA3LjcwOGw2IDZhLjUuNSAwIDAgMCAuNzA3IDB6Ii8+PC9zdmc+)}.pull-refresh-icon.rotate{transform:translateZ(0) rotate(180deg)}.pull-refresh-icon.loading{animation:pull-loading .8s infinite linear;background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI5MzIiIGhlaWdodD0iOTMyIiB2aWV3Qm94PSIwIDAgOTMyIDkzMiI+PHBhdGggZD0iTTQ2NiA5MzJjLTEyNC40NzMgMC0yNDEuNDk1LTQ4LjQ3My0zMjkuNTEzLTEzNi40ODdDNDguNDczIDcwNy40OTUgMCA1OTAuNDczIDAgNDY2YzAtODguMTM4IDI0Ljc0LTE3My45NjIgNzEuNTQ0LTI0OC4xOTIgNDUuNTA4LTcyLjE3MiAxMDkuODIzLTEzMC40OSAxODUuOTk2LTE2OC42NTJsMzkuMTM3IDc4LjEyQzIzNC43NTIgMTU4LjMgMTgyLjQ2IDIwNS43MiAxNDUuNDU1IDI2NC40MSAxMDcuNDYgMzI0LjY3IDg3LjM3NSAzOTQuMzc4IDg3LjM3NSA0NjZjMCAyMDguNzc0IDE2OS44NTMgMzc4LjYyNiAzNzguNjI2IDM3OC42MjZTODQ0LjYyNyA2NzQuNzc0IDg0NC42MjcgNDY2YzAtNzEuNjItMjAuMDg0LTE0MS4zMy01OC4wNzctMjAxLjU5LTM3LjAwOC01OC42OS04OS4zLTEwNi4xMS0xNTEuMjIzLTEzNy4xMzNsMzkuMTM3LTc4LjEyYzc2LjE3MyAzOC4xNiAxNDAuNDkgOTYuNDggMTg1Ljk5NiAxNjguNjVDOTA3LjI2MiAyOTIuMDQgOTMyLjAwMiAzNzcuODY0IDkzMi4wMDIgNDY2YzAgMTI0LjQ3My00OC40NzMgMjQxLjQ5NS0xMzYuNDg3IDMyOS41MTNDNzA3LjQ5NyA4ODMuNTI3IDU5MC40NzUgOTMyIDQ2Ni4wMDIgOTMyeiIvPjwvc3ZnPg==)}@keyframes pull-loading{0%{transform:translateZ(0) rotate(0deg)}to{transform:translateZ(0) rotate(1turn)}}.pull-refresh-text{color:#666;font-size:12px;text-align:center}.pull-load-more{position:absolute;bottom:5px;left:0;right:0;visibility:hidden}.pull-load-more-icon{height:20px;width:20px;margin:0 auto;color:#666;background-size:contain;background:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyMCIgaGVpZ2h0PSIyMCIgdmlld0JveD0iMCAwIDIwIDIwIj48cGF0aCBkPSJNOS44NTQgMTkuMzU0bDYtNmEuNS41IDAgMCAwLS43MDctLjcwN0wxMCAxNy43OTNWMS41YS41LjUgMCAwIDAtMSAwdjE2LjI5M2wtNS4xNDUtNS4xNDZhLjUuNSAwIDAgMC0uNzA3LjcwOGw2IDZhLjUuNSAwIDAgMCAuNzA3IDB6Ii8+PC9zdmc+) 50% no-repeat;transform:rotate(180deg)}.pull-load-more-icon.hide{display:none}.pull-load-more-icon.rotate{transform:rotate(0deg)}.pull-load-more-icon.loading{display:block;background:transparent url("data:image/svg+xml;charset=utf-8,%3Csvg viewBox='0 0 120 120' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink'%3E%3Cdefs%3E%3Cpath id='a' stroke='%236c6c6c' stroke-width='11' stroke-linecap='round' d='M60 7v20'/%3E%3C/defs%3E%3Cuse xlink:href='%23a' opacity='.27'/%3E%3Cuse xlink:href='%23a' opacity='.27' transform='rotate(30 60 60)'/%3E%3Cuse xlink:href='%23a' opacity='.27' transform='rotate(60 60 60)'/%3E%3Cuse xlink:href='%23a' opacity='.27' transform='rotate(90 60 60)'/%3E%3Cuse xlink:href='%23a' opacity='.27' transform='rotate(120 60 60)'/%3E%3Cuse xlink:href='%23a' opacity='.27' transform='rotate(150 60 60)'/%3E%3Cuse xlink:href='%23a' opacity='.37' transform='rotate(180 60 60)'/%3E%3Cuse xlink:href='%23a' opacity='.46' transform='rotate(210 60 60)'/%3E%3Cuse xlink:href='%23a' opacity='.56' transform='rotate(240 60 60)'/%3E%3Cuse xlink:href='%23a' opacity='.66' transform='rotate(270 60 60)'/%3E%3Cuse xlink:href='%23a' opacity='.75' transform='rotate(300 60 60)'/%3E%3Cuse xlink:href='%23a' opacity='.85' transform='rotate(330 60 60)'/%3E%3C/svg%3E") 50% no-repeat;background-size:20px 20px;animation:pull-load-more 1s step-end infinite}.pull-load-more-text{font-size:12px;margin-top:5px;color:#666;text-align:center}@keyframes pull-load-more{0%{transform:rotate(0deg)}8.33333333%{transform:rotate(30deg)}16.66666667%{transform:rotate(60deg)}25%{transform:rotate(90deg)}33.33333333%{transform:rotate(120deg)}41.66666667%{transform:rotate(150deg)}50%{transform:rotate(180deg)}58.33333333%{transform:rotate(210deg)}66.66666667%{transform:rotate(240deg)}75%{transform:rotate(270deg)}83.33333333%{transform:rotate(300deg)}91.66666667%{transform:rotate(330deg)}to{transform:rotate(1turn)}}
2 | /*# sourceMappingURL=pull.1cdce4fcd519ccb16612.css.map*/
--------------------------------------------------------------------------------
/examples-dist/css/pull.1cdce4fcd519ccb16612.css.map:
--------------------------------------------------------------------------------
1 | {"version":3,"sources":[],"names":[],"mappings":"","file":"css/pull.1cdce4fcd519ccb16612.css","sourceRoot":""}
--------------------------------------------------------------------------------
/examples-dist/css/simple.cd5bd1d575b7cc335111.css:
--------------------------------------------------------------------------------
1 | body{margin:0}a{color:#00c176}a:active,a:focus,a:hover{color:#88c100}.example{margin:50px auto;width:80%}.example-list>li{padding:10px}.footer,.header{padding:5px;background-color:#00c176;color:#fff;text-align:center}.pull-carousel .pull-refresh{top:-50px;padding-bottom:10px}.carousel-scroller .swiper-panel{text-align:center;height:200px;font-size:28px;background:#f0f0f0}.alloy-wrapper{top:0;bottom:0;overflow:hidden}.alloy-scroller,.alloy-wrapper{position:absolute;z-index:1;left:0;right:0}.alloy-scroller{user-select:none;text-size-adjust:none;-webkit-tap-highlight-color:transparent;-webkit-touch-callout:none}
2 | /*# sourceMappingURL=simple.cd5bd1d575b7cc335111.css.map*/
--------------------------------------------------------------------------------
/examples-dist/css/simple.cd5bd1d575b7cc335111.css.map:
--------------------------------------------------------------------------------
1 | {"version":3,"sources":[],"names":[],"mappings":"","file":"css/simple.cd5bd1d575b7cc335111.css","sourceRoot":""}
--------------------------------------------------------------------------------
/examples-dist/css/tabs-carousel.65b224ba332c3c8c1bb4.css:
--------------------------------------------------------------------------------
1 | body{margin:0}a{color:#00c176}a:active,a:focus,a:hover{color:#88c100}.example{margin:50px auto;width:80%}.example-list>li{padding:10px}.footer,.header{padding:5px;background-color:#00c176;color:#fff;text-align:center}.pull-carousel .pull-refresh{top:-50px;padding-bottom:10px}.carousel-scroller .swiper-panel{text-align:center;height:200px;font-size:28px;background:#f0f0f0}.carousel-wrapper{margin:0 auto;overflow:hidden;position:relative}.carousel-scroller{position:relative;font-size:0;user-select:none;text-size-adjust:none;-webkit-tap-highlight-color:transparent;-webkit-touch-callout:none}.carousel-scroller .swiper-panel{float:left}.carousel-tabs-menu{display:flex}.carousel-tabs-menu .carousel-tabs-item{flex:1;text-align:center;line-height:2.2;bordr-bottom:2px solid transparent}.carousel-tabs-menu .active{color:#cf121b;border-bottom:2px solid #cf121b}.carousel-nav{position:absolute;bottom:6px;right:10px}.carousel-nav>a{display:inline-block;background-color:#fff;cursor:pointer;width:6px;height:6px;border-radius:5px;border:1px solid gray;transition:all .5s ease-in}.carousel-nav>a.active{background-color:#ffd800;width:10px}
2 | /*# sourceMappingURL=tabs-carousel.65b224ba332c3c8c1bb4.css.map*/
--------------------------------------------------------------------------------
/examples-dist/css/tabs-carousel.65b224ba332c3c8c1bb4.css.map:
--------------------------------------------------------------------------------
1 | {"version":3,"sources":[],"names":[],"mappings":"","file":"css/tabs-carousel.65b224ba332c3c8c1bb4.css","sourceRoot":""}
--------------------------------------------------------------------------------
/examples-dist/header-footer.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 带头部和底部的下拉刷新,上拉加载更多
5 |
6 |
8 |
9 |
24 |
25 |
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/examples-dist/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | React AlloyTouch 例子
5 |
6 |
8 |
9 |
24 |
25 |
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/examples-dist/pull-carousel.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 下拉刷新中包含轮播图
5 |
6 |
8 |
9 |
24 |
25 |
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/examples-dist/pull-carousel2.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 下拉刷新中包含轮播图2
5 |
6 |
8 |
9 |
24 |
25 |
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/examples-dist/pull.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 下拉刷新,上拉加载更多
5 |
6 |
8 |
9 |
24 |
25 |
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/examples-dist/simple.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | React AlloyTouch 简单例子
5 |
6 |
8 |
9 |
24 |
25 |
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/examples-dist/tabs-carousel.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 自定义轮播内容+tabs
5 |
6 |
8 |
9 |
24 |
25 |
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/examples/carousel.js:
--------------------------------------------------------------------------------
1 | import React, {Component} from 'react';
2 | import {render} from 'react-dom';
3 | import injectTapEventPlugin from 'react-tap-event-plugin';
4 | import ReactCarousel from '../js/ReactCarousel';
5 | import '../sass/carousel.scss';
6 | import './sass/example.scss';
7 |
8 | // 初始化 tapEvent 事件, 移动端
9 | injectTapEventPlugin();
10 |
11 | const ReactCarouselExample = () => {
12 |
13 | const items = [{
14 | image: 'http://alloyteam.github.io/AlloyTouch/example/asset/ci1.jpg',
15 | link: 'http://jd.com'
16 | }, {
17 | image: 'http://alloyteam.github.io/AlloyTouch/example/asset/ci2.jpg',
18 | }, {
19 | image: 'http://alloyteam.github.io/AlloyTouch/example/asset/ci3.jpg',
20 | link: 'http://jd.com'
21 | }, {
22 | image: 'http://alloyteam.github.io/AlloyTouch/example/asset/ci4.jpg'
23 | }];
24 |
25 | const events = {
26 | onTouchTap: () => {
27 | console.info('这是个测试!');
28 | }
29 | };
30 |
31 | return (
32 |
33 | );
34 | };
35 |
36 | render(
37 | , document.getElementById('layout')
38 | );
39 |
--------------------------------------------------------------------------------
/examples/header-footer.js:
--------------------------------------------------------------------------------
1 | import React, {Component} from 'react';
2 | import {render} from 'react-dom';
3 | import injectTapEventPlugin from 'react-tap-event-plugin';
4 | import ReactPull from '../js/ReactPull';
5 | import '../sass/pull.scss';
6 | import './sass/example.scss';
7 |
8 | // 初始化 tapEvent 事件, 移动端
9 | injectTapEventPlugin();
10 |
11 | class HeaderFooter extends Component {
12 | constructor(props) {
13 | super(props);
14 | this.state = {
15 | items: 2,
16 | disablePullUp: false
17 | };
18 | }
19 |
20 | refreshCallback = () => {
21 | return new Promise((resolve, reject) => {
22 | setTimeout(() => {
23 | let result = false;
24 | if (Math.random() > 0.2) {
25 | result = true;
26 | }
27 | if (result) {
28 | this.setState({
29 | items: 30,
30 | disablePullUp: false
31 | }, () => {
32 | resolve();
33 | });
34 | } else {
35 | reject(new Error('错误'));
36 | }
37 | }, 1000);
38 | }).then(() => {
39 | console.info('刷新成功!');
40 | }, (error) => {
41 | console.info('刷新失败!');
42 | Promise.error(error);
43 | });
44 | };
45 |
46 | loadMoreCallback = () => {
47 | return new Promise((resolve, reject) => {
48 | setTimeout(() => {
49 | let result = false;
50 | if (Math.random() > 0.2) {
51 | result = true;
52 | }
53 | if (result) {
54 | this.setState({
55 | items: this.state.items + 10,
56 | disablePullUp: this.state.items >= 60
57 | }, () => {
58 | resolve();
59 | });
60 | } else {
61 | reject(new Error('错误'));
62 | }
63 | }, 1000);
64 | }).then(() => {
65 | console.info('加载更多成功!');
66 | }, (error) => {
67 | console.info('加载更多失败!');
68 | Promise.error(error);
69 | });
70 | };
71 |
72 | handleTouchTap = (e) => {
73 | console.info('测试下拉刷新插件是否与 Tap 事件冲突');
74 | };
75 |
76 | render() {
77 | const contents = [];
78 | const {items, disablePullUp} = this.state;
79 |
80 | for (let i = items; i > 0; i--) {
81 | if (i < 10) {
82 | contents.push(这里放置真实显示的DOM内容 {i});
83 | } else {
84 | contents.push(这里放置真实显示的DOM内容 {i});
85 | }
86 | }
87 |
88 | const props = {
89 | refreshCallback: this.refreshCallback,
90 | loadMoreCallback: this.loadMoreCallback,
91 | refresh: true,
92 | loadMore: true,
93 | disablePullUp,
94 | header: (头部
),
95 | footer: (底部
)
96 | };
97 |
98 | return (
99 |
100 |
101 | {contents.map((item) => {
102 | return item;
103 | })}
104 |
105 |
106 | );
107 | }
108 | }
109 |
110 | render(
111 | , document.getElementById('layout')
112 | );
113 |
--------------------------------------------------------------------------------
/examples/index.js:
--------------------------------------------------------------------------------
1 | import React, {Component} from 'react';
2 | import {render} from 'react-dom';
3 | import './sass/example.scss';
4 |
5 | const Index = () => {
6 | return (
7 |
33 | );
34 | };
35 |
36 | render(, document.getElementById('layout'));
37 |
--------------------------------------------------------------------------------
/examples/pull-carousel.js:
--------------------------------------------------------------------------------
1 | import React, {Component} from 'react';
2 | import {render} from 'react-dom';
3 | import injectTapEventPlugin from 'react-tap-event-plugin';
4 | import ReactPull from '../js/ReactPull';
5 | import ReactCarousel from '../js/ReactCarousel';
6 | import '../sass/pull.scss';
7 | import '../sass/carousel.scss';
8 | import './sass/example.scss';
9 |
10 | // 初始化 tapEvent 事件, 移动端
11 | injectTapEventPlugin();
12 |
13 | class ReactPullExample extends Component {
14 | constructor(props) {
15 | super(props);
16 | this.state = {
17 | items: 30,
18 | disablePullUp: false
19 | };
20 | }
21 |
22 | refreshCallback = () => {
23 | return new Promise((resolve, reject) => {
24 | setTimeout(() => {
25 | let result = false;
26 | if (Math.random() > 0.2) {
27 | result = true;
28 | }
29 | if (result) {
30 | this.setState({
31 | items: 30,
32 | disablePullUp: false
33 | }, () => {
34 | resolve();
35 | });
36 | } else {
37 | reject(new Error('错误'));
38 | }
39 | }, 1000);
40 | }).then(() => {
41 | console.info('刷新成功!');
42 | }, () => {
43 | console.info('刷新失败!');
44 | });
45 | };
46 |
47 | loadMoreCallback = () => {
48 | return new Promise((resolve, reject) => {
49 | setTimeout(() => {
50 | let result = false;
51 | if (Math.random() > 0.2) {
52 | result = true;
53 | }
54 | if (result) {
55 | this.setState({
56 | items: this.state.items + 10,
57 | disablePullUp: this.state.items >= 60
58 | }, () => {
59 | resolve();
60 | });
61 | } else {
62 | reject(new Error('错误'));
63 | }
64 | }, 1000);
65 | }).then(() => {
66 | console.info('加载更多成功!');
67 | }, () => {
68 | console.info('加载更多失败!');
69 | });
70 | };
71 |
72 | handleTouchTap = (e) => {
73 | console.info('测试下拉刷新插件是否与 Tap 事件冲突');
74 | };
75 |
76 | render() {
77 | const contents = [];
78 | const {items, disablePullUp} = this.state;
79 |
80 | for (let i = items; i > 0; i--) {
81 | if (i < 10) {
82 | contents.push(这里放置真实显示的DOM内容 {i});
83 | } else {
84 | contents.push(这里放置真实显示的DOM内容 {i});
85 | }
86 | }
87 |
88 | const props = {
89 | refreshCallback: this.refreshCallback,
90 | loadMoreCallback: this.loadMoreCallback,
91 | refresh: true,
92 | loadMore: true,
93 | disablePullUp,
94 | };
95 |
96 | const carouselItems = [{
97 | image: 'http://alloyteam.github.io/AlloyTouch/example/asset/ci1.jpg',
98 | link: 'http://jd.com'
99 | }, {
100 | image: 'http://alloyteam.github.io/AlloyTouch/example/asset/ci2.jpg',
101 | }, {
102 | image: 'http://alloyteam.github.io/AlloyTouch/example/asset/ci3.jpg',
103 | link: 'http://jd.com'
104 | }, {
105 | image: 'http://alloyteam.github.io/AlloyTouch/example/asset/ci4.jpg'
106 | }];
107 |
108 | const header = (
109 |
110 |
111 |
112 | );
113 | return (
114 |
115 |
116 | {contents.map((item) => {
117 | return item;
118 | })}
119 |
120 |
121 | );
122 | }
123 | }
124 |
125 | render(
126 | , document.getElementById('layout')
127 | );
128 |
--------------------------------------------------------------------------------
/examples/pull-carousel2.js:
--------------------------------------------------------------------------------
1 | import React, {Component} from 'react';
2 | import {render} from 'react-dom';
3 | import injectTapEventPlugin from 'react-tap-event-plugin';
4 | import ReactPull from '../js/ReactPull';
5 | import ReactCarousel from '../js/ReactCarousel';
6 | import '../sass/pull.scss';
7 | import '../sass/carousel.scss';
8 | import './sass/example.scss';
9 |
10 | // 初始化 tapEvent 事件, 移动端
11 | injectTapEventPlugin();
12 |
13 | class ReactPullExample extends Component {
14 | constructor(props) {
15 | super(props);
16 | this.state = {
17 | items: 30,
18 | disablePullUp: false
19 | };
20 | }
21 |
22 | refreshCallback = () => {
23 | return new Promise((resolve, reject) => {
24 | setTimeout(() => {
25 | let result = false;
26 | if (Math.random() > 0.2) {
27 | result = true;
28 | }
29 | if (result) {
30 | this.setState({
31 | items: 30,
32 | disablePullUp: false
33 | }, () => {
34 | resolve();
35 | });
36 | } else {
37 | reject(new Error('错误'));
38 | }
39 | }, 1000);
40 | }).then(() => {
41 | console.info('刷新成功!');
42 | }, () => {
43 | console.info('刷新失败!');
44 | });
45 | };
46 |
47 | loadMoreCallback = () => {
48 | return new Promise((resolve, reject) => {
49 | setTimeout(() => {
50 | let result = false;
51 | if (Math.random() > 0.2) {
52 | result = true;
53 | }
54 | if (result) {
55 | this.setState({
56 | items: this.state.items + 10,
57 | disablePullUp: this.state.items >= 60
58 | }, () => {
59 | resolve();
60 | });
61 | } else {
62 | reject(new Error('错误'));
63 | }
64 | }, 1000);
65 | }).then(() => {
66 | console.info('加载更多成功!');
67 | }, () => {
68 | console.info('加载更多失败!');
69 | });
70 | };
71 |
72 | handleTouchTap = (e) => {
73 | console.info('测试下拉刷新插件是否与 Tap 事件冲突');
74 | };
75 |
76 | render() {
77 | const contents = [];
78 | const {items, disablePullUp} = this.state;
79 |
80 | for (let i = items; i > 0; i--) {
81 | if (i < 10) {
82 | contents.push(这里放置真实显示的DOM内容 {i});
83 | } else {
84 | contents.push(这里放置真实显示的DOM内容 {i});
85 | }
86 | }
87 |
88 | const props = {
89 | refreshCallback: this.refreshCallback,
90 | loadMoreCallback: this.loadMoreCallback,
91 | refresh: true,
92 | loadMore: true,
93 | disablePullUp,
94 | };
95 |
96 | const carouselItems = [{
97 | image: 'http://alloyteam.github.io/AlloyTouch/example/asset/ci1.jpg',
98 | link: 'http://jd.com'
99 | }, {
100 | image: 'http://alloyteam.github.io/AlloyTouch/example/asset/ci2.jpg',
101 | }, {
102 | image: 'http://alloyteam.github.io/AlloyTouch/example/asset/ci3.jpg',
103 | link: 'http://jd.com'
104 | }, {
105 | image: 'http://alloyteam.github.io/AlloyTouch/example/asset/ci4.jpg'
106 | }];
107 |
108 | return (
109 |
110 |
111 |
112 |
113 | {contents.map((item) => {
114 | return item;
115 | })}
116 |
117 |
118 |
119 | );
120 | }
121 | }
122 |
123 | render(
124 | , document.getElementById('layout')
125 | );
126 |
--------------------------------------------------------------------------------
/examples/pull.js:
--------------------------------------------------------------------------------
1 | import React, {Component} from 'react';
2 | import {render} from 'react-dom';
3 | import injectTapEventPlugin from 'react-tap-event-plugin';
4 | import ReactPull from '../js/ReactPull';
5 | import '../sass/pull.scss';
6 | import './sass/example.scss';
7 |
8 | // 初始化 tapEvent 事件, 移动端
9 | injectTapEventPlugin();
10 |
11 | class ReactPullExample extends Component {
12 | constructor(props) {
13 | super(props);
14 | this.state = {
15 | items: 2,
16 | disablePullUp: false
17 | };
18 | }
19 |
20 | refreshCallback = () => {
21 | return new Promise((resolve, reject) => {
22 | setTimeout(() => {
23 | let result = false;
24 | if (Math.random() > 0.5) {
25 | result = true;
26 | }
27 | if (result) {
28 | this.setState({
29 | items: 30,
30 | disablePullUp: false
31 | }, () => {
32 | resolve();
33 | });
34 | } else {
35 | reject(new Error('错误'));
36 | }
37 | }, 1000);
38 | }).then(() => {
39 | console.info('刷新成功!');
40 | }, (error) => {
41 | console.info('刷新失败!');
42 | Promise.error(error);
43 | });
44 | };
45 |
46 | loadMoreCallback = () => {
47 | return new Promise((resolve, reject) => {
48 | setTimeout(() => {
49 | let result = false;
50 | if (Math.random() > 0.5) {
51 | result = true;
52 | }
53 | if (result) {
54 | const {items} = this.state;
55 | this.setState({
56 | items: items >= 60 ? (items + 1) : (items + 10),
57 | disablePullUp: items >= 60
58 | }, () => {
59 | resolve();
60 | });
61 | } else {
62 | reject(new Error('错误'));
63 | }
64 | }, 1000);
65 | }).then(() => {
66 | console.info('加载更多成功!');
67 | }, (error) => {
68 | console.info('加载更多失败!');
69 | Promise.error(error);
70 | });
71 | };
72 |
73 | handleTouchTap = (e) => {
74 | console.info('测试下拉刷新插件是否与 Tap 事件冲突');
75 | };
76 |
77 | render() {
78 | const contents = [];
79 | const {items, disablePullUp} = this.state;
80 |
81 | for (let i = items; i > 0; i--) {
82 | if (i < 10) {
83 | contents.push(这里放置真实显示的DOM内容 {i});
84 | } else {
85 | contents.push(这里放置真实显示的DOM内容 {i});
86 | }
87 | }
88 |
89 | const props = {
90 | refreshCallback: this.refreshCallback,
91 | loadMoreCallback: this.loadMoreCallback,
92 | refresh: true,
93 | loadMore: true,
94 | disablePullUp,
95 | };
96 |
97 | return (
98 |
99 |
100 | {contents.map((item) => {
101 | return item;
102 | })}
103 |
104 |
105 | );
106 | }
107 | }
108 |
109 | render(
110 | , document.getElementById('layout')
111 | );
112 |
--------------------------------------------------------------------------------
/examples/sass/example.scss:
--------------------------------------------------------------------------------
1 | body {
2 | margin: 0;
3 | }
4 |
5 | a {
6 | color: #00C176;
7 | &:hover,
8 | &:focus,
9 | &:active {
10 | color: #88C100;
11 | }
12 | }
13 |
14 | .example {
15 | margin: 50px auto;
16 | width: 80%;
17 | }
18 |
19 | .example-list {
20 | > li {
21 | padding: 10px;
22 | }
23 | }
24 |
25 | .header,
26 | .footer {
27 | padding: 5px;
28 | background-color: #00C176;
29 | color: #fff;
30 | text-align: center;
31 | }
32 |
33 | .pull-carousel {
34 | .pull-refresh {
35 | top: -50px;
36 | padding-bottom: 10px;
37 | }
38 | }
39 |
40 | .carousel-scroller .swiper-panel{
41 | text-align: center;
42 | height: 200px;
43 | font-size: 28px;
44 | background: #f0f0f0;
45 | }
--------------------------------------------------------------------------------
/examples/simple.js:
--------------------------------------------------------------------------------
1 | import React, {Component} from 'react';
2 | import {render} from 'react-dom';
3 | import ReactAlloyTouch from '../js/index';
4 | import '../sass/index.scss';
5 | import './sass/example.scss';
6 |
7 | const ReactAlloyTouchExample = () => {
8 | const len = 100;
9 | const content = [];
10 | for (let i = 0; i < len; i++) {
11 | content.push(i);
12 | }
13 | return (
14 |
15 |
16 | {content.map((it) => {
17 | return (
18 |
{`测试内容 ${it + 1}`}
19 | );
20 | })}
21 |
22 |
23 | );
24 | };
25 |
26 | render(
27 | , document.getElementById('layout')
28 | );
29 |
--------------------------------------------------------------------------------
/examples/tabs-carousel.js:
--------------------------------------------------------------------------------
1 | import React, {Component} from 'react';
2 | import {render} from 'react-dom';
3 | import injectTapEventPlugin from 'react-tap-event-plugin';
4 | import ReactSwiper from '../js/ReactSwiper';
5 | import '../sass/carousel.scss';
6 | import './sass/example.scss';
7 |
8 | // 初始化 tapEvent 事件, 移动端
9 | injectTapEventPlugin();
10 |
11 | class ReactSwiperExample extends Component {
12 | constructor(props) {
13 | super(props);
14 | this.state = {
15 | items: 30,
16 | disablePullUp: false
17 | };
18 | }
19 |
20 |
21 | handleTouchTap = (e) => {
22 | console.info('测试下拉刷新插件是否与 Tap 事件冲突');
23 | };
24 |
25 | handleSlideChange = (currentIndex) => {
26 | console.log(`currentIndex is ${currentIndex}`)
27 | const btns = document.querySelectorAll('input')
28 | Array.prototype.forEach.call(btns, (item, index) => {
29 | if (index === currentIndex) {
30 | item.style.color = 'red'
31 | } else {
32 | item.style.color = 'black'
33 | }
34 | })
35 | };
36 |
37 | handleST = (index) => {
38 |
39 | return function () {
40 | const {swiper} = this.refs
41 | swiper.SlideTo(index)
42 |
43 | // slideto()
44 |
45 | console.log(swiper)
46 | }.bind(this)
47 |
48 | }
49 |
50 | render() {
51 |
52 | const swiper1 = (
53 | 123
54 | )
55 | const swiper2 = (
56 | 456
57 | )
58 |
59 | const carouselItems = [swiper1, swiper2];
60 |
61 | return (
62 |
67 | );
68 | }
69 | }
70 |
71 | render(
72 | , document.getElementById('layout')
73 | );
74 |
--------------------------------------------------------------------------------
/examples/templates/layout.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | <%= htmlWebpackPlugin.options.title %>
5 |
6 |
8 |
9 |
24 |
25 |
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/gulp/example.babel.js:
--------------------------------------------------------------------------------
1 | import gulp from 'gulp';
2 | import gulpLoadPlugins from 'gulp-load-plugins';
3 | import webpack from 'webpack';
4 | import WebpackDevServer from 'webpack-dev-server';
5 | import opn from 'opn';
6 | import exampleConfig from '../webpack.config.example.babel';
7 |
8 | const $ = gulpLoadPlugins();
9 | const {webpackConfig, ip, port} = exampleConfig;
10 |
11 | gulp.task('copy-eruda', () => {
12 | return gulp.src('node_modules/eruda/eruda.min.js')
13 | .pipe(gulp.dest('examples'));
14 | });
15 |
16 | // 运行 example
17 | gulp.task('example', ['copy-eruda'], () => {
18 | // Start a webpack-dev-server
19 | const compiler = webpack(webpackConfig);
20 | new WebpackDevServer(compiler, webpackConfig.devServer)
21 | .listen(port, ip, (err) => {
22 | if (err) {
23 | throw new $.util.PluginError('webpack-dev-server', err);
24 | }
25 | // Server listening
26 | $.util.log('[webpack-dev-server]', `http://${ip}:${port}/`);
27 |
28 | // keep the server alive or continue?
29 | opn(port === '80' ? `http://${ip}` : `http://${ip}:${port}/`, {app: 'google chrome'});
30 | });
31 | });
32 |
33 | gulp.task('copy-eruda-dist', () => {
34 | return gulp.src('node_modules/eruda/eruda.min.js')
35 | .pipe(gulp.dest('examples-dist'));
36 | });
37 |
38 |
--------------------------------------------------------------------------------
/gulp/publish.babel.js:
--------------------------------------------------------------------------------
1 | import childProcess from 'child_process';
2 | import gulp from 'gulp';
3 | import chalk from 'chalk';
4 | import gulpLoadPlugins from 'gulp-load-plugins';
5 |
6 | const $ = gulpLoadPlugins();
7 |
8 | gulp.task('copy-publish', () => {
9 | return gulp
10 | .src(['README.md', 'sass/*', 'js/*'])
11 | .pipe($.copy('publish'))
12 | });
13 |
14 | // 发布到 npm 中
15 | gulp.task('publish', () => {
16 | const {exec} = childProcess;
17 | exec('cd publish && npm publish && cd ..', (error, stdout, stderr) => {
18 | if (error) {
19 | console.log(chalk.magenta(error));
20 | return;
21 | }
22 | if (stdout) {
23 | console.log(chalk.magenta(`stdout: ${stdout}`));
24 | }
25 | if (stderr) {
26 | console.log(chalk.magenta(`stderr: ${stderr}`));
27 | }
28 | });
29 | });
30 |
--------------------------------------------------------------------------------
/gulp/scss.babel.js:
--------------------------------------------------------------------------------
1 | import gulp from 'gulp';
2 | import gulpLoadPlugins from 'gulp-load-plugins';
3 | import chalk from 'chalk';
4 | import autoprefixer from 'autoprefixer';
5 | import flexbugs from 'postcss-flexbugs-fixes';
6 |
7 | const $ = gulpLoadPlugins();
8 |
9 | const scssOption = {
10 | outputStyle: 'expanded', // 不压缩,设为 compressed 表示压缩
11 | precision: 10, // 设置小数精度
12 | includePaths: ['.']
13 | };
14 |
15 | /**
16 | * 浏览器支持性参考 bootstrap 官方的支持,参见源码 postcss.js 的支持性说明
17 | * iOS:https://developer.apple.com/support/app-store/
18 | * Android:https://developer.android.com/about/dashboards/index.html
19 | */
20 | const browsers = ['Chrome >= 35', 'Firefox >= 38',
21 | 'Android >= 4.3', 'iOS >= 8', 'Safari >= 8', 'Opera >= 12'];
22 |
23 | const postcssPlugins = [
24 | autoprefixer({
25 | flexbox: 'no-2009', // 不生成2009定义的 Flexbox
26 | browsers
27 | }),
28 | flexbugs
29 | ];
30 |
31 | /**
32 | * 利用sass生成styles任务
33 | * [在线补齐前缀](http://autoprefixer.github.io/)
34 | * [浏览器列表](https://github.com/ai/browserslist)
35 | *
36 | */
37 | gulp.task('scss', () => {
38 | return gulp.src('sass/*.scss')
39 | .pipe($.sourcemaps.init())
40 | .pipe($.sass.sync(scssOption).on('error', $.sass.logError))
41 | .pipe($.postcss(postcssPlugins))
42 | .pipe($.sourcemaps.write('./maps'))
43 | .pipe(gulp.dest('publish/css'));
44 | });
45 |
46 | // 检测样式加前缀
47 | gulp.task('css-pre', () => {
48 | const info = autoprefixer({
49 | browsers
50 | }).info();
51 |
52 | console.log(chalk.magenta(info));
53 | });
54 |
--------------------------------------------------------------------------------
/gulpfile.babel.js:
--------------------------------------------------------------------------------
1 | import gulp from 'gulp';
2 | import requireDir from 'require-dir';
3 |
4 | requireDir('./gulp');
5 |
6 | // 默认任务
7 | gulp.task('default', () => {
8 | gulp.start('build');
9 | });
10 |
--------------------------------------------------------------------------------
/js/AlloyTouch.js:
--------------------------------------------------------------------------------
1 | import AlloyTouch from 'alloytouch';
2 |
3 | // 重新设置 AlloyTouch 方法
4 | AlloyTouch.prototype.setOption = function (key, value) {
5 | this[key] = value;
6 | };
7 |
8 | export default AlloyTouch;
9 |
--------------------------------------------------------------------------------
/js/ReactAlloyTouch.js:
--------------------------------------------------------------------------------
1 | import React, {Component} from 'react';
2 | import PropTypes from 'prop-types';
3 | import AlloyTouch from './AlloyTouch';
4 | import Transform from 'alloytouch/transformjs/transform';
5 |
6 | // 基于腾讯组件 https://github.com/AlloyTeam/AlloyTouch 实现
7 | class ReactAlloyTouch extends Component {
8 | //可能需要传入的参数
9 | static propTypes = {
10 | children: PropTypes.node, // 待渲染的内容
11 | className: PropTypes.string, // 自定义 className
12 | prefix: PropTypes.string, // 样式前缀
13 | options: PropTypes.object, // AlloyTouch 组件选项
14 | transform: PropTypes.bool, // 是否用 Transform 处理
15 | extensionFunc: PropTypes.func, // 扩展函数,处理额外的功能
16 | updateFunc: PropTypes.func, // 执行 componentDidUpdate 调用的回调
17 | };
18 |
19 | static defaultProps = {
20 | className: '',
21 | prefix: 'alloy',
22 | options: {},
23 | transform: true,
24 | };
25 |
26 | componentDidMount() {
27 | const {wrapper, scroller} = this;
28 | const {options, transform, extensionFunc} = this.props;
29 |
30 | // 处理 options 中函数,返回 wrapper 和 scroller
31 | Object.keys(options).forEach((func) => {
32 | if (typeof func === 'function') {
33 | options[func] = function (...args) {
34 | options[func](...args, wrapper, scroller);
35 | };
36 | }
37 | });
38 |
39 | if (transform) {
40 | Transform(scroller, true);
41 | }
42 |
43 | let min = wrapper.clientHeight - scroller.scrollHeight;
44 | if (min >= 0) {
45 | min = 0;
46 | }
47 |
48 | const alloyOptions = {
49 | touch: wrapper, // 反馈触摸的dom
50 | target: scroller, // 运动的对象
51 | vertical: true, // 不必需,默认是true代表监听竖直方向touch
52 | property: 'translateY', // 被运动的属性
53 | sensitivity: 1, // 不必需,触摸区域的灵敏度,默认值为1,可以为负数
54 | factor: 1, // 不必需,表示触摸位移与被运动属性映射关系,默认值是1
55 | min,
56 | max: 0, // 不必需,滚动属性的最大值
57 | step: 40, // 用于校正到step的整数倍
58 | ...(options || {})
59 | };
60 |
61 | // 初始化 alloyTouch 实例
62 | this.alloyTouch = new AlloyTouch(alloyOptions);
63 |
64 | if (typeof extensionFunc === 'function') {
65 | extensionFunc(this.alloyTouch, wrapper, scroller);
66 | }
67 | }
68 |
69 | componentDidUpdate() {
70 | const {updateFunc} = this.props;
71 | const {wrapper, scroller} = this;
72 | if (typeof updateFunc === 'function') {
73 | updateFunc(this.alloyTouch, wrapper, scroller);
74 | }
75 | }
76 |
77 | handleWrapper = (wrapper) => {
78 | this.wrapper = wrapper;
79 | };
80 | handleScroller = (scroller) => {
81 | this.scroller = scroller;
82 | };
83 |
84 | render() {
85 | const {
86 | children, className, prefix,
87 | } = this.props;
88 |
89 | return (
90 |
91 |
92 | {children}
93 |
94 |
95 | );
96 | }
97 | }
98 |
99 | export default ReactAlloyTouch;
100 |
--------------------------------------------------------------------------------
/js/ReactCarousel.js:
--------------------------------------------------------------------------------
1 | import React, {Component} from 'react';
2 | import PropTypes from 'prop-types';
3 | import AlloyTouch from './AlloyTouch';
4 | import Transform from 'alloytouch/transformjs/transform';
5 |
6 | // 基于腾讯组件 https://github.com/AlloyTeam/AlloyTouch 实现
7 | class ReactAlloyTouch extends Component {
8 | //可能需要传入的参数
9 | static propTypes = {
10 | className: PropTypes.string, // 自定义 className
11 | prefix: PropTypes.string, // 样式前缀
12 | options: PropTypes.object, // AlloyTouch 组件选项
13 | items: PropTypes.array, // 轮播图
14 | active: PropTypes.number, // 当前活动轮播图
15 | autoPlay: PropTypes.oneOfType([PropTypes.bool, PropTypes.number]), // 是否自动播放
16 | events: PropTypes.object, // 自定义各种事件
17 | };
18 |
19 | static defaultProps = {
20 | className: '',
21 | prefix: 'carousel',
22 | active: 0,
23 | autoPlay: 4000, // 默认一4秒播放一次
24 | events: {},
25 | };
26 |
27 | constructor(props) {
28 | super(props);
29 |
30 | this.currentIndex = 0;
31 | }
32 |
33 | componentDidMount() {
34 | const {wrapper, scroller, nav} = this.refs;
35 | const {options, items} = this.props;
36 |
37 | this.navItems = nav.querySelectorAll('a');
38 | Transform(scroller, true);
39 |
40 | const alloyOptions = {
41 | touch: wrapper, //反馈触摸的dom
42 | vertical: false, //不必需,默认是true代表监听竖直方向touch
43 | target: scroller, //运动的对象
44 | property: 'translateX', //被运动的属性
45 | min: wrapper.clientWidth * -(items.length - 1), //不必需,运动属性的最小值
46 | max: 0, //不必需,滚动属性的最大值
47 | step: wrapper.clientWidth,
48 | spring: true, //不必需,是否有回弹效果。默认是true
49 | inertia: false, //不必需,是否有惯性。默认是true
50 | touchStart: this.touchStart,
51 | touchEnd: this.touchEnd,
52 | animationEnd: this.animationEnd,
53 | ...(options || {})
54 | };
55 |
56 | // 初始化 alloyTouch 实例
57 | this.alloyTouch = new AlloyTouch(alloyOptions);
58 | this.handleAutoPlay();
59 | }
60 |
61 | touchStart = () => {
62 | // 先删除
63 | clearInterval(this.timerId);
64 | };
65 |
66 | touchEnd = (evt, value, index) => {
67 | const {step, min, max} = this.alloyTouch;
68 | const stepV = index * step * -1;
69 | const dx = value - stepV;
70 |
71 | if (value < min) {
72 | this.alloyTouch.to(min);
73 | } else if (value > max) {
74 | this.alloyTouch.to(max);
75 | } else if (Math.abs(dx) < 30) {
76 | this.alloyTouch.to(stepV);
77 | } else if (dx > 0) {
78 | this.alloyTouch.to(stepV + step);
79 | } else {
80 | this.alloyTouch.to(stepV - step);
81 | }
82 | this.currentIndex = index;
83 |
84 | // 开启自动播放
85 | this.handleAutoPlay();
86 | return false;
87 | };
88 |
89 | animationEnd = () => {
90 | const len = this.navItems.length;
91 | let i = 0;
92 | for (; i < len; i++) {
93 | if (i === this.alloyTouch.currentPage) {
94 | this.navItems[i].classList.add('active');
95 | } else {
96 | this.navItems[i].classList.remove('active');
97 | }
98 | }
99 | };
100 |
101 | // 自动播放
102 | handleAutoPlay() {
103 | const {autoPlay, items} = this.props;
104 | const len = items.length;
105 | if (autoPlay) {
106 | this.timerId = setInterval(() => {
107 | const {step} = this.alloyTouch;
108 | const stepV = this.currentIndex * step * -1;
109 | this.alloyTouch.to(stepV);
110 | if (this.currentIndex >= len - 1) {
111 | this.currentIndex = 0;
112 | } else {
113 | this.currentIndex++;
114 | }
115 | }, autoPlay);
116 | }
117 | }
118 |
119 | render() {
120 | const {
121 | className, prefix, items, active, events,
122 | } = this.props;
123 |
124 | const len = items.length;
125 | return (
126 |
127 |
128 | {items.map(({image, link}) => {
129 | if (link) {
130 | return (
131 |
132 | );
133 | }
134 | return (

);
135 | })}
136 |
137 |
138 | {items.map((it, index) => {
139 | /*eslint-disable react/no-array-index-key*/
140 | return (
);
141 | })}
142 |
143 |
144 | );
145 | }
146 | }
147 |
148 | export default ReactAlloyTouch;
149 |
--------------------------------------------------------------------------------
/js/ReactPull.js:
--------------------------------------------------------------------------------
1 | import React, {Component} from 'react';
2 | import PropTypes from 'prop-types';
3 | import AlloyTouch from './AlloyTouch';
4 | import Transform from 'alloytouch/transformjs/transform';
5 |
6 | // 基于腾讯组件
7 | class ReactAlloyTouch extends Component {
8 | //可能需要传入的参数
9 | static propTypes = {
10 | children: PropTypes.node, // 待渲染的内容
11 | className: PropTypes.string, // 自定义 className
12 | header: PropTypes.element, // 头部
13 | footer: PropTypes.element, // 底部
14 | options: PropTypes.object, // AlloyTouch 组件选项
15 | lockInTime: PropTypes.number, // 延迟刷新或加载
16 | enableText: PropTypes.bool, // 是否显示文本
17 | refresh: PropTypes.bool, // 是否下拉刷新
18 | refreshThreshold: PropTypes.number, // 设置刷新页面时,距离顶部临界值,
19 | refreshCallback: PropTypes.func, // 刷新回调函数
20 | pullDownText: PropTypes.array, // 下拉显示文本内容
21 | loadMore: PropTypes.bool, // 是否加载更多
22 | loadMoreThrottle: PropTypes.number, // 设置加载更多,距离最底部临界值,
23 | loadMoreCallback: PropTypes.func, // 加载更多回调函数
24 | pullUpText: PropTypes.array, // 上拉显示文本内容
25 | loadMoreProcessIcon: PropTypes.bool, // 加载更多过程图标
26 | disablePullUp: PropTypes.bool, // 对于上拉加载更多时,如果没有更多记录时,禁止上滑,
27 | loadedRecoilTime: PropTypes.number, // 加载完更多数据回弹时间
28 | moveForwardOffset: PropTypes.number, // 加载完更多数据时,向前推进的距离
29 | };
30 |
31 | static defaultProps = {
32 | className: '',
33 | refreshThreshold: 50,
34 | loadMoreThrottle: 30,
35 | lockInTime: 0,
36 | pullDownText: ['下拉刷新', '松开刷新数据', '加载中,请稍后...'],
37 | pullUpText: ['上滑加载更多...', '松开加载数据', '加载中,请稍后...', '没有更多数据了'],
38 | enableText: true,
39 | loadMoreProcessIcon: true,
40 | loadedRecoilTime: 300,
41 | moveForwardOffset: 50
42 | };
43 |
44 | constructor(props) {
45 | super(props);
46 | this.state = {
47 | refreshText: props.pullDownText[0],
48 | loadMoreText: props.pullUpText[0]
49 | };
50 | // 下拉状态: 分为没有开启,开启,加载中 null enable loading
51 | this.refreshState = null;
52 | // 上滑状态: 分为没有开启,开启,加载中 null enable loading
53 | this.loadMoreState = null;
54 | }
55 |
56 | componentDidMount() {
57 | const {wrapper, scroller} = this.refs;
58 | const {options} = this.props;
59 |
60 | Transform(scroller, true);
61 |
62 | // 设置向下滑动时,滑动的最小值,如果采用translateY,则设置 y的最小值,如果不设置 min,则可以无限制的向下滑动
63 | let min = wrapper.clientHeight - scroller.scrollHeight;
64 | if (min >= 0) {
65 | min = 0;
66 | }
67 |
68 | const alloyOptions = {
69 | touch: wrapper, // 反馈触摸的dom
70 | target: scroller, // 运动的对象
71 | vertical: true, // 不必需,默认是true代表监听竖直方向touch
72 | property: 'translateY', // 被运动的属性
73 | sensitivity: 1, // 不必需,触摸区域的灵敏度,默认值为1,可以为负数
74 | factor: 1, // 不必需,表示触摸位移与被运动属性映射关系,默认值是1
75 | min,
76 | max: 0, // 不必需,滚动属性的最大值
77 | step: 40, // 用于校正到step的整数倍
78 | maxSpeed: 2, //不必需,触摸反馈的最大速度限制
79 | touchStart: this.touchStart,
80 | touchMove: this.touchMove,
81 | touchEnd: this.touchEnd,
82 | ...(options || {})
83 | };
84 |
85 | // 初始化 alloyTouch 实例
86 | this.alloyTouch = new AlloyTouch(alloyOptions);
87 |
88 | this.adjustPosition();
89 | }
90 |
91 | componentDidUpdate() {
92 | // 每次页面数据更改后,需要重新设置 this.alloyTouch 的 min 值
93 | const {wrapper, scroller} = this.refs;
94 |
95 | let min = wrapper.clientHeight - scroller.scrollHeight;
96 | if (min >= 0) {
97 | min = 0;
98 | }
99 | this.alloyTouch.setOption('min', min);
100 |
101 | this.adjustPosition();
102 | }
103 |
104 | adjustPosition() {
105 | const {header, footer, alloyBody} = this.refs;
106 |
107 | if (header) {
108 | alloyBody.style.top = `${header.scrollHeight}px`;
109 | }
110 |
111 | if (footer) {
112 | alloyBody.style.bottom = `${footer.scrollHeight}px`;
113 | }
114 | }
115 |
116 | // touch 开始时
117 | touchStart = (e, value) => {
118 | if (this.props.loadMore) {
119 | // 记录当前滑动值
120 | const {wrapper, scroller} = this.refs;
121 | let heightOffset = wrapper.clientHeight - scroller.scrollHeight;
122 | if (heightOffset > 0) {
123 | heightOffset = 0;
124 | }
125 |
126 | this.offsetStart = heightOffset;
127 | this.moveValue = value;
128 | }
129 | };
130 |
131 | // touch 移动时,分刷新和加载更多
132 | touchMove = (e, value) => {
133 | const {
134 | refresh, loadMore, refreshThreshold, loadMoreThrottle,
135 | pullDownText, pullUpText
136 | } = this.props;
137 |
138 | // 下拉刷新
139 | if (refresh && this.refreshState !== 'loading') {
140 | const {refreshEl, refreshIconEl} = this.refs;
141 | const {style} = refreshEl;
142 | if (value > 0) {
143 | if (value > refreshThreshold) {
144 | this.refreshState = 'enable';
145 | refreshIconEl.classList.add('rotate');
146 | this.setState({
147 | refreshText: pullDownText[1]
148 | });
149 | } else {
150 | this.refreshState = null;
151 | refreshIconEl.classList.remove('rotate');
152 | this.setState({
153 | refreshText: pullDownText[0]
154 | });
155 | }
156 | }
157 |
158 | style.opacity = 1;
159 | style.webkitTransform = `translate3d(0, ${value}px, 0)`;
160 | style.transform = `translate3d(0, ${value}px, 0)`;
161 | }
162 |
163 | // 上滑加载更多
164 | if (loadMore) {
165 | const {disablePullUp} = this.props;
166 | const {loadMoreEl, loadMoreIconEl} = this.refs;
167 | const {style} = loadMoreEl;
168 | const {wrapper, scroller} = this.refs;
169 |
170 | const min = wrapper.clientHeight - scroller.scrollHeight;
171 |
172 | if (this.loadMoreState !== 'loading') {
173 | if (disablePullUp) {
174 | const min = wrapper.clientHeight - scroller.scrollHeight;
175 | if (min < 0) {
176 | loadMoreEl.style.visibility = value < min - 5 ? 'visible' : 'hidden';
177 | }
178 | return false;
179 | }
180 | if (value < min && value < 0) {
181 | style.visibility = 'visible';
182 | if (Math.abs(value - this.moveValue) > loadMoreThrottle) {
183 | this.loadMoreState = 'enable';
184 | loadMoreIconEl.classList.add('rotate');
185 | this.setState({
186 | loadMoreText: pullUpText[1]
187 | });
188 | } else {
189 | this.loadMoreState = null;
190 | loadMoreIconEl.classList.remove('rotate');
191 | this.setState({
192 | loadMoreText: pullUpText[0]
193 | });
194 | }
195 | } else {
196 | style.visibility = 'hidden';
197 | }
198 | }
199 | }
200 | };
201 |
202 | // touch end
203 | touchEnd = (e, value) => {
204 | const {refresh, loadMore, disablePullUp} = this.props;
205 | // 刷新
206 | if (value > 0) {
207 | if (refresh) {
208 | if (this.refreshState === 'enable') {
209 | this.refresh(e);
210 | } else {
211 | this.resetRefreshState();
212 | }
213 | // 阻止默认的滑动
214 | return false;
215 | }
216 | return;
217 | }
218 |
219 | // 加载更多
220 | const {wrapper, scroller} = this.refs;
221 | const min = wrapper.clientHeight - scroller.scrollHeight;
222 | if (value < min) {
223 | if (loadMore && !disablePullUp && this.loadMoreState === 'enable') {
224 | this.loadMore(e);
225 | // 阻止默认的滑动
226 | return false;
227 | }
228 | this.resetLoadMoreState({moveTo: false});
229 | }
230 | };
231 |
232 | // 刷新数据
233 | refresh = (e) => {
234 | if (e) {
235 | e.stopImmediatePropagation();
236 | }
237 |
238 | if (this.refreshState === null || this.refreshState === 'loading') {
239 | return;
240 | }
241 | this.refreshState = 'loading';
242 | const {refreshCallback, lockInTime, pullDownText} = this.props;
243 | const {refreshIconEl} = this.refs;
244 | refreshIconEl.classList.add('loading');
245 | this.setState({
246 | refreshText: pullDownText[2]
247 | });
248 |
249 | if (refreshCallback && typeof refreshCallback === 'function') {
250 | if (lockInTime > 0) {
251 | clearTimeout(this.refreshTimoutId);
252 | this.refreshTimoutId = setTimeout(() => {
253 | refreshCallback().then(this.resetRefreshState, this.resetRefreshState);
254 | }, lockInTime);
255 | } else {
256 | refreshCallback().then(this.resetRefreshState, this.resetRefreshState);
257 | }
258 | } else {
259 | this.resetRefreshState();
260 | }
261 | };
262 |
263 | // 恢复刷新原始状态
264 | resetRefreshState = () => {
265 | const {pullDownText, refresh} = this.props;
266 | this.refreshState = null;
267 | if (refresh) {
268 | const {refreshEl, refreshIconEl} = this.refs;
269 | const {style} = refreshEl;
270 | refreshIconEl.classList.remove('rotate');
271 | refreshIconEl.classList.remove('loading');
272 |
273 | style.opacity = 0;
274 | style.transition = '';
275 | style.webkitTransition = '';
276 | style.webkitTransform = 'translate3d(0, 0, 0)';
277 | style.transform = 'translate3d(0, 0, 0)';
278 |
279 | this.setState({
280 | refreshText: pullDownText[0]
281 | });
282 | }
283 |
284 | this.alloyTouch.to(0);
285 | };
286 |
287 | // 加载更多
288 | loadMore = (e) => {
289 | if (e) {
290 | e.stopImmediatePropagation();
291 | }
292 |
293 | if (this.loadMoreState === null || this.loadMoreState === 'loading') {
294 | return;
295 | }
296 | this.loadMoreState = 'loading';
297 | const {loadMoreCallback, lockInTime, pullUpText} = this.props;
298 | const {loadMoreIconEl} = this.refs;
299 | loadMoreIconEl.classList.add('loading');
300 | this.setState({
301 | loadMoreText: pullUpText[2]
302 | });
303 |
304 | if (loadMoreCallback && typeof loadMoreCallback === 'function') {
305 | if (lockInTime > 0) {
306 | clearTimeout(this.loadMoreTimoutId);
307 | this.loadMoreTimoutId = setTimeout(() => {
308 | loadMoreCallback().then(() => {
309 | this.resetLoadMoreState({adjust: true});
310 | }, () => {
311 | this.resetLoadMoreState({});
312 | });
313 | }, lockInTime);
314 | } else {
315 | loadMoreCallback().then(() => {
316 | this.resetLoadMoreState({adjust: true});
317 | }, () => {
318 | this.resetLoadMoreState({});
319 | });
320 | }
321 | } else {
322 | this.resetLoadMoreState({});
323 | }
324 | };
325 |
326 | // 恢复加载更多原始状态
327 | resetLoadMoreState = ({adjust = false, moveTo = true}) => {
328 | const {pullUpText, loadedRecoilTime, moveForwardOffset, loadMore} = this.props;
329 | this.loadMoreState = null;
330 | if (loadMore) {
331 | const {loadMoreEl, loadMoreIconEl} = this.refs;
332 | loadMoreIconEl.classList.remove('rotate');
333 | loadMoreIconEl.classList.remove('loading');
334 |
335 | this.setState({
336 | loadMoreText: pullUpText[0]
337 | });
338 | loadMoreEl.style.visibility = 'hidden';
339 | }
340 |
341 | if (this.offsetStart !== undefined) {
342 | let offset;
343 | if (adjust) {
344 | offset = this.offsetStart < -moveForwardOffset ? this.offsetStart - moveForwardOffset : this.offsetStart;
345 | } else {
346 | offset = this.offsetStart;
347 | }
348 |
349 | if (moveTo) {
350 | this.alloyTouch.to(offset, loadedRecoilTime);
351 | }
352 | }
353 | };
354 |
355 | // 选择加载更多
356 | renderLoadMore() {
357 | const {loadMoreText} = this.state;
358 | const {enableText, loadMore, loadMoreProcessIcon, disablePullUp, pullUpText} = this.props;
359 | if (loadMore) {
360 | return (
361 |
362 |
364 | {enableText ? (
365 |
{disablePullUp ? pullUpText[3] : loadMoreText}
) : null}
367 |
368 | );
369 | }
370 | return null;
371 | }
372 |
373 | render() {
374 | const {
375 | children, className, header, footer, refresh, enableText
376 | } = this.props;
377 | const {refreshText} = this.state;
378 |
379 | return (
380 |
381 | {header ? (
{header}
) : null}
382 |
383 | {
384 | refresh ? (
385 |
388 | {enableText ? (
{refreshText}
) : null}
389 |
) : null
390 | }
391 |
392 |
393 | {children}
394 |
395 |
396 | {this.renderLoadMore()}
397 |
398 | {footer ? (
{footer}
) : null}
399 |
400 | );
401 | }
402 | }
403 |
404 | export default ReactAlloyTouch;
405 |
--------------------------------------------------------------------------------
/js/ReactSwiper.js:
--------------------------------------------------------------------------------
1 | import React, {Component} from 'react';
2 | import PropTypes from 'prop-types';
3 | import AlloyTouch from './AlloyTouch';
4 | import Transform from 'alloytouch/transformjs/transform';
5 |
6 | // 基于腾讯组件 https://github.com/AlloyTeam/AlloyTouch 实现
7 | class ReactAlloyTouch extends Component {
8 | //可能需要传入的参数
9 | static propTypes = {
10 | className: PropTypes.string, // 自定义 className
11 | prefix: PropTypes.string, // 样式前缀
12 | options: PropTypes.object, // AlloyTouch 组件选项
13 | items: PropTypes.array, // 轮播图
14 | showDot: PropTypes.bool, //是否显示点
15 | active: PropTypes.number, // 当前活动轮播图
16 | autoPlay: PropTypes.oneOfType([PropTypes.bool, PropTypes.number]), // 是否自动播放
17 | events: PropTypes.object, // 自定义各种事件
18 | onSlideChange: PropTypes.func
19 | };
20 |
21 | static defaultProps = {
22 | className: '',
23 | prefix: 'carousel',
24 | active: 0,
25 | autoPlay: 4000, // 默认一4秒播放一次
26 | tabsMenu: null,
27 | events: {},
28 | };
29 |
30 | constructor(props) {
31 | super(props);
32 |
33 | this.currentIndex = 0;
34 | }
35 |
36 | componentDidMount() {
37 | const {wrapper, scroller, nav, menu} = this.refs;
38 | const {options, items, prefix} = this.props;
39 |
40 | this.navItems = nav.querySelectorAll('a');
41 | Transform(scroller);
42 |
43 | const alloyOptions = {
44 | touch: wrapper, //反馈触摸的dom
45 | vertical: false, //不必需,默认是true代表监听竖直方向touch
46 | target: scroller, //运动的对象
47 | property: 'translateX', //被运动的属性
48 | min: wrapper.clientWidth * -(items.length - 1), //不必需,运动属性的最小值
49 | max: 0, //不必需,滚动属性的最大值
50 | step: wrapper.clientWidth,
51 | spring: true, //不必需,是否有回弹效果。默认是true
52 | inertia: false, //不必需,是否有惯性。默认是true
53 | touchStart: this.touchStart,
54 | touchEnd: this.touchEnd,
55 | animationEnd: this.animationEnd,
56 | ...(options || {})
57 | };
58 |
59 | // 初始化 alloyTouch 实例
60 | this.alloyTouch = new AlloyTouch(alloyOptions);
61 | this.handleAutoPlay();
62 | }
63 |
64 | touchStart = () => {
65 | // 先删除
66 | clearInterval(this.timerId);
67 | };
68 |
69 | touchEnd = (evt, value, index) => {
70 | const {step, min, max} = this.alloyTouch;
71 | const stepV = index * step * -1;
72 | const dx = value - stepV;
73 |
74 | if (value < min) {
75 | this.alloyTouch.to(min);
76 | } else if (value > max) {
77 | this.alloyTouch.to(max);
78 | } else if (Math.abs(dx) < 30) {
79 | this.alloyTouch.to(stepV);
80 | } else if (dx > 0) {
81 | this.alloyTouch.to(stepV + step);
82 | } else {
83 | this.alloyTouch.to(stepV - step);
84 | }
85 | this.currentIndex = index;
86 |
87 | // 开启自动播放
88 | this.handleAutoPlay();
89 | return false;
90 | };
91 |
92 | animationEnd = () => {
93 | const len = this.navItems.length;
94 | let i = 0;
95 | for (; i < len; i++) {
96 | if (i === this.alloyTouch.currentPage) {
97 | this.navItems[i].classList.add('active');
98 | } else {
99 | this.navItems[i].classList.remove('active');
100 | }
101 | }
102 |
103 | if (typeof this.props.onSlideChange === 'function') this.props.onSlideChange(this.alloyTouch.currentPage)
104 | };
105 |
106 | //给外部组件提供接口
107 | SlideTo = (index) => {
108 | const {step} = this.alloyTouch;
109 | const stepV = index * step * -1;
110 | this.alloyTouch.to(stepV);
111 | };
112 |
113 | // 自动播放
114 | handleAutoPlay() {
115 | const {autoPlay, items} = this.props;
116 | const len = items.length;
117 | if (autoPlay) {
118 | this.timerId = setInterval(() => {
119 | const {step} = this.alloyTouch;
120 | const stepV = this.currentIndex * step * -1;
121 | this.alloyTouch.to(stepV);
122 | if (this.currentIndex >= len - 1) {
123 | this.currentIndex = 0;
124 | } else {
125 | this.currentIndex++;
126 | }
127 | }, autoPlay);
128 | }
129 | }
130 |
131 | render() {
132 | const {
133 | className, prefix, items, active, showDot, events,
134 | } = this.props;
135 |
136 | const len = items.length;
137 | return (
138 |
139 |
140 | {items.map((item, index) => {
141 | /*eslint-disable react/no-array-index-key*/
142 | return (
143 | {item}
144 |
);
145 | })}
146 |
147 |
148 | {items.map((it, index) => {
149 | /*eslint-disable react/no-array-index-key*/
150 | return (
);
151 | })}
152 |
153 |
154 | );
155 | }
156 | }
157 |
158 | export default ReactAlloyTouch;
159 |
--------------------------------------------------------------------------------
/js/index.js:
--------------------------------------------------------------------------------
1 | import ReactAlloyTouch from './ReactAlloyTouch';
2 | import reactPull from './ReactPull';
3 | import reactCarousel from './ReactCarousel';
4 | import reactSwiper from './ReactSwiper';
5 |
6 | export const ReactPull = reactPull;
7 | export const ReactCarousel = reactCarousel;
8 | export const ReactSwiper = reactSwiper;
9 |
10 | export default ReactAlloyTouch;
11 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "react-alloytouch",
3 | "version": "0.4.1",
4 | "author": {
5 | "name": "Linder Wang",
6 | "email": "linder0209@126.com",
7 | "url": "https://github.com/hopefuture"
8 | },
9 | "description": "This is a react component for AlloyTouch.",
10 | "keywords": [
11 | "react",
12 | "alloyTouch"
13 | ],
14 | "main": "lib/index.js",
15 | "module": "es/index.js",
16 | "jsnext:main": "es/index.js",
17 | "scripts": {
18 | "start": "gulp example",
19 | "clean": "rimraf publish/css publish/sass publish/lib publish/js publish/dist publish/es",
20 | "clean:examples": "rimraf examples-dist",
21 | "build:commonjs": "cross-env BABEL_ENV=commonjs babel js --out-dir publish/lib",
22 | "build:es": "cross-env BABEL_ENV=es babel js --out-dir publish/es",
23 | "build:umd": "webpack --progress --colors --config webpack.config.babel.js --output-filename [name].js",
24 | "build:umd:min": "webpack --progress --colors --config webpack.config.babel.js --output-filename [name].min.js --optimize-minimize",
25 | "prebuild": "npm run clean",
26 | "build": "npm run build:commonjs && npm run build:es && npm run build:umd && npm run build:umd:min",
27 | "prebuild:examples": "npm run clean:examples",
28 | "build:examples": "webpack --progress --colors --config webpack.config.example.dist.babel.js",
29 | "postbuild:examples": "gulp copy-eruda-dist",
30 | "prebuild:publish": "npm run build && gulp scss && gulp copy-publish",
31 | "build:publish": "gulp publish",
32 | "examples:publish": "npm run build:examples && git add examples-dist && git commit -m \"Update online examples\" && git subtree push --prefix=examples-dist origin gh-pages --squash && git push"
33 | },
34 | "dependencies": {
35 | "alloytouch": "^0.2.5",
36 | "eruda": "^1.3.1",
37 | "prop-types": "^15.6.0",
38 | "react": "^16.2.0",
39 | "react-dom": "^16.2.0",
40 | "react-tap-event-plugin": "^3.0.2"
41 | },
42 | "devDependencies": {
43 | "autoprefixer": "^7.2.1",
44 | "babel-cli": "^6.26.0",
45 | "babel-core": "^6.26.0",
46 | "babel-eslint": "^8.0.3",
47 | "babel-loader": "^7.1.2",
48 | "babel-plugin-transform-class-properties": "^6.24.1",
49 | "babel-plugin-transform-object-rest-spread": "^6.26.0",
50 | "babel-preset-env": "^1.6.1",
51 | "babel-preset-react": "^6.24.1",
52 | "cross-env": "^5.1.1",
53 | "css-loader": "^0.28.7",
54 | "eslint": "4.12.1",
55 | "eslint-loader": "^1.9.0",
56 | "eslint-plugin-react": "^7.5.1",
57 | "extract-text-webpack-plugin": "^3.0.2",
58 | "gulp": "^3.9.1",
59 | "gulp-autoprefixer": "^4.0.0",
60 | "gulp-copy": "^1.0.1",
61 | "gulp-load-plugins": "^1.5.0",
62 | "gulp-postcss": "^7.0.0",
63 | "gulp-sass": "^3.1.0",
64 | "gulp-sourcemaps": "^2.6.1",
65 | "gulp-util": "^3.0.8",
66 | "html-webpack-plugin": "^2.30.1",
67 | "node-sass": "^4.7.2",
68 | "opn": "^5.1.0",
69 | "postcss": "^6.0.14",
70 | "postcss-flexbugs-fixes": "^3.2.0",
71 | "postcss-loader": "^2.0.9",
72 | "precss": "^2.0.0",
73 | "require-dir": "^0.3.2",
74 | "sass-loader": "^6.0.6",
75 | "style-loader": "^0.19.0",
76 | "webpack": "^3.10.0",
77 | "webpack-dev-server": "^2.9.5"
78 | },
79 | "engines": {
80 | "node": ">=6.9.1"
81 | },
82 | "repository": {
83 | "type": "git",
84 | "url": "git+https://github.com/joy-web/react-alloytouch.git"
85 | },
86 | "license": "MIT",
87 | "bugs": {
88 | "url": "https://github.com/joy-web/react-alloytouch/issues"
89 | },
90 | "homepage": "https://github.com/joy-web/react-alloytouch#readme"
91 | }
92 |
--------------------------------------------------------------------------------
/publish/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "react-alloytouch",
3 | "version": "0.4.1",
4 | "author": {
5 | "name": "Linder Wang",
6 | "email": "linder0209@126.com",
7 | "url": "https://github.com/hopefuture"
8 | },
9 | "description": "This is a react component for AlloyTouch.",
10 | "keywords": [
11 | "react",
12 | "alloyTouch"
13 | ],
14 | "main": "lib/index.js",
15 | "module": "es/index.js",
16 | "jsnext:main": "es/index.js",
17 | "scripts": {},
18 | "dependencies": {
19 | "alloytouch": "^0.2.5"
20 | },
21 | "engines": {
22 | "node": ">=6.9.1"
23 | },
24 | "repository": {
25 | "type": "git",
26 | "url": "git+https://github.com/joy-web/react-alloytouch.git"
27 | },
28 | "license": "MIT",
29 | "bugs": {
30 | "url": "https://github.com/joy-web/react-alloytouch/issues"
31 | },
32 | "homepage": "https://github.com/joy-web/react-alloytouch#readme"
33 | }
34 |
--------------------------------------------------------------------------------
/sass/carousel.scss:
--------------------------------------------------------------------------------
1 | .carousel-wrapper {
2 | margin: 0 auto;
3 | overflow: hidden;
4 | position: relative;
5 | }
6 |
7 | .carousel-scroller {
8 | position: relative;
9 | font-size: 0;
10 | user-select: none;
11 | text-size-adjust: none;
12 | -webkit-tap-highlight-color: rgba(0, 0, 0, 0);
13 | -webkit-touch-callout: none;
14 | }
15 | .carousel-scroller .swiper-panel{
16 | float: left;
17 | }
18 |
19 | .carousel-tabs-menu{
20 | display: flex;
21 | .carousel-tabs-item{
22 | flex: 1;
23 | text-align: center;
24 | line-height: 2.2;
25 | bordr-bottom: 2px solid transparent;
26 | }
27 | .active{
28 | color: #CF121B;
29 | border-bottom: 2px solid #CF121B;
30 | }
31 | }
32 | .carousel-nav {
33 | position: absolute;
34 | bottom: 6px;
35 | right: 10px;
36 | > a {
37 | display: inline-block;
38 | background-color: white;
39 | cursor: pointer;
40 | width: 6px;
41 | height: 6px;
42 | border-radius: 5px;
43 | border: 1px solid #808080;
44 | transition: all .5s ease-in;
45 | &.active {
46 | background-color: #ffd800;
47 | width: 10px;
48 | }
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/sass/index.scss:
--------------------------------------------------------------------------------
1 | .alloy-wrapper {
2 | position: absolute;
3 | z-index: 1;
4 | top: 0;
5 | bottom: 0;
6 | left: 0;
7 | right: 0;
8 | overflow: hidden;
9 | }
10 |
11 | .alloy-scroller {
12 | position: absolute;
13 | left: 0;
14 | right: 0;
15 | z-index: 1;
16 | user-select: none;
17 | text-size-adjust: none;
18 | -webkit-tap-highlight-color: rgba(0, 0, 0, 0);
19 | -webkit-touch-callout: none;
20 | }
--------------------------------------------------------------------------------
/sass/pull.scss:
--------------------------------------------------------------------------------
1 | .pull-panel {
2 | }
3 |
4 | .pull-header {
5 | position: absolute;
6 | z-index: 2;
7 | top: 0;
8 | left: 0;
9 | right: 0;
10 | }
11 |
12 | .pull-footer {
13 | position: absolute;
14 | z-index: 2;
15 | bottom: 0;
16 | left: 0;
17 | right: 0;
18 | }
19 |
20 | .pull-body {
21 | position: absolute;
22 | top: 0;
23 | bottom: 0;
24 | left: 0;
25 | right: 0;
26 | }
27 |
28 | .pull-wrapper {
29 | position: absolute;
30 | z-index: 1;
31 | top: 0;
32 | bottom: 0;
33 | left: 0;
34 | right: 0;
35 | overflow: hidden;
36 | }
37 |
38 | .pull-scroller {
39 | position: absolute;
40 | left: 0;
41 | right: 0;
42 | z-index: 1;
43 | user-select: none;
44 | text-size-adjust: none;
45 | -webkit-tap-highlight-color: rgba(0, 0, 0, 0);
46 | -webkit-touch-callout: none;
47 | }
48 |
49 | .pull-refresh {
50 | position: absolute;
51 | top: -40px;
52 | left: 0;
53 | right: 0;
54 | display: block;
55 | overflow: hidden;
56 | }
57 |
58 | .pull-refresh-icon-wrapper {
59 | position: relative;
60 | width: 40px;
61 | margin: auto;
62 | text-align: center;
63 | height: 25px;
64 | }
65 |
66 | .pull-refresh-icon {
67 | position: absolute;
68 | top: 0;
69 | left: 12px;
70 | width: 14px;
71 | height: 25px;
72 | background-size: contain;
73 | background-position: center;
74 | background-repeat: no-repeat;
75 | background-image: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyMCIgaGVpZ2h0PSIyMCIgdmlld0JveD0iMCAwIDIwIDIwIj48cGF0aCBkPSJNOS44NTQgMTkuMzU0bDYtNmEuNS41IDAgMCAwLS43MDctLjcwN0wxMCAxNy43OTNWMS41YS41LjUgMCAwIDAtMSAwdjE2LjI5M2wtNS4xNDUtNS4xNDZhLjUuNSAwIDAgMC0uNzA3LjcwOGw2IDZhLjUuNSAwIDAgMCAuNzA3IDB6Ii8+PC9zdmc+);
76 | }
77 |
78 | .pull-refresh-icon.rotate {
79 | transform: translate3d(0, 0, 0) rotate(180deg);
80 | }
81 |
82 | .pull-refresh-icon.loading {
83 | animation: pull-loading 0.8s infinite linear;
84 | background-image: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI5MzIiIGhlaWdodD0iOTMyIiB2aWV3Qm94PSIwIDAgOTMyIDkzMiI+PHBhdGggZD0iTTQ2NiA5MzJjLTEyNC40NzMgMC0yNDEuNDk1LTQ4LjQ3My0zMjkuNTEzLTEzNi40ODdDNDguNDczIDcwNy40OTUgMCA1OTAuNDczIDAgNDY2YzAtODguMTM4IDI0Ljc0LTE3My45NjIgNzEuNTQ0LTI0OC4xOTIgNDUuNTA4LTcyLjE3MiAxMDkuODIzLTEzMC40OSAxODUuOTk2LTE2OC42NTJsMzkuMTM3IDc4LjEyQzIzNC43NTIgMTU4LjMgMTgyLjQ2IDIwNS43MiAxNDUuNDU1IDI2NC40MSAxMDcuNDYgMzI0LjY3IDg3LjM3NSAzOTQuMzc4IDg3LjM3NSA0NjZjMCAyMDguNzc0IDE2OS44NTMgMzc4LjYyNiAzNzguNjI2IDM3OC42MjZTODQ0LjYyNyA2NzQuNzc0IDg0NC42MjcgNDY2YzAtNzEuNjItMjAuMDg0LTE0MS4zMy01OC4wNzctMjAxLjU5LTM3LjAwOC01OC42OS04OS4zLTEwNi4xMS0xNTEuMjIzLTEzNy4xMzNsMzkuMTM3LTc4LjEyYzc2LjE3MyAzOC4xNiAxNDAuNDkgOTYuNDggMTg1Ljk5NiAxNjguNjVDOTA3LjI2MiAyOTIuMDQgOTMyLjAwMiAzNzcuODY0IDkzMi4wMDIgNDY2YzAgMTI0LjQ3My00OC40NzMgMjQxLjQ5NS0xMzYuNDg3IDMyOS41MTNDNzA3LjQ5NyA4ODMuNTI3IDU5MC40NzUgOTMyIDQ2Ni4wMDIgOTMyeiIvPjwvc3ZnPg==);
85 | }
86 |
87 | @keyframes pull-loading {
88 | from {
89 | transform: translate3d(0, 0, 0) rotate(0deg);
90 | }
91 | to {
92 | transform: translate3d(0, 0, 0) rotate(360deg);
93 | }
94 | }
95 |
96 | .pull-refresh-text {
97 | color: #666;
98 | font-size: 12px;
99 | text-align: center;
100 | }
101 |
102 | // 加载更多
103 | .pull-load-more {
104 | position: absolute;
105 | bottom: 5px;
106 | left: 0;
107 | right: 0;
108 | visibility: hidden;
109 | }
110 |
111 | .pull-load-more-icon {
112 | height: 20px;
113 | width: 20px;
114 | margin: 0 auto;
115 | color: #666;
116 | background-size: contain;
117 | background: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyMCIgaGVpZ2h0PSIyMCIgdmlld0JveD0iMCAwIDIwIDIwIj48cGF0aCBkPSJNOS44NTQgMTkuMzU0bDYtNmEuNS41IDAgMCAwLS43MDctLjcwN0wxMCAxNy43OTNWMS41YS41LjUgMCAwIDAtMSAwdjE2LjI5M2wtNS4xNDUtNS4xNDZhLjUuNSAwIDAgMC0uNzA3LjcwOGw2IDZhLjUuNSAwIDAgMCAuNzA3IDB6Ii8+PC9zdmc+) center no-repeat;
118 | transform: rotate(180deg);
119 | }
120 |
121 | .pull-load-more-icon.hide {
122 | display: none;
123 | }
124 |
125 | .pull-load-more-icon.rotate {
126 | transform: rotate(0deg);
127 | }
128 |
129 | .pull-load-more-icon.loading {
130 | display: block;
131 | background: transparent url('data:image/svg+xml;charset=utf-8,') center no-repeat;
132 | background-size: 20px 20px;
133 | animation: pull-load-more 1s step-end infinite;
134 | }
135 |
136 | .pull-load-more-text {
137 | font-size: 12px;
138 | margin-top: 5px;
139 | color: #666;
140 | text-align: center;
141 | }
142 |
143 | @keyframes pull-load-more {
144 | 0% {
145 | transform: rotate(0deg)
146 | }
147 | 8.33333333% {
148 | transform: rotate(30deg)
149 | }
150 | 16.66666667% {
151 | transform: rotate(60deg)
152 | }
153 | 25% {
154 | transform: rotate(90deg)
155 | }
156 | 33.33333333% {
157 | transform: rotate(120deg)
158 | }
159 | 41.66666667% {
160 | transform: rotate(150deg)
161 | }
162 | 50% {
163 | transform: rotate(180deg)
164 | }
165 | 58.33333333% {
166 | transform: rotate(210deg)
167 | }
168 | 66.66666667% {
169 | transform: rotate(240deg)
170 | }
171 | 75% {
172 | transform: rotate(270deg)
173 | }
174 | 83.33333333% {
175 | transform: rotate(300deg)
176 | }
177 | 91.66666667% {
178 | transform: rotate(330deg)
179 | }
180 | 100% {
181 | transform: rotate(360deg)
182 | }
183 | }
184 |
--------------------------------------------------------------------------------
/webpack.config.babel.js:
--------------------------------------------------------------------------------
1 | import path from 'path';
2 | import webpack from 'webpack';
3 | import precss from 'precss';
4 | import autoprefixer from 'autoprefixer';
5 |
6 | const webpackConfig = {
7 | devtool: 'source-map',
8 | resolve: {
9 | //自动扩展文件后缀名
10 | extensions: ['.js', '.jsx', '.scss']
11 | },
12 | entry: {
13 | index: ['./js/index.js']
14 | },
15 | externals: {
16 | react: 'react',
17 | 'react-dom': 'react-dom',
18 | 'prop-types': 'prop-types'
19 | },
20 | output: {
21 | path: path.join(__dirname, 'publish/dist'), //打包输出目录
22 | publicPath: './', //生成文件基于上下文路径
23 | library: ['reactAlloyTouch'],
24 | libraryTarget: 'umd'
25 | },
26 | module: {
27 | rules: [
28 | // https://github.com/MoOx/eslint-loader
29 | {
30 | enforce: 'pre',
31 | test: /\.js$/,
32 | exclude: /node_modules/,
33 | use: 'eslint-loader'
34 | },
35 | {
36 | test: /\.js$/,
37 | exclude: /node_modules/,
38 | use: 'babel-loader',
39 | }
40 | ],
41 | },
42 |
43 | plugins: [
44 | // http://webpack.github.io/docs/list-of-plugins.html#uglifyjsplugin
45 | //用来优化生成的代码 chunk,合并相同的代码
46 | new webpack.optimize.AggressiveMergingPlugin(),
47 | //用来保证编译过程不出错
48 | new webpack.NoEmitOnErrorsPlugin(),
49 | new webpack.DefinePlugin({
50 | 'process.env': {
51 | NODE_ENV: JSON.stringify('production')
52 | }
53 | }),
54 | new webpack.LoaderOptionsPlugin({
55 | options: {
56 | // eslint 配置
57 | eslint: {
58 | emitError: true, // 验证失败,终止
59 | configFile: '.eslintrc'
60 | },
61 | postcss () {
62 | return {
63 | defaults: [precss, autoprefixer],
64 | cleaner: [autoprefixer({
65 | flexbox: 'no-2009',
66 | browsers: ['Chrome >= 35', 'Firefox >= 38',
67 | 'Android >= 4.3', 'iOS >=8', 'Safari >= 8']
68 | })]
69 | };
70 | },
71 | }
72 | })
73 | ]
74 | };
75 |
76 | module.exports = webpackConfig;
77 |
--------------------------------------------------------------------------------
/webpack.config.example.babel.js:
--------------------------------------------------------------------------------
1 | import path from 'path';
2 | import webpack from 'webpack';
3 | import HtmlwebpackPlugin from 'html-webpack-plugin';
4 | import precss from 'precss';
5 | import autoprefixer from 'autoprefixer';
6 |
7 | const ip = '0.0.0.0';
8 | const port = 9090;
9 | const hotDevServer = 'webpack/hot/dev-server';
10 | // https://github.com/webpack/webpack-dev-server
11 | const webpackDevServer = `webpack-dev-server/client?http://${ip}:${port}`;
12 |
13 | const appPath = path.resolve(__dirname, 'examples');
14 |
15 | const webpackConfig = {
16 | cache: true,
17 | devtool: 'source-map', //生成 source map文件
18 | stats: {
19 | colors: true,
20 | reasons: true
21 | },
22 | devServer: {
23 | //指定根目录路径,比如访问 eruda.min.js 时,只需 http://localhost:9090/eruda.min.js 即可
24 | contentBase: './examples',
25 | historyApiFallback: true,
26 | hot: true,
27 | stats: {
28 | colors: true
29 | },
30 | watchOptions: {
31 | aggregateTimeout: 300,
32 | poll: 1000
33 | },
34 | quiet: false, // 设为true,不把任何信息输出到控制台
35 | open: true,
36 | },
37 | resolve: {
38 | //自动扩展文件后缀名
39 | extensions: ['.js', '.jsx', '.scss']
40 | },
41 |
42 | // 入口文件 让webpack用哪个文件作为项目的入口
43 | entry: {
44 | index: ['./examples/index.js', webpackDevServer, hotDevServer],
45 | simple: ['./examples/simple.js', webpackDevServer, hotDevServer],
46 | pull: ['./examples/pull.js', webpackDevServer, hotDevServer],
47 | 'header-footer': ['./examples/header-footer.js', webpackDevServer, hotDevServer],
48 | carousel: ['./examples/carousel.js', webpackDevServer, hotDevServer],
49 | 'pull-carousel': ['./examples/pull-carousel.js', webpackDevServer, hotDevServer],
50 | 'pull-carousel2': ['./examples/pull-carousel2.js', webpackDevServer, hotDevServer],
51 | 'tabs-carousel': ['./examples/tabs-carousel.js', webpackDevServer, hotDevServer]
52 | },
53 |
54 | // 出口 让webpack把处理完成的文件放在哪里
55 | output: {
56 | path: path.resolve(__dirname, 'examples/dist'), //打包输出目录
57 | filename: '[name].[hash].bundle.js', //文件名称
58 | publicPath: './' //资源路径
59 | },
60 |
61 | module: {
62 | rules: [
63 | // https://github.com/MoOx/eslint-loader
64 | {
65 | enforce: 'pre',
66 | test: /\.js$/,
67 | exclude: /node_modules/,
68 | use: 'eslint-loader'
69 | },
70 | {
71 | test: /\.js$/,
72 | exclude: /node_modules/,
73 | use: 'babel-loader',
74 | },
75 | {
76 | test: /\.scss$/,
77 | use: ['style-loader', 'css-loader', 'postcss-loader?pack=cleaner', 'sass-loader?outputStyle=expanded'],
78 | }
79 | ]
80 | },
81 |
82 | plugins: [
83 | new webpack.HotModuleReplacementPlugin(), // 热部署替换模块
84 | new webpack.NoEmitOnErrorsPlugin(),
85 | new webpack.LoaderOptionsPlugin({
86 | debug: true,
87 | options: {
88 | // eslint 配置
89 | eslint: {
90 | emitError: true, // 验证失败,终止
91 | configFile: '.eslintrc'
92 | },
93 | postcss () {
94 | return {
95 | defaults: [precss, autoprefixer],
96 | cleaner: [autoprefixer({
97 | flexbox: 'no-2009',
98 | browsers: ['Chrome >= 35', 'Firefox >= 38',
99 | 'Android >= 4.3', 'iOS >=8', 'Safari >= 8']
100 | })]
101 | };
102 | },
103 | }
104 | })
105 | ]
106 | };
107 |
108 | //创建 HtmlWebpackPlugin 的实例
109 | // https://www.npmjs.com/package/html-webpack-plugin
110 | const {entry} = webpackConfig;
111 |
112 | // 为 HtmlwebpackPlugin 设置配置项,与 entry 键对应,根据需要设置其参数值
113 | const htmlwebpackPluginConfig = {
114 | index: {
115 | title: 'React AlloyTouch 例子'
116 | },
117 | simple: {
118 | title: 'React AlloyTouch 简单例子'
119 | },
120 | pull: {
121 | title: '下拉刷新,上拉加载更多'
122 | },
123 | 'header-footer': {
124 | title: '带头部和底部的下拉刷新,上拉加载更多'
125 | },
126 | carousel: {
127 | title: '轮播'
128 | },
129 | 'pull-carousel': {
130 | title: '下拉刷新中包含轮播图'
131 | },
132 | 'pull-carousel2': {
133 | title: '下拉刷新中包含轮播图2'
134 | },
135 | 'tabs-carousel': {
136 | title: '自定义轮播内容+tabs'
137 | }
138 | };
139 |
140 | for (const key in entry) {
141 | if (entry.hasOwnProperty(key) && key !== 'vendors') {
142 | webpackConfig.plugins.push(
143 | new HtmlwebpackPlugin({
144 | title: htmlwebpackPluginConfig[key].title,
145 | template: path.resolve(appPath, 'templates/layout.html'),
146 | filename: `${key}.html`,
147 | //chunks这个参数告诉插件要引用entry里面的哪几个入口
148 | chunks: [key, 'vendors'],
149 | //要把script插入到标签里
150 | inject: 'body'
151 | })
152 | );
153 | }
154 | }
155 |
156 | export default {
157 | webpackConfig,
158 | ip,
159 | port
160 | };
161 |
--------------------------------------------------------------------------------
/webpack.config.example.dist.babel.js:
--------------------------------------------------------------------------------
1 | import path from 'path';
2 | import webpack from 'webpack';
3 | import ExtractTextPlugin from 'extract-text-webpack-plugin';
4 | import HtmlwebpackPlugin from 'html-webpack-plugin';
5 | import precss from 'precss';
6 | import autoprefixer from 'autoprefixer';
7 |
8 | const appPath = path.resolve(__dirname, 'examples');
9 |
10 | // multiple extract instances
11 | const extractSass = new ExtractTextPlugin({
12 | filename: 'css/[name].[chunkhash].css',
13 | disable: false,
14 | allChunks: true
15 | });
16 |
17 | const webpackConfig = {
18 | devtool: 'source-map', //生成 source map文件
19 | resolve: {
20 | //自动扩展文件后缀名
21 | extensions: ['.js', '.jsx', '.scss']
22 | },
23 |
24 | // 入口文件 让webpack用哪个文件作为项目的入口
25 | entry: {
26 | index: ['./examples/index.js'],
27 | simple: ['./examples/simple.js'],
28 | pull: ['./examples/pull.js'],
29 | 'header-footer': ['./examples/header-footer.js'],
30 | carousel: ['./examples/carousel.js'],
31 | 'pull-carousel': ['./examples/pull-carousel.js'],
32 | 'pull-carousel2': ['./examples/pull-carousel2.js'],
33 | 'tabs-carousel': ['./examples/tabs-carousel.js']
34 | },
35 |
36 | // 出口 让webpack把处理完成的文件放在哪里
37 | output: {
38 | path: path.resolve(__dirname, 'examples-dist'), //打包输出目录
39 | filename: '[name].[hash].bundle.js', //文件名称
40 | publicPath: './' //资源路径
41 | },
42 |
43 | module: {
44 | rules: [
45 | {
46 | test: /\.js$/,
47 | exclude: /node_modules/,
48 | use: 'babel-loader',
49 | },
50 | {
51 | test: /\.scss$/,
52 | use: ExtractTextPlugin.extract({
53 | fallback: 'style-loader',
54 | use: ['css-loader', 'postcss-loader?pack=cleaner', 'sass-loader?outputStyle=expanded'],
55 | publicPath: '/dist'
56 | })
57 | }
58 | ],
59 | },
60 |
61 | plugins: [
62 | // http://webpack.github.io/docs/list-of-plugins.html#uglifyjsplugin
63 | //用来优化生成的代码 chunk,合并相同的代码
64 | new webpack.optimize.AggressiveMergingPlugin(),
65 | //用来保证编译过程不出错
66 | new webpack.NoEmitOnErrorsPlugin(),
67 | extractSass,
68 | //http://dev.topheman.com/make-your-react-production-minified-version-with-webpack/
69 | new webpack.DefinePlugin({
70 | 'process.env': {
71 | NODE_ENV: JSON.stringify('production')
72 | }
73 | }),
74 | // http://webpack.github.io/docs/list-of-plugins.html#uglifyjsplugin
75 | // 相当于命令参数 --optimize-minimize
76 | new webpack.optimize.UglifyJsPlugin({
77 | sourceMap: true,
78 | compress: {
79 | warnings: true
80 | },
81 | mangle: {
82 | except: [] // 设置不混淆变量名
83 | }
84 | }),
85 | new webpack.LoaderOptionsPlugin({
86 | minimize: true,
87 | options: {
88 | postcss () {
89 | return {
90 | defaults: [precss, autoprefixer],
91 | cleaner: [autoprefixer({
92 | flexbox: 'no-2009',
93 | browsers: ['Chrome >= 35', 'Firefox >= 38',
94 | 'Android >= 4.3', 'iOS >=8', 'Safari >= 8']
95 | })]
96 | };
97 | },
98 | }
99 | })
100 | ]
101 | };
102 |
103 | //创建 HtmlWebpackPlugin 的实例
104 | // https://www.npmjs.com/package/html-webpack-plugin
105 | const {entry} = webpackConfig;
106 |
107 | // 为 HtmlwebpackPlugin 设置配置项,与 entry 键对应,根据需要设置其参数值
108 | const htmlwebpackPluginConfig = {
109 | index: {
110 | title: 'React AlloyTouch 例子'
111 | },
112 | simple: {
113 | title: 'React AlloyTouch 简单例子'
114 | },
115 | pull: {
116 | title: '下拉刷新,上拉加载更多'
117 | },
118 | 'header-footer': {
119 | title: '带头部和底部的下拉刷新,上拉加载更多'
120 | },
121 | carousel: {
122 | title: '轮播'
123 | },
124 | 'pull-carousel': {
125 | title: '下拉刷新中包含轮播图'
126 | },
127 | 'pull-carousel2': {
128 | title: '下拉刷新中包含轮播图2'
129 | },
130 | 'tabs-carousel': {
131 | title: '自定义轮播内容+tabs'
132 | }
133 | };
134 |
135 | for (const key in entry) {
136 | if (entry.hasOwnProperty(key) && key !== 'vendors') {
137 | webpackConfig.plugins.push(
138 | new HtmlwebpackPlugin({
139 | title: htmlwebpackPluginConfig[key].title,
140 | template: path.resolve(appPath, 'templates/layout.html'),
141 | filename: `${key}.html`,
142 | //chunks这个参数告诉插件要引用entry里面的哪几个入口
143 | chunks: [key, 'vendors'],
144 | //要把script插入到标签里
145 | inject: 'body'
146 | })
147 | );
148 | }
149 | }
150 |
151 | export default webpackConfig;
152 |
--------------------------------------------------------------------------------