├── .babelrc
├── .gitignore
├── .travis.yml
├── LICENSE
├── README.md
├── README.quick.md
├── README.quick.zh-CN.md
├── config
├── webpack.base.config.js
├── webpack.dev.config.js
├── webpack.page.config.js
├── webpack.pro.config.js
└── webpack.test.config.js
├── coverage
├── lcov-report
│ ├── base.css
│ ├── components
│ │ └── index.html
│ ├── index.html
│ ├── prettify.css
│ ├── prettify.js
│ ├── sort-arrow-sprite.png
│ └── sorter.js
└── lcov.info
├── dist
└── main.js
├── index.html
├── index.js
├── karma.conf.js
├── package-lock.json
├── package.json
├── postcss.config.js
├── src
├── GarenLoadmore.vue
└── index.js
├── static
├── loadmoregif.gif
├── shanglajiazai.jpg
├── shifangshuaxin.jpg
├── wugengduoshuju.jpg
├── xialashuaxin.jpg
└── zhengzaishuaxin.jpg
└── test
├── LoadMore.spec.js
├── setup.js
└── utils.js
/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": [
3 | ["env",
4 | {
5 | "target": {
6 | "browsers": [ "iOS >= 7","Android >= 4"
7 | ]
8 | }
9 | }
10 | ]
11 | ],
12 | "plugins": [
13 | [
14 | "transform-runtime",
15 | {
16 | "helpers": false,
17 | "polyfill": false,
18 | "regenerator": true,
19 | "moduleName": "babel-runtime"
20 | }
21 | ]
22 | ]
23 | }
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules/
2 | .cache/
3 | .vscode/
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: node_js
2 | node_js:
3 | - "8"
4 | - "9"
5 |
6 | addons:
7 | chrome: stable
8 | sudo: required
9 | before_script:
10 | - "sudo chown root /opt/google/chrome/chrome-sandbox"
11 | - "sudo chmod 4755 /opt/google/chrome/chrome-sandbox"
12 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2018 duyanpeng
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 | # garen-loadmore
2 | [](https://travis-ci.org/duyanpeng/vue-quick-loadmore)
3 | 
4 | [](https://www.jsdelivr.com/package/npm/vue-quick-loadmore)
5 |
6 | vue移动端下拉刷新上拉无限滚动加载插件,支持更换loading图片,保存设置滚动距离等。
7 |
8 | 默认样式如下,可根据状态更换loading图片或提示文案。
9 |
10 | 
11 |
12 | ## 文档
13 | 更多vue移动端组件,欢迎使用: [garen-ui](https://duyanpeng.github.io/garen/)
14 |
15 | 原vue-quick-loadmore文档:[vue-quick-loadmore中文文档](https://github.com/duyanpeng/vue-quick-loadmore/blob/master/README.quick.zh-CN.md)
16 |
17 |
18 | ## 安装
19 | ---
20 | `npm install garen-loadmore -S`
21 |
22 | ```
23 | // 引入方式
24 | import Vue from 'vue';
25 | import GarenLoadmore from 'garen-loadmore';
26 |
27 | Vue.use(GarenLoadmore)
28 | ```
29 |
30 | ```html
31 |
32 |
33 |
34 |
35 |
36 |
37 |
41 | ```
42 | ## 示例
43 | ---
44 |
45 | ```vue
46 |
47 |
48 |
51 |
60 | {{index}}
61 |
62 |
63 |
64 |
65 |
172 |
190 | ```
191 | ## API
192 |
193 | ### 下拉刷新配置
194 | ---
195 | 参数|类型|说明|备注
196 | :--:|:--:|:--:|:--:
197 | :disableTop|Boolean|禁止下拉刷新|默认:false
198 | :distanceIndex|Number|手指滑动与页面滑动比例|默认:2
199 | :topLoadingDistance|Number|loading状态时页面距顶部距离|默认:50
200 | :topDistance|Number|下拉刷新触发值|默认:100
201 | :top-change-text|Object|下拉刷新提示文案|见示例代码
202 | @top-method|Function|下拉刷新触发方法|
203 | @top-status-change|Function|下拉刷新状态改变回调|五种状态具体见示例代码
204 | ref.onTopLoaded|Function|下拉刷新完成时调用函数,参数是完成状态等待时间ms|通过ref使用具体见示例代码
205 | ---
206 | ### 上拉加载配置:
207 | 参数|类型|说明|备注
208 | :--:|:--:|:--:|:--:
209 | :disableBttom|Boolean|禁止上拉加载|默认:false
210 | :bottomDistance|Number|上拉加载触发值|默认:10
211 | :bottom-change-text|Object|上拉加载提示文案|见示例代码
212 | @bottom-method|Function|上拉加载触发方法|
213 | @bottom-status-change|Function|上拉加载状态改变回调|四种状态具体见示例代码
214 | @bottom-error-click|Function|数据请求出错点击触发方法|
215 | :eventScroll|Function|scroll事件回调|用于监听scroll事件
216 | ref.onBottomLoaded(boolean = true)|Function|上拉加载完成时调用函数|通过ref使用具体见示例代码(注意:如果下拉加载之后是无更多数据状态,函数传参为false,此后不在触发上拉刷新方法,下拉刷新之后会自动开启上拉加载)
217 | ref.onBottomError()|Function|上拉加载出错时调用函数|通过ref使用具体见示例代码
218 | ---
219 | ### 其他配置:
220 | 参数|类型|说明|备注
221 | :--:|:--:|:--:|:--:
222 | ref.getScrollTop|Function|获得滚动距离|具体见示例代码
223 | ref.setScroolTop(y)|Function|设置滚动距离|具体见示例代码
224 | ---
225 | ### 替换下拉刷新下拉加载loading图方法:
226 |
227 | ```html
228 |
229 | 根据topStatusChange返回的状态,设置topLoadingDistance高度,通过margin-top:负高度定位图片,渲染下拉刷新不同阶段的样式
230 |
231 |
232 | 根据bottomStatusChange返回的状态,渲染上拉加载不同阶段的样式
233 |
234 |
235 | ```
236 | ```css
237 | /* 参考自定义样式css */
238 | .garen-loadmore-header {
239 | margin-top: -50px;
240 | height: 50px;
241 | line-height: 50px;
242 | text-align: center;
243 | font-size: 14px;
244 | color: #666666;
245 | letter-spacing: -0.31px;
246 | }
247 | .garen-loadmore-footer {
248 | height: 50px;
249 | line-height: 50px;
250 | text-align: center;
251 | font-size: 13px;
252 | color: #666666;
253 | letter-spacing: -0.31px;
254 | }
255 |
256 | ```
257 |
258 | ## 版本更新说明
259 | ---
260 | 版本号|说明|
261 | :--:|:--:|
262 | 1.0.0|正式版本
263 | 0.1.0|项目发布
264 |
265 | ## 联系我
266 | ---
267 | QQ群:257216865
268 | 邮箱:215028726@qq.com
269 |
--------------------------------------------------------------------------------
/README.quick.md:
--------------------------------------------------------------------------------
1 | # vue-quick-loadmore
2 | [](https://travis-ci.org/duyanpeng/vue-quick-loadmore)
3 | 
4 |
5 | A pull-down refresh and pull-up infinite scroll component for Vue.js,support to replace loading images, save and settings scrolling distance and so on
6 |
7 | [zh-CN中文文档](https://github.com/duyanpeng/vue-quick-loadmore/blob/master/README.zh-CN.md)
8 |
9 | The default style is as follows, you can change the loading picture or text according to the status.
10 |
11 | 
12 |
13 |
14 | ## Install
15 | ---
16 | `npm install vue-quick-loadmore -S`
17 |
18 | ```
19 | // how to use
20 | import Vue from 'vue';
21 | import VueQuickLoadmore from 'vue-quick-loadmore';
22 |
23 | Vue.use(VueQuickLoadmore)
24 | ```
25 |
26 | ## Use
27 | ---
28 | ```html
29 |
30 |
31 |
33 |
38 | {{index}}
39 |
40 |
41 |
42 | ```
43 | ```javascript
44 | export default {
45 | name: "Message",
46 | data() {
47 | return {
48 | dataList: [1, 2, 3, 4, 5]
49 | };
50 | },
51 | // Implement the go to the details page to return to the list location function - with keep-alive
52 | beforeRouteLeave(to, from, next) {
53 | // if enter detail
54 | if (to.name === "MessageDetail") {
55 | // Get scrolling distance
56 | let scrollTop = this.$refs.vueLoad.getScrollTop();
57 | // Setting the cache
58 | sessionStorage.setItem("messageScrollTop", scrollTop);
59 | } else {
60 | // remore the cache
61 | sessionStorage.removeItem("messageScrollTop");
62 | }
63 | next();
64 | },
65 | activated() {
66 | let scrollTop = sessionStorage.getItem("messageScrollTop");
67 | // where from ?
68 | if (scrollTop == null) {
69 | console.log("不需要缓存的页面");
70 | } else {
71 | // need record -- scroll
72 | this.$refs.vueLoad.setScrollTop(scrollTop);
73 | }
74 | },
75 | deactivated() {
76 |
77 | },
78 | methods: {
79 | handleTop() {
80 | // pull-down refresh
81 | // mock data
82 | setTimeout(() => {
83 | this.dataList = [1, 2, 3, 4, 5];
84 | // scroll to top
85 | this.$refs.vueLoad.onTopLoaded();
86 | }, 1000);
87 | },
88 | handleStatusChange(status) {
89 | // status change
90 | const TOPSTATUS = {
91 | wait: "wait",
92 | pulling: "pulling",
93 | limit: "limit",
94 | loading: "loading"
95 | };
96 | console.log(status, "statuschange");
97 | },
98 | handleBottomStatusChange(status) {
99 | // status change
100 | const BOTTOMSTATUS = {
101 | wait: "wait",
102 | loading: "loading",
103 | nodata: "nodata"
104 | };
105 | console.log(status, "bottomchange");
106 | },
107 | handleBottom() {
108 | // pull-up infinite
109 | // mock data
110 | setTimeout(() => {
111 | this.dataList.push(1, 2, 3);
112 | // have more data ? false: this.$refs.vueLoad.onBottomLoaded(false))
113 | // scroll to bottom
114 | this.$refs.vueLoad.onBottomLoaded();
115 | }, 1000);
116 | }
117 | },
118 | mounted() {
119 | // console.log("mounted");
120 | }
121 | };
122 | ```
123 | ```css
124 | *{
125 | margin:0;
126 | padding:0;
127 | }
128 | html,body,#app{
129 | height:100%;
130 | overflow: hidden;
131 | }
132 | .item{
133 | height:200px;
134 | background: lightgray;
135 | border:2px solid green;
136 | overflow: hidden;
137 | }
138 | ```
139 |
140 | ### Pull-down options
141 | ---
142 | params|type|description|note
143 | :--:|:--:|:--:|:--:
144 | v-bind:disableTop|Boolean|Disable pull-down refresh|default:false
145 | v-bind:distanceIndex|Number|Scrolling ratio|default:2
146 | v-bind:topLoadingDistance|Number|Loading distance|default:50
147 | v-bind:topDistance|Number|Pull-down refresh trigger value|default:100
148 | v-bind:topMethod|Function|Pull-down refresh trigger method|
149 | v-bind:topStatusChange|Function|Pull-down status change|look for example
150 | ref.onTopLoaded|Function|Pull-down complete|use ref api
151 | ---
152 | ### Pull-up options:
153 | params|type|description|note
154 | :--:|:--:|:--:|:--:
155 | v-bind:disableBttom|Boolean|Disable pull-up|default:false
156 | v-bind:bottomDistance|Number|Loading distance|default:10
157 | v-bind:bottomMethod|Function|Pull-up trigger method|
158 | v-bind:bottomStatusChange|Function|Pull-up status change|look for example
159 | v-bind:eventScroll|Function|Scroll event callback|Used to listen for scroll events
160 | ref.onBottomLoaded(boolean = true)|Function|Pull-up complete|use ref api
161 | ---
162 | ### Other options:
163 | params|type|description|note
164 | :--:|:--:|:--:|:--:
165 | ref.getScrollTop|Function|get scroll distance|look for example
166 | ref.setScroolTop(y)|Function|scroll to distance|look for example
167 | ---
168 | ### How to replace loading image:
169 |
170 | ```html
171 |
172 | according to topStatusChange,change image
173 |
174 |
175 | according to bottomStatusChange,change image
176 |
177 |
178 | ```
179 |
180 |
181 |
--------------------------------------------------------------------------------
/README.quick.zh-CN.md:
--------------------------------------------------------------------------------
1 | # vue-quick-loadmore
2 | [](https://travis-ci.org/duyanpeng/vue-quick-loadmore)
3 | 
4 | [](https://www.jsdelivr.com/package/npm/vue-quick-loadmore)
5 |
6 | vue移动端下拉刷新上拉无限滚动加载插件,支持更换loading图片,保存设置滚动距离等。
7 |
8 | 默认样式如下,可根据状态更换loading图片或提示文案。
9 |
10 | 
11 |
12 |
13 | ## 安装
14 | ---
15 | `npm install vue-quick-loadmore -S`
16 |
17 | ```
18 | // 引入方式
19 | import Vue from 'vue';
20 | import VueQuickLoadmore from 'vue-quick-loadmore';
21 |
22 | Vue.use(VueQuickLoadmore)
23 | ```
24 |
25 | ## 使用
26 | ---
27 | ```html
28 |
29 |
30 |
33 |
38 | {{index}}
39 |
40 |
41 |
42 | ```
43 | ```javascript
44 | export default {
45 | name: "Message",
46 | data() {
47 | return {
48 | dataList: [1, 2, 3, 4, 5]
49 | };
50 | },
51 | // 实现进入详情页返回列表位置功能-搭配keep-alive
52 | beforeRouteLeave(to, from, next) {
53 | // 如果进入详情页
54 | if (to.name === "MessageDetail") {
55 | // 获得滚动距离
56 | let scrollTop = this.$refs.vueLoad.getScrollTop();
57 | // 设置缓存
58 | sessionStorage.setItem("messageScrollTop", scrollTop);
59 | } else {
60 | // 如果去其他页移除缓存
61 | sessionStorage.removeItem("messageScrollTop");
62 | }
63 | next();
64 | },
65 | activated() {
66 | // 激活路由
67 | let scrollTop = sessionStorage.getItem("messageScrollTop");
68 | // 判断来源
69 | if (scrollTop == null) {
70 | console.log("不需要缓存的页面");
71 | } else {
72 | // 需要缓存的页面,滚动
73 | this.$refs.vueLoad.setScrollTop(scrollTop);
74 | }
75 | },
76 | deactivated() {
77 |
78 | },
79 | methods: {
80 | handleTop() {
81 | // 下拉刷新
82 | // 定时器用来模拟下拉刷新接口延迟时间
83 | setTimeout(() => {
84 | // 模拟数据更新
85 | this.dataList = [1, 2, 3, 4, 5];
86 | // 数据跟新完调用该方法使quick-loadmore滚到顶部
87 | this.$refs.vueLoad.onTopLoaded();
88 | }, 1000);
89 | },
90 | handleStatusChange(status) {
91 | // status监控下拉刷新状态--等待/下拉/到达阙值/刷新
92 | const TOPSTATUS = {
93 | wait: "wait",
94 | pulling: "pulling",
95 | limit: "limit",
96 | loading: "loading"
97 | };
98 | console.log(status, "statuschange");
99 | },
100 | handleBottomStatusChange(status) {
101 | // status监控上拉加载状态--等待/加载/没有更多数据
102 | const BOTTOMSTATUS = {
103 | wait: "wait",
104 | loading: "loading",
105 | nodata: "nodata"
106 | };
107 | console.log(status, "bottomchange");
108 | },
109 | handleBottom() {
110 | // 上拉加载
111 | // 定时器用来模拟上拉加载接口延迟时间
112 | setTimeout(() => {
113 | // 模拟数据更新
114 | this.dataList.push(1, 2, 3);
115 | // 数据跟新完调用该方法使数据加载中提示消失,(注意:如果没有更多数据参数传false: this.$refs.vueLoad.onBottomLoaded(false))
116 | this.$refs.vueLoad.onBottomLoaded();
117 | }, 1000);
118 | }
119 | },
120 | mounted() {
121 | // console.log("mounted");
122 | }
123 | };
124 | ```
125 | ```css
126 | *{
127 | margin:0;
128 | padding:0;
129 | }
130 | html,body,#app{
131 | height:100%;
132 | overflow: hidden;
133 | }
134 | .item{
135 | height:200px;
136 | background: lightgray;
137 | border:2px solid green;
138 | overflow: hidden;
139 | }
140 | ```
141 | ```html
142 |
143 |
144 |
145 |
146 |
147 |
148 |
152 |
153 |
154 | ```
155 |
156 | ### 下拉刷新配置
157 | ---
158 | 参数|类型|说明|备注
159 | :--:|:--:|:--:|:--:
160 | v-bind:disableTop|Boolean|禁止下拉刷新|默认:false
161 | v-bind:distanceIndex|Number|手指滑动与页面滑动比例|默认:2
162 | v-bind:topLoadingDistance|Number|loading状态时页面距顶部距离|默认:50
163 | v-bind:topDistance|Number|下拉刷新触发值|默认:100
164 | v-bind:topMethod|Function|下拉刷新触发方法|
165 | v-bind:topStatusChange|Function|下拉刷新状态改变回调|四种状态具体见示例代码
166 | ref.onTopLoaded|Function|下拉刷新完成时调用函数|通过ref使用具体见示例代码
167 | ---
168 | ### 上拉加载配置:
169 | 参数|类型|说明|备注
170 | :--:|:--:|:--:|:--:
171 | v-bind:disableBttom|Boolean|禁止上拉加载|默认:false
172 | v-bind:bottomDistance|Number|上拉加载触发值|默认:10
173 | v-bind:bottomMethod|Function|上拉加载触发方法|
174 | v-bind:bottomStatusChange|Function|上拉加载状态改变回调|三种状态具体见示例代码
175 | v-bind:eventScroll|Function|scroll事件回调|用于监听scroll事件
176 | ref.onBottomLoaded(boolean = true)|Function|上拉加载完成时调用函数|通过ref使用具体见示例代码(注意:如果下拉加载之后是无更多数据状态,函数传参为false,此后不在触发上拉刷新方法,下拉刷新之后会自动开启上拉加载)
177 | ---
178 | ### 其他配置:
179 | 参数|类型|说明|备注
180 | :--:|:--:|:--:|:--:
181 | ref.getScrollTop|Function|获得滚动距离|具体见示例代码
182 | ref.setScroolTop(y)|Function|设置滚动距离|具体见示例代码
183 | ---
184 | ### 替换下拉刷新下拉加载loading图方法:
185 |
186 | ```html
187 |
188 | 根据topStatusChange返回的状态,设置topLoadingDistance高度,通过margin-top:负高度定位图片,渲染下拉刷新不同阶段的样式
189 |
190 |
191 | 根据bottomStatusChange返回的状态,渲染上拉加载不同阶段的样式
192 |
193 |
194 | ```
195 | ## 提示
196 | 更好用的loadmore组件,及更多vue移动端组件,欢迎使用: [garen-ui](https://duyanpeng.github.io/garen/)
197 |
198 | ## 版本更新说明
199 | ---
200 | 版本号|说明|
201 | :--:|:--:|
202 | 1.0.3|增加script标签直接引入方式使用
203 | 1.0.0|更换打包方式
204 | 0.0.6|修复下拉误点击bug
205 | 0.0.5|更新文档
206 | 0.0.4|解决命令行报错问题
207 | 0.0.3|用vue-cli时命令行会报警告,不影响正常使用,以后修复。
208 | 0.0.2|更新文档
209 | 0.0.1|项目初始化
210 |
211 | ## 联系我
212 | ---
213 | QQ群:257216865
214 |
--------------------------------------------------------------------------------
/config/webpack.base.config.js:
--------------------------------------------------------------------------------
1 | const path = require('path')
2 | const VueLoaderPlugin = require('vue-loader/lib/plugin');
3 | module.exports = {
4 | output: {
5 | path: path.resolve(__dirname, '../dist'),
6 | filename: '[name].js'
7 | },
8 | plugins: [
9 | new VueLoaderPlugin()
10 | ],
11 | module: {
12 | rules: [
13 | {
14 | test: /\.js$/,
15 | exclude: /(node_modules|bower_components)/,
16 | use: {
17 | loader: 'babel-loader'
18 | }
19 | },
20 |
21 | {
22 | test: /\.vue$/,
23 | use: [
24 | {
25 | loader: 'vue-loader',
26 | options: {}
27 | }
28 | ]
29 |
30 | }
31 | ]
32 |
33 | },
34 | resolve: {
35 | alias: {
36 | 'vue$': 'vue/dist/vue.common.js'
37 | }
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/config/webpack.dev.config.js:
--------------------------------------------------------------------------------
1 | const path = require('path');
2 | const HtmlWebpackPlugin = require('html-webpack-plugin');
3 | const VueLoaderPlugin = require('vue-loader/lib/plugin');
4 | const WebpackBaseConfig = require('./webpack.base.config.js');
5 | const WebpackMerge = require('webpack-merge')
6 |
7 | module.exports = WebpackMerge(WebpackBaseConfig,{
8 | entry: './index.js',
9 | mode:'development',
10 | plugins:[
11 | new HtmlWebpackPlugin({
12 | template: './index.html'
13 | }),
14 | ],
15 | module:{
16 | rules:[
17 | {
18 | test: /\.css$/, use: [
19 | { loader: 'style-loader' },
20 | {
21 | loader: 'css-loader',
22 | },
23 | {
24 | loader:'postcss-loader'
25 | }
26 | ]
27 | },
28 | {
29 | test: /\.less$/, use: [
30 | { loader: 'style-loader' },
31 | {
32 | loader: 'css-loader',
33 | },
34 | {
35 | loader:'postcss-loader'
36 | },{
37 | loader:'less-loader'
38 | }
39 | ]
40 | }
41 | ]
42 | },
43 | devServer: {
44 | overlay: true,
45 | disableHostCheck: true,
46 | host:'0.0.0.0',
47 | port: 9000
48 | }
49 | })
50 |
--------------------------------------------------------------------------------
/config/webpack.page.config.js:
--------------------------------------------------------------------------------
1 | const path = require('path');
2 | const HtmlWebpackPlugin = require('html-webpack-plugin');
3 | const CleanWebpackPlugin = require('clean-webpack-plugin');
4 | const VueLoaderPlugin = require('vue-loader/lib/plugin');
5 | const WebpackBaseConfig = require('./webpack.base.config.js');
6 | const WebpackMerge = require('webpack-merge')
7 | const ExtractTextPlugin = require("extract-text-webpack-plugin");
8 | module.exports = WebpackMerge(WebpackBaseConfig, {
9 | entry: './index.js',
10 | output: {
11 | path: path.resolve(__dirname, '../build'),
12 | filename: '[name].[chunkhash].js',
13 | },
14 | mode: 'production',
15 | module:{
16 | rules:[
17 | {
18 | test: /\.css$/,
19 | use: ExtractTextPlugin.extract({
20 | fallback: "style-loader",
21 | use: ["css-loader","postcss-loader"]
22 | })
23 | // use: [
24 | // { loader: 'style-loader' },
25 | // {
26 | // loader: 'css-loader',
27 | // },
28 | // {
29 | // loader:'postcss-loader'
30 | // }
31 | // ]
32 | },
33 | {
34 | test: /\.less$/,
35 | use: ExtractTextPlugin.extract({
36 | fallback: "style-loader",
37 | use: ["css-loader","postcss-loader","less-loader"]
38 | })
39 | // use: [
40 | // { loader: 'style-loader' },
41 | // {
42 | // loader: 'css-loader',
43 | // },
44 | // {
45 | // loader:'postcss-loader'
46 | // },{
47 | // loader:'less-loader'
48 | // }
49 | // ]
50 | },
51 | ]
52 | },
53 | plugins: [
54 | new CleanWebpackPlugin(['build']),
55 | new ExtractTextPlugin("styles.css"),
56 | new HtmlWebpackPlugin({
57 | template: './index.html'
58 | }),
59 |
60 | ],
61 | optimization: {
62 | splitChunks: {
63 | // chunks:'all'
64 | cacheGroups: {
65 | commons: {
66 | test: /[\\/]node_modules[\\/]/,
67 | name: 'vendors',
68 | chunks: 'all'
69 | }
70 | }
71 | }
72 | }
73 | })
74 |
--------------------------------------------------------------------------------
/config/webpack.pro.config.js:
--------------------------------------------------------------------------------
1 | const path = require('path');
2 | const HtmlWebpackPlugin = require('html-webpack-plugin');
3 | const CleanWebpackPlugin = require('clean-webpack-plugin');
4 | const VueLoaderPlugin = require('vue-loader/lib/plugin');
5 | const WebpackBaseConfig = require('./webpack.base.config.js');
6 | const WebpackMerge = require('webpack-merge')
7 |
8 | module.exports = WebpackMerge(WebpackBaseConfig,{
9 | entry:'./src/index.js',
10 | output:{
11 | path: path.resolve(__dirname, '../dist'),
12 | filename: '[name].js',
13 | library:'GarenLoadmore',
14 | libraryTarget:'umd',
15 | libraryExport: 'default'
16 | },
17 | module:{
18 | rules:[
19 | {
20 | test: /\.css$/, use: [
21 | { loader: 'style-loader' },
22 | {
23 | loader: 'css-loader',
24 | },
25 | {
26 | loader:'postcss-loader'
27 | }
28 | ]
29 | },
30 | {
31 | test: /\.less$/, use: [
32 | { loader: 'style-loader' },
33 | {
34 | loader: 'css-loader',
35 | },
36 | {
37 | loader:'postcss-loader'
38 | },{
39 | loader:'less-loader'
40 | }
41 | ]
42 | },
43 | ]
44 | },
45 | plugins:[
46 | new CleanWebpackPlugin(['dist'])
47 | ],
48 | mode:'production',
49 | })
50 |
--------------------------------------------------------------------------------
/config/webpack.test.config.js:
--------------------------------------------------------------------------------
1 | const path = require('path');
2 | const HtmlWebpackPlugin = require('html-webpack-plugin');
3 | const VueLoaderPlugin = require('vue-loader/lib/plugin');
4 | const WebpackBaseConfig = require('./webpack.base.config.js');
5 | const WebpackMerge = require('webpack-merge')
6 | const nodeExternals = require('webpack-node-externals');
7 |
8 | module.exports = WebpackMerge(WebpackBaseConfig,{
9 | entry: './index.js',
10 | mode:'production',
11 | output:{
12 | devtoolModuleFilenameTemplate: '[absolute-resource-path]',
13 | devtoolFallbackModuleFilenameTemplate: '[absolute-resource-path]?[hash]'
14 | },
15 | plugins:[
16 | new HtmlWebpackPlugin({
17 | template: './index.html'
18 | }),
19 | ],
20 | module:{
21 | rules:[
22 | {
23 | test: /\.css$/, use: [
24 | { loader: 'style-loader' },
25 | {
26 | loader: 'css-loader',
27 | },
28 | {
29 | loader:'postcss-loader'
30 | }
31 | ]
32 | },
33 | {
34 | test: /\.less$/, use: [
35 | { loader: 'style-loader' },
36 | {
37 | loader: 'css-loader',
38 | },
39 | {
40 | loader:'postcss-loader'
41 | },{
42 | loader:'less-loader'
43 | }
44 | ]
45 | }
46 | ]
47 | },
48 | devServer: {
49 | overlay: true,
50 | disableHostCheck: true,
51 | port: 9000
52 | },
53 | devtool: 'inline-cheap-module-source-map',
54 | // target: 'node',
55 | // externals: [nodeExternals()]
56 | })
57 |
--------------------------------------------------------------------------------
/coverage/lcov-report/base.css:
--------------------------------------------------------------------------------
1 | body, html {
2 | margin:0; padding: 0;
3 | height: 100%;
4 | }
5 | body {
6 | font-family: Helvetica Neue, Helvetica, Arial;
7 | font-size: 14px;
8 | color:#333;
9 | }
10 | .small { font-size: 12px; }
11 | *, *:after, *:before {
12 | -webkit-box-sizing:border-box;
13 | -moz-box-sizing:border-box;
14 | box-sizing:border-box;
15 | }
16 | h1 { font-size: 20px; margin: 0;}
17 | h2 { font-size: 14px; }
18 | pre {
19 | font: 12px/1.4 Consolas, "Liberation Mono", Menlo, Courier, monospace;
20 | margin: 0;
21 | padding: 0;
22 | -moz-tab-size: 2;
23 | -o-tab-size: 2;
24 | tab-size: 2;
25 | }
26 | a { color:#0074D9; text-decoration:none; }
27 | a:hover { text-decoration:underline; }
28 | .strong { font-weight: bold; }
29 | .space-top1 { padding: 10px 0 0 0; }
30 | .pad2y { padding: 20px 0; }
31 | .pad1y { padding: 10px 0; }
32 | .pad2x { padding: 0 20px; }
33 | .pad2 { padding: 20px; }
34 | .pad1 { padding: 10px; }
35 | .space-left2 { padding-left:55px; }
36 | .space-right2 { padding-right:20px; }
37 | .center { text-align:center; }
38 | .clearfix { display:block; }
39 | .clearfix:after {
40 | content:'';
41 | display:block;
42 | height:0;
43 | clear:both;
44 | visibility:hidden;
45 | }
46 | .fl { float: left; }
47 | @media only screen and (max-width:640px) {
48 | .col3 { width:100%; max-width:100%; }
49 | .hide-mobile { display:none!important; }
50 | }
51 |
52 | .quiet {
53 | color: #7f7f7f;
54 | color: rgba(0,0,0,0.5);
55 | }
56 | .quiet a { opacity: 0.7; }
57 |
58 | .fraction {
59 | font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace;
60 | font-size: 10px;
61 | color: #555;
62 | background: #E8E8E8;
63 | padding: 4px 5px;
64 | border-radius: 3px;
65 | vertical-align: middle;
66 | }
67 |
68 | div.path a:link, div.path a:visited { color: #333; }
69 | table.coverage {
70 | border-collapse: collapse;
71 | margin: 10px 0 0 0;
72 | padding: 0;
73 | }
74 |
75 | table.coverage td {
76 | margin: 0;
77 | padding: 0;
78 | vertical-align: top;
79 | }
80 | table.coverage td.line-count {
81 | text-align: right;
82 | padding: 0 5px 0 20px;
83 | }
84 | table.coverage td.line-coverage {
85 | text-align: right;
86 | padding-right: 10px;
87 | min-width:20px;
88 | }
89 |
90 | table.coverage td span.cline-any {
91 | display: inline-block;
92 | padding: 0 5px;
93 | width: 100%;
94 | }
95 | .missing-if-branch {
96 | display: inline-block;
97 | margin-right: 5px;
98 | border-radius: 3px;
99 | position: relative;
100 | padding: 0 4px;
101 | background: #333;
102 | color: yellow;
103 | }
104 |
105 | .skip-if-branch {
106 | display: none;
107 | margin-right: 10px;
108 | position: relative;
109 | padding: 0 4px;
110 | background: #ccc;
111 | color: white;
112 | }
113 | .missing-if-branch .typ, .skip-if-branch .typ {
114 | color: inherit !important;
115 | }
116 | .coverage-summary {
117 | border-collapse: collapse;
118 | width: 100%;
119 | }
120 | .coverage-summary tr { border-bottom: 1px solid #bbb; }
121 | .keyline-all { border: 1px solid #ddd; }
122 | .coverage-summary td, .coverage-summary th { padding: 10px; }
123 | .coverage-summary tbody { border: 1px solid #bbb; }
124 | .coverage-summary td { border-right: 1px solid #bbb; }
125 | .coverage-summary td:last-child { border-right: none; }
126 | .coverage-summary th {
127 | text-align: left;
128 | font-weight: normal;
129 | white-space: nowrap;
130 | }
131 | .coverage-summary th.file { border-right: none !important; }
132 | .coverage-summary th.pct { }
133 | .coverage-summary th.pic,
134 | .coverage-summary th.abs,
135 | .coverage-summary td.pct,
136 | .coverage-summary td.abs { text-align: right; }
137 | .coverage-summary td.file { white-space: nowrap; }
138 | .coverage-summary td.pic { min-width: 120px !important; }
139 | .coverage-summary tfoot td { }
140 |
141 | .coverage-summary .sorter {
142 | height: 10px;
143 | width: 7px;
144 | display: inline-block;
145 | margin-left: 0.5em;
146 | background: url(sort-arrow-sprite.png) no-repeat scroll 0 0 transparent;
147 | }
148 | .coverage-summary .sorted .sorter {
149 | background-position: 0 -20px;
150 | }
151 | .coverage-summary .sorted-desc .sorter {
152 | background-position: 0 -10px;
153 | }
154 | .status-line { height: 10px; }
155 | /* dark red */
156 | .red.solid, .status-line.low, .low .cover-fill { background:#C21F39 }
157 | .low .chart { border:1px solid #C21F39 }
158 | /* medium red */
159 | .cstat-no, .fstat-no, .cbranch-no, .cbranch-no { background:#F6C6CE }
160 | /* light red */
161 | .low, .cline-no { background:#FCE1E5 }
162 | /* light green */
163 | .high, .cline-yes { background:rgb(230,245,208) }
164 | /* medium green */
165 | .cstat-yes { background:rgb(161,215,106) }
166 | /* dark green */
167 | .status-line.high, .high .cover-fill { background:rgb(77,146,33) }
168 | .high .chart { border:1px solid rgb(77,146,33) }
169 | /* dark yellow (gold) */
170 | .medium .chart { border:1px solid #f9cd0b; }
171 | .status-line.medium, .medium .cover-fill { background: #f9cd0b; }
172 | /* light yellow */
173 | .medium { background: #fff4c2; }
174 | /* light gray */
175 | span.cline-neutral { background: #eaeaea; }
176 |
177 | .cbranch-no { background: yellow !important; color: #111; }
178 |
179 | .cstat-skip { background: #ddd; color: #111; }
180 | .fstat-skip { background: #ddd; color: #111 !important; }
181 | .cbranch-skip { background: #ddd !important; color: #111; }
182 |
183 |
184 | .cover-fill, .cover-empty {
185 | display:inline-block;
186 | height: 12px;
187 | }
188 | .chart {
189 | line-height: 0;
190 | }
191 | .cover-empty {
192 | background: white;
193 | }
194 | .cover-full {
195 | border-right: none !important;
196 | }
197 | pre.prettyprint {
198 | border: none !important;
199 | padding: 0 !important;
200 | margin: 0 !important;
201 | }
202 | .com { color: #999 !important; }
203 | .ignore-none { color: #999; font-weight: normal; }
204 |
205 | .wrapper {
206 | min-height: 100%;
207 | height: auto !important;
208 | height: 100%;
209 | margin: 0 auto -48px;
210 | }
211 | .footer, .push {
212 | height: 48px;
213 | }
214 |
--------------------------------------------------------------------------------
/coverage/lcov-report/components/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Code coverage report for components/
5 |
6 |
7 |
8 |
9 |
14 |
15 |
16 |
17 |
18 |
19 | all files components/
20 |
21 |
22 |
23 | 100%
24 | Statements
25 | 2/2
26 |
27 |
28 | 100%
29 | Branches
30 | 0/0
31 |
32 |
33 | 100%
34 | Functions
35 | 0/0
36 |
37 |
38 | 100%
39 | Lines
40 | 2/2
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 | File |
50 | |
51 | Statements |
52 | |
53 | Branches |
54 | |
55 | Functions |
56 | |
57 | Lines |
58 | |
59 |
60 |
61 |
62 | HelloWord.vue.js |
63 | |
64 | 100% |
65 | 2/2 |
66 | 100% |
67 | 0/0 |
68 | 100% |
69 | 0/0 |
70 | 100% |
71 | 2/2 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
82 |
83 |
84 |
91 |
92 |
93 |
94 |
--------------------------------------------------------------------------------
/coverage/lcov-report/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Code coverage report for All files
5 |
6 |
7 |
8 |
9 |
14 |
15 |
16 |
17 |
18 |
19 | /
20 |
21 |
22 |
23 | 100%
24 | Statements
25 | 0/0
26 |
27 |
28 | 100%
29 | Branches
30 | 0/0
31 |
32 |
33 | 100%
34 | Functions
35 | 0/0
36 |
37 |
38 | 100%
39 | Lines
40 | 0/0
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 | File |
50 | |
51 | Statements |
52 | |
53 | Branches |
54 | |
55 | Functions |
56 | |
57 | Lines |
58 | |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
69 |
70 |
71 |
78 |
79 |
80 |
81 |
--------------------------------------------------------------------------------
/coverage/lcov-report/prettify.css:
--------------------------------------------------------------------------------
1 | .pln{color:#000}@media screen{.str{color:#080}.kwd{color:#008}.com{color:#800}.typ{color:#606}.lit{color:#066}.pun,.opn,.clo{color:#660}.tag{color:#008}.atn{color:#606}.atv{color:#080}.dec,.var{color:#606}.fun{color:red}}@media print,projection{.str{color:#060}.kwd{color:#006;font-weight:bold}.com{color:#600;font-style:italic}.typ{color:#404;font-weight:bold}.lit{color:#044}.pun,.opn,.clo{color:#440}.tag{color:#006;font-weight:bold}.atn{color:#404}.atv{color:#060}}pre.prettyprint{padding:2px;border:1px solid #888}ol.linenums{margin-top:0;margin-bottom:0}li.L0,li.L1,li.L2,li.L3,li.L5,li.L6,li.L7,li.L8{list-style-type:none}li.L1,li.L3,li.L5,li.L7,li.L9{background:#eee}
2 |
--------------------------------------------------------------------------------
/coverage/lcov-report/prettify.js:
--------------------------------------------------------------------------------
1 | window.PR_SHOULD_USE_CONTINUATION=true;(function(){var h=["break,continue,do,else,for,if,return,while"];var u=[h,"auto,case,char,const,default,double,enum,extern,float,goto,int,long,register,short,signed,sizeof,static,struct,switch,typedef,union,unsigned,void,volatile"];var p=[u,"catch,class,delete,false,import,new,operator,private,protected,public,this,throw,true,try,typeof"];var l=[p,"alignof,align_union,asm,axiom,bool,concept,concept_map,const_cast,constexpr,decltype,dynamic_cast,explicit,export,friend,inline,late_check,mutable,namespace,nullptr,reinterpret_cast,static_assert,static_cast,template,typeid,typename,using,virtual,where"];var x=[p,"abstract,boolean,byte,extends,final,finally,implements,import,instanceof,null,native,package,strictfp,super,synchronized,throws,transient"];var R=[x,"as,base,by,checked,decimal,delegate,descending,dynamic,event,fixed,foreach,from,group,implicit,in,interface,internal,into,is,lock,object,out,override,orderby,params,partial,readonly,ref,sbyte,sealed,stackalloc,string,select,uint,ulong,unchecked,unsafe,ushort,var"];var r="all,and,by,catch,class,else,extends,false,finally,for,if,in,is,isnt,loop,new,no,not,null,of,off,on,or,return,super,then,true,try,unless,until,when,while,yes";var w=[p,"debugger,eval,export,function,get,null,set,undefined,var,with,Infinity,NaN"];var s="caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END";var I=[h,"and,as,assert,class,def,del,elif,except,exec,finally,from,global,import,in,is,lambda,nonlocal,not,or,pass,print,raise,try,with,yield,False,True,None"];var f=[h,"alias,and,begin,case,class,def,defined,elsif,end,ensure,false,in,module,next,nil,not,or,redo,rescue,retry,self,super,then,true,undef,unless,until,when,yield,BEGIN,END"];var H=[h,"case,done,elif,esac,eval,fi,function,in,local,set,then,until"];var A=[l,R,w,s+I,f,H];var e=/^(DIR|FILE|vector|(de|priority_)?queue|list|stack|(const_)?iterator|(multi)?(set|map)|bitset|u?(int|float)\d*)/;var C="str";var z="kwd";var j="com";var O="typ";var G="lit";var L="pun";var F="pln";var m="tag";var E="dec";var J="src";var P="atn";var n="atv";var N="nocode";var M="(?:^^\\.?|[+-]|\\!|\\!=|\\!==|\\#|\\%|\\%=|&|&&|&&=|&=|\\(|\\*|\\*=|\\+=|\\,|\\-=|\\->|\\/|\\/=|:|::|\\;|<|<<|<<=|<=|=|==|===|>|>=|>>|>>=|>>>|>>>=|\\?|\\@|\\[|\\^|\\^=|\\^\\^|\\^\\^=|\\{|\\||\\|=|\\|\\||\\|\\|=|\\~|break|case|continue|delete|do|else|finally|instanceof|return|throw|try|typeof)\\s*";function k(Z){var ad=0;var S=false;var ac=false;for(var V=0,U=Z.length;V122)){if(!(al<65||ag>90)){af.push([Math.max(65,ag)|32,Math.min(al,90)|32])}if(!(al<97||ag>122)){af.push([Math.max(97,ag)&~32,Math.min(al,122)&~32])}}}}af.sort(function(av,au){return(av[0]-au[0])||(au[1]-av[1])});var ai=[];var ap=[NaN,NaN];for(var ar=0;arat[0]){if(at[1]+1>at[0]){an.push("-")}an.push(T(at[1]))}}an.push("]");return an.join("")}function W(al){var aj=al.source.match(new RegExp("(?:\\[(?:[^\\x5C\\x5D]|\\\\[\\s\\S])*\\]|\\\\u[A-Fa-f0-9]{4}|\\\\x[A-Fa-f0-9]{2}|\\\\[0-9]+|\\\\[^ux0-9]|\\(\\?[:!=]|[\\(\\)\\^]|[^\\x5B\\x5C\\(\\)\\^]+)","g"));var ah=aj.length;var an=[];for(var ak=0,am=0;ak=2&&ai==="["){aj[ak]=X(ag)}else{if(ai!=="\\"){aj[ak]=ag.replace(/[a-zA-Z]/g,function(ao){var ap=ao.charCodeAt(0);return"["+String.fromCharCode(ap&~32,ap|32)+"]"})}}}}return aj.join("")}var aa=[];for(var V=0,U=Z.length;V=0;){S[ac.charAt(ae)]=Y}}var af=Y[1];var aa=""+af;if(!ag.hasOwnProperty(aa)){ah.push(af);ag[aa]=null}}ah.push(/[\0-\uffff]/);V=k(ah)})();var X=T.length;var W=function(ah){var Z=ah.sourceCode,Y=ah.basePos;var ad=[Y,F];var af=0;var an=Z.match(V)||[];var aj={};for(var ae=0,aq=an.length;ae=5&&"lang-"===ap.substring(0,5);if(am&&!(ai&&typeof ai[1]==="string")){am=false;ap=J}if(!am){aj[ag]=ap}}var ab=af;af+=ag.length;if(!am){ad.push(Y+ab,ap)}else{var al=ai[1];var ak=ag.indexOf(al);var ac=ak+al.length;if(ai[2]){ac=ag.length-ai[2].length;ak=ac-al.length}var ar=ap.substring(5);B(Y+ab,ag.substring(0,ak),W,ad);B(Y+ab+ak,al,q(ar,al),ad);B(Y+ab+ac,ag.substring(ac),W,ad)}}ah.decorations=ad};return W}function i(T){var W=[],S=[];if(T.tripleQuotedStrings){W.push([C,/^(?:\'\'\'(?:[^\'\\]|\\[\s\S]|\'{1,2}(?=[^\']))*(?:\'\'\'|$)|\"\"\"(?:[^\"\\]|\\[\s\S]|\"{1,2}(?=[^\"]))*(?:\"\"\"|$)|\'(?:[^\\\']|\\[\s\S])*(?:\'|$)|\"(?:[^\\\"]|\\[\s\S])*(?:\"|$))/,null,"'\""])}else{if(T.multiLineStrings){W.push([C,/^(?:\'(?:[^\\\']|\\[\s\S])*(?:\'|$)|\"(?:[^\\\"]|\\[\s\S])*(?:\"|$)|\`(?:[^\\\`]|\\[\s\S])*(?:\`|$))/,null,"'\"`"])}else{W.push([C,/^(?:\'(?:[^\\\'\r\n]|\\.)*(?:\'|$)|\"(?:[^\\\"\r\n]|\\.)*(?:\"|$))/,null,"\"'"])}}if(T.verbatimStrings){S.push([C,/^@\"(?:[^\"]|\"\")*(?:\"|$)/,null])}var Y=T.hashComments;if(Y){if(T.cStyleComments){if(Y>1){W.push([j,/^#(?:##(?:[^#]|#(?!##))*(?:###|$)|.*)/,null,"#"])}else{W.push([j,/^#(?:(?:define|elif|else|endif|error|ifdef|include|ifndef|line|pragma|undef|warning)\b|[^\r\n]*)/,null,"#"])}S.push([C,/^<(?:(?:(?:\.\.\/)*|\/?)(?:[\w-]+(?:\/[\w-]+)+)?[\w-]+\.h|[a-z]\w*)>/,null])}else{W.push([j,/^#[^\r\n]*/,null,"#"])}}if(T.cStyleComments){S.push([j,/^\/\/[^\r\n]*/,null]);S.push([j,/^\/\*[\s\S]*?(?:\*\/|$)/,null])}if(T.regexLiterals){var X=("/(?=[^/*])(?:[^/\\x5B\\x5C]|\\x5C[\\s\\S]|\\x5B(?:[^\\x5C\\x5D]|\\x5C[\\s\\S])*(?:\\x5D|$))+/");S.push(["lang-regex",new RegExp("^"+M+"("+X+")")])}var V=T.types;if(V){S.push([O,V])}var U=(""+T.keywords).replace(/^ | $/g,"");if(U.length){S.push([z,new RegExp("^(?:"+U.replace(/[\s,]+/g,"|")+")\\b"),null])}W.push([F,/^\s+/,null," \r\n\t\xA0"]);S.push([G,/^@[a-z_$][a-z_$@0-9]*/i,null],[O,/^(?:[@_]?[A-Z]+[a-z][A-Za-z_$@0-9]*|\w+_t\b)/,null],[F,/^[a-z_$][a-z_$@0-9]*/i,null],[G,new RegExp("^(?:0x[a-f0-9]+|(?:\\d(?:_\\d+)*\\d*(?:\\.\\d*)?|\\.\\d\\+)(?:e[+\\-]?\\d+)?)[a-z]*","i"),null,"0123456789"],[F,/^\\[\s\S]?/,null],[L,/^.[^\s\w\.$@\'\"\`\/\#\\]*/,null]);return g(W,S)}var K=i({keywords:A,hashComments:true,cStyleComments:true,multiLineStrings:true,regexLiterals:true});function Q(V,ag){var U=/(?:^|\s)nocode(?:\s|$)/;var ab=/\r\n?|\n/;var ac=V.ownerDocument;var S;if(V.currentStyle){S=V.currentStyle.whiteSpace}else{if(window.getComputedStyle){S=ac.defaultView.getComputedStyle(V,null).getPropertyValue("white-space")}}var Z=S&&"pre"===S.substring(0,3);var af=ac.createElement("LI");while(V.firstChild){af.appendChild(V.firstChild)}var W=[af];function ae(al){switch(al.nodeType){case 1:if(U.test(al.className)){break}if("BR"===al.nodeName){ad(al);if(al.parentNode){al.parentNode.removeChild(al)}}else{for(var an=al.firstChild;an;an=an.nextSibling){ae(an)}}break;case 3:case 4:if(Z){var am=al.nodeValue;var aj=am.match(ab);if(aj){var ai=am.substring(0,aj.index);al.nodeValue=ai;var ah=am.substring(aj.index+aj[0].length);if(ah){var ak=al.parentNode;ak.insertBefore(ac.createTextNode(ah),al.nextSibling)}ad(al);if(!ai){al.parentNode.removeChild(al)}}}break}}function ad(ak){while(!ak.nextSibling){ak=ak.parentNode;if(!ak){return}}function ai(al,ar){var aq=ar?al.cloneNode(false):al;var ao=al.parentNode;if(ao){var ap=ai(ao,1);var an=al.nextSibling;ap.appendChild(aq);for(var am=an;am;am=an){an=am.nextSibling;ap.appendChild(am)}}return aq}var ah=ai(ak.nextSibling,0);for(var aj;(aj=ah.parentNode)&&aj.nodeType===1;){ah=aj}W.push(ah)}for(var Y=0;Y=S){ah+=2}if(V>=ap){Z+=2}}}var t={};function c(U,V){for(var S=V.length;--S>=0;){var T=V[S];if(!t.hasOwnProperty(T)){t[T]=U}else{if(window.console){console.warn("cannot override language handler %s",T)}}}}function q(T,S){if(!(T&&t.hasOwnProperty(T))){T=/^\s*]*(?:>|$)/],[j,/^<\!--[\s\S]*?(?:-\->|$)/],["lang-",/^<\?([\s\S]+?)(?:\?>|$)/],["lang-",/^<%([\s\S]+?)(?:%>|$)/],[L,/^(?:<[%?]|[%?]>)/],["lang-",/^]*>([\s\S]+?)<\/xmp\b[^>]*>/i],["lang-js",/^
307 |
--------------------------------------------------------------------------------
/src/index.js:
--------------------------------------------------------------------------------
1 |
2 | import GarenLoadmore from './GarenLoadmore.vue';
3 |
4 | export default {
5 | install(Vue){
6 | Vue.component('garen-loadmore', GarenLoadmore)
7 | }
8 | }
--------------------------------------------------------------------------------
/static/loadmoregif.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/duyanpeng/vue-quick-loadmore/2c2f5c4221260749cd4774563d70cb50ac1d1ecc/static/loadmoregif.gif
--------------------------------------------------------------------------------
/static/shanglajiazai.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/duyanpeng/vue-quick-loadmore/2c2f5c4221260749cd4774563d70cb50ac1d1ecc/static/shanglajiazai.jpg
--------------------------------------------------------------------------------
/static/shifangshuaxin.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/duyanpeng/vue-quick-loadmore/2c2f5c4221260749cd4774563d70cb50ac1d1ecc/static/shifangshuaxin.jpg
--------------------------------------------------------------------------------
/static/wugengduoshuju.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/duyanpeng/vue-quick-loadmore/2c2f5c4221260749cd4774563d70cb50ac1d1ecc/static/wugengduoshuju.jpg
--------------------------------------------------------------------------------
/static/xialashuaxin.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/duyanpeng/vue-quick-loadmore/2c2f5c4221260749cd4774563d70cb50ac1d1ecc/static/xialashuaxin.jpg
--------------------------------------------------------------------------------
/static/zhengzaishuaxin.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/duyanpeng/vue-quick-loadmore/2c2f5c4221260749cd4774563d70cb50ac1d1ecc/static/zhengzaishuaxin.jpg
--------------------------------------------------------------------------------
/test/LoadMore.spec.js:
--------------------------------------------------------------------------------
1 | import { shallowMount, mount } from '@vue/test-utils'
2 | import Loadmore from '../src/GarenLoadmore.vue'
3 | import chai, { expect } from 'chai'
4 | import { createEvent } from './utils'
5 | import sinon from 'sinon'
6 | import sinonChai from 'sinon-chai'
7 |
8 | chai.use(sinonChai)
9 |
10 | describe('Loadmore', () => {
11 | it('pulling状态改变pulling', (done) => {
12 | const wrapper = mount(Loadmore, {
13 | propsData: {
14 | 'top-change-text': {
15 | pulling: "测试下拉刷新",
16 | limit: "测试释放刷新",
17 | loading: "测试正在刷新...",
18 | complete: "测试完成",
19 | }
20 | }
21 | })
22 | const vm = wrapper.vm
23 | const touchmove = createEvent('touchmove')
24 | touchmove.touches = [{ screenY: 20 }]
25 | const content = vm.$refs.content
26 | vm.startPositionTop = -40
27 | content.addEventListener('touchmove', function (e) {
28 | expect(vm.topStatus).to.equal('pulling')
29 | expect(vm.topText).to.equal('测试下拉刷新')
30 | setTimeout(() => {
31 | expect(wrapper.emitted()['top-status-change'][0][0]).to.be.equal('pulling')
32 | done()
33 | }, 0)
34 | }, false);
35 | content.dispatchEvent(touchmove)
36 | })
37 |
38 | it('pulling状态改变limit', (done) => {
39 | const wrapper = mount(Loadmore, {
40 | propsData: {
41 | 'top-change-text': {
42 | pulling: "测试下拉刷新",
43 | limit: "测试释放刷新",
44 | loading: "测试正在刷新...",
45 | complete: "测试完成",
46 | }
47 | }
48 | })
49 | const vm = wrapper.vm
50 | const touchmove = createEvent('touchmove')
51 | touchmove.touches = [{ screenY: 200 }]
52 | const content = vm.$refs.content
53 | content.addEventListener('touchmove', function (e) {
54 | expect(vm.topStatus).to.equal('limit')
55 | expect(vm.topText).to.equal('测试释放刷新')
56 | setTimeout(() => {
57 | expect(wrapper.emitted()['top-status-change'][0][0]).to.be.equal('limit')
58 | done()
59 | }, 0)
60 | }, false);
61 | content.dispatchEvent(touchmove)
62 | })
63 |
64 | it('pulling状态改变loading', (done) => {
65 | const wrapper = mount(Loadmore,
66 | {
67 | propsData: {
68 | 'top-change-text': {
69 | pulling: "测试下拉刷新",
70 | limit: "测试释放刷新",
71 | loading: "测试正在刷新...",
72 | complete: "测试完成",
73 | }
74 | }
75 | })
76 | const vm = wrapper.vm
77 | const touchend = createEvent('touchend')
78 | touchend.changedTouches = [{ screenY: 200 }]
79 | const content = vm.$refs.content
80 | content.addEventListener('touchend', function (e) {
81 | expect(vm.topStatus).to.equal('loading')
82 | expect(vm.topText).to.equal('测试正在刷新...')
83 | setTimeout(() => {
84 | expect(wrapper.emitted()['top-status-change'][0][0]).to.be.equal('loading')
85 | expect(wrapper.emitted()['top-method']).to.not.be.undefined
86 | done()
87 | }, 0)
88 | }, false);
89 | content.dispatchEvent(touchend)
90 | })
91 |
92 | it('pulling状态改变complete', () => {
93 | const wrapper = mount(Loadmore, {
94 | propsData: {
95 | 'top-change-text': {
96 | pulling: "测试下拉刷新",
97 | limit: "测试释放刷新",
98 | loading: "测试正在刷新...",
99 | complete: "测试完成",
100 | }
101 | }
102 | })
103 | const vm = wrapper.vm
104 | const content = vm.$refs.content
105 | vm.topStatus = 'loading'
106 | vm.onTopLoaded()
107 | expect(vm.topStatus).to.equal('complete')
108 | expect(vm.topText).to.equal('测试完成')
109 | })
110 |
111 | it('loading状态改变loading', (done) => {
112 | const wrapper = mount(Loadmore,
113 | {
114 | propsData: {
115 | 'bottom-change-text': {
116 | loading: "测试正在加载更多...",
117 | nodata: "测试暂无更多数据",
118 | error: "测试请求数据出错,请点击重试",
119 | }
120 | }
121 | })
122 | const vm = wrapper.vm
123 | const scroll = createEvent('scroll')
124 | vm.$el.addEventListener('scroll', function (e) {
125 | expect(vm.bottomStatus).to.equal('loading')
126 | expect(vm.bottomText).to.equal('测试正在加载更多...')
127 | setTimeout(() => {
128 | expect(wrapper.emitted()['bottom-status-change'][0][0]).to.be.equal('loading')
129 | expect(wrapper.emitted()['bottom-method']).to.not.be.undefined
130 | done()
131 | }, 0)
132 | }, false);
133 | vm.$el.dispatchEvent(scroll)
134 | })
135 |
136 | it('loading状态改变complete', () => {
137 | const wrapper = mount(Loadmore,
138 | {
139 | propsData: {
140 | 'bottom-change-text': {
141 | loading: "测试正在加载更多...",
142 | nodata: "测试暂无更多数据",
143 | error: "测试请求数据出错,请点击重试",
144 | }
145 | }
146 | })
147 | const vm = wrapper.vm
148 | vm.bottomStatus = 'loading'
149 | vm.onBottomLoaded()
150 | expect(vm.bottomStatus).to.equal('wait')
151 | })
152 |
153 | it('loading状态改变nodata', () => {
154 | const wrapper = mount(Loadmore,
155 | {
156 | propsData: {
157 | 'bottom-change-text': {
158 | loading: "测试正在加载更多...",
159 | nodata: "测试暂无更多数据",
160 | error: "测试请求数据出错,请点击重试",
161 | }
162 | }
163 | })
164 | const vm = wrapper.vm
165 | vm.bottomStatus = 'loading'
166 | vm.onBottomLoaded(false)
167 | expect(vm.bottomStatus).to.equal('nodata')
168 | })
169 |
170 | it('loading状态改变error', (done) => {
171 | const wrapper = mount(Loadmore,
172 | {
173 | propsData: {
174 | 'bottom-change-text': {
175 | loading: "测试正在加载更多...",
176 | nodata: "测试暂无更多数据",
177 | error: "测试请求数据出错,请点击重试",
178 | }
179 | }
180 | })
181 | const vm = wrapper.vm
182 | vm.bottomStatus = 'loading'
183 | vm.onBottomError()
184 | expect(vm.bottomStatus).to.equal('error')
185 | wrapper.find('.garen-loadmore-footer').trigger('click')
186 | setTimeout(() => {
187 | expect(wrapper.emitted()['bottom-error-click']).to.not.be.undefined
188 | done()
189 | }, 0)
190 | })
191 |
192 | it('loading监听scroll', (done) => {
193 | const cb = sinon.spy()
194 | const wrapper = mount(Loadmore,
195 | {
196 | propsData: {
197 | 'event-scroll': cb
198 | }
199 | })
200 | const vm = wrapper.vm
201 | const scroll = createEvent('scroll')
202 | vm.$el.addEventListener('scroll', function (e) {
203 | setTimeout(() => {
204 | expect(cb).to.have.been.called
205 | done()
206 | }, 0)
207 | }, false);
208 | vm.$el.dispatchEvent(scroll)
209 | })
210 |
211 | it('loading获取滚动距离', () => {
212 | const wrapper = mount(Loadmore)
213 | const vm = wrapper.vm
214 | const scrollTop = vm.getScrollTop()
215 | expect(scrollTop).to.equal(0)
216 | })
217 |
218 | it('loading设置滚动距离', (done) => {
219 | const wrapper = mount(Loadmore)
220 | const vm = wrapper.vm
221 | vm.setScrollTop(50)
222 | setTimeout(()=>{
223 | // TODO: slots
224 | const scrollTop = vm.getScrollTop()
225 | // expect(scrollTop).to.equal(50)
226 | done()
227 | },0)
228 | })
229 | })
230 |
--------------------------------------------------------------------------------
/test/setup.js:
--------------------------------------------------------------------------------
1 | require('jsdom-global')()
2 |
3 | global.expect = require('expect')
--------------------------------------------------------------------------------
/test/utils.js:
--------------------------------------------------------------------------------
1 | export function createEvent(name){
2 | const event = new Event(name)
3 | return event
4 | }
--------------------------------------------------------------------------------