Skip to content
This repository was archived by the owner on Apr 18, 2023. It is now read-only.

Commit edeafa0

Browse files
committed
add files
1 parent b8d4749 commit edeafa0

11 files changed

+439
-0
lines changed

.babelrc

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"presets": ["es2015"],
3+
"plugins": ["transform-runtime"],
4+
"comments": false
5+
}

.eslintrc.js

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
module.exports = {
2+
root: true,
3+
parser: 'babel-eslint',
4+
parserOptions: {
5+
sourceType: 'module'
6+
},
7+
// https://github.com/feross/standard/blob/master/RULES.md#javascript-standard-style
8+
extends: 'standard',
9+
// required to lint *.vue files
10+
plugins: [
11+
'html'
12+
],
13+
// add your custom rules here
14+
'rules': {
15+
// allow paren-less arrow functions
16+
'arrow-parens': 0,
17+
// allow async-await
18+
'generator-star-spacing': 0,
19+
// allow debugger during development
20+
'no-debugger': process.env.NODE_ENV === 'production' ? 2 : 0,
21+
'semi': 0,
22+
'comma-dangle': 0,
23+
'no-multiple-empty-lines': 0,
24+
'quotes': 1,
25+
},
26+
27+
"env": {
28+
"jasmine": true
29+
},
30+
"globals": {
31+
},
32+
}

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
node_modules/
2+
npm-debug.log.*
3+
coverage/

LICENSE

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
The MIT License (MIT)
2+
3+
Copyright (c) 2017 kamijin-fanta
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
13+
all 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
21+
THE SOFTWARE.

README.md

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
# vue-async-data for Vue.js 2.0
2+
3+
**this plugin is experimental!**
4+
5+
Async data loading plugin for Vue.js
6+
7+
### Install
8+
9+
- this plugin is written in ES2015,
10+
so recommend compile with babel/babel-polyfill.
11+
12+
``` bash
13+
npm install kamijin-fanta/vue-async-data
14+
```
15+
16+
``` js
17+
// use as global plugin
18+
import Vue from 'vue';
19+
import { AsyncDataPlugin } from './utils/asyncdata';
20+
Vue.use(AsyncDataPlugin);
21+
```
22+
23+
``` js
24+
// use as locally mixin
25+
import { AsyncDataMixin } from './utils/asyncdata';
26+
27+
export default {
28+
mixins: [ AsyncDataMixin ],
29+
}
30+
```
31+
32+
### Usage
33+
34+
``` html
35+
<template>
36+
<div>
37+
<p v-if="userNameLoading">Loading...</p>
38+
<p v-else-if="userNameError">Error: {{ userNameError }}</p>
39+
<p v-else>Hello {{ userName }} !</p>
40+
<button v-on:click="asyncReload('userName')">Reload userName</button>
41+
</div>
42+
</template>
43+
44+
<script>
45+
export default {
46+
name: 'show-data',
47+
asyncData: {
48+
userName () {
49+
return new Promise((resolve, reject) => {
50+
setTimeout(_ => {
51+
if (Math.random() > 0.5) {
52+
resolve('risa');
53+
} else {
54+
reject('fetch error...');
55+
}
56+
}, 1000);
57+
})
58+
},
59+
},
60+
}
61+
</script>
62+
```
63+
64+
65+
### API
66+
67+
#### this.asyncData: object
68+
#### this.asyncReload([name])
69+
#### this.asyncLoading: object
70+
#### this.asyncError: object

karma.conf.js

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
var webpackConfig = require('./webpack.test.conf');
2+
3+
module.exports = function (config) {
4+
config.set({
5+
// to run in additional browsers:
6+
// 1. install corresponding karma launcher
7+
// http://karma-runner.github.io/0.13/config/browsers.html
8+
// 2. add it to the `browsers` array below.
9+
browsers: ['PhantomJS'],
10+
frameworks: ['jasmine'],
11+
reporters: ['spec', 'coverage'],
12+
files: [
13+
'./node_modules/babel-polyfill/dist/polyfill.js',
14+
'./test.js'
15+
],
16+
preprocessors: {
17+
'./test.js': ['webpack', 'sourcemap']
18+
// './test.js': ['sourcemap']
19+
},
20+
webpack: webpackConfig,
21+
webpackMiddleware: {
22+
noInfo: true
23+
},
24+
coverageReporter: {
25+
dir: './coverage',
26+
reporters: [
27+
{ type: 'lcov', subdir: '.' },
28+
{ type: 'text-summary' }
29+
]
30+
},
31+
logLevel: config.LOG_INFO,
32+
})
33+
}

package.json

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
{
2+
"name": "vue-async-data",
3+
"version": "0.0.1-beta.0",
4+
"description": "",
5+
"main": "src/main.js",
6+
"scripts": {
7+
"test": "unit",
8+
"unit": "karma start karma.conf.js --single-run",
9+
"unit:watch": "karma start karma.conf.js"
10+
},
11+
"repository": {
12+
"type": "git",
13+
"url": "git+https://github.com/kamijin-fanta/vue-async-data.git"
14+
},
15+
"author": "kamijin-fanta <[email protected]>",
16+
"license": "MIT",
17+
"bugs": {
18+
"url": "https://github.com/kamijin-fanta/vue-async-data/issues"
19+
},
20+
"homepage": "https://github.com/kamijin-fanta/vue-async-data#readme",
21+
"devDependencies": {
22+
"babel-core": "^6.21.0",
23+
"babel-eslint": "^7.1.1",
24+
"babel-loader": "^6.2.10",
25+
"babel-plugin-transform-runtime": "^6.15.0",
26+
"babel-polyfill": "^6.20.0",
27+
"babel-preset-es2015": "^6.18.0",
28+
"eslint": "^3.12.2",
29+
"eslint-config-standard": "^6.2.1",
30+
"eslint-friendly-formatter": "^2.0.6",
31+
"eslint-loader": "^1.6.1",
32+
"eslint-plugin-html": "^1.7.0",
33+
"eslint-plugin-promise": "^3.4.0",
34+
"eslint-plugin-standard": "^2.0.1",
35+
"function-bind": "^1.1.0",
36+
"jasmine-core": "^2.5.2",
37+
"karma": "^1.3.0",
38+
"karma-coverage": "^1.1.1",
39+
"karma-jasmine": "^1.1.0",
40+
"karma-phantomjs-launcher": "^1.0.2",
41+
"karma-sourcemap-loader": "^0.3.7",
42+
"karma-spec-reporter": "0.0.26",
43+
"karma-webpack": "^1.8.0",
44+
"vue": "^2.1.6",
45+
"webpack": "^1.14.0"
46+
}
47+
}

src/main.js

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
var AsyncDataMixin = {
2+
created () {
3+
},
4+
mounted () {
5+
this.asyncReload();
6+
},
7+
methods: {
8+
// name args optional
9+
asyncReload (name) {
10+
let asyncData = this.$options.asyncData;
11+
if (asyncData) {
12+
let names = Object.keys(asyncData)
13+
.filter(s => !s.endsWith('Default'))
14+
.filter(s => name === undefined || s === name);
15+
for (let prop of names) {
16+
// helper
17+
let setData = data => { this[prop] = data };
18+
let setError = err => {
19+
this[prop + 'Error'] = err;
20+
if (err) this.asyncError = true;
21+
else this.asyncError = !!names.find(n => this[n + 'Error']);
22+
};
23+
let setLoading = flag => {
24+
this[prop + 'Loading'] = flag
25+
if (flag) this.asyncLoading = true;
26+
else this.asyncLoading = !!names.find(n => this[`${n}Loading`]);
27+
};
28+
29+
setLoading(true);
30+
setError(undefined);
31+
asyncData[prop].apply(this)
32+
.then(res => {
33+
setData(res);
34+
setLoading(false);
35+
})
36+
.catch(err => {
37+
setError(err);
38+
setLoading(false);
39+
});
40+
}
41+
}
42+
},
43+
},
44+
data () {
45+
let asyncData = this.$options.asyncData;
46+
if (asyncData) {
47+
let dataObj = {
48+
'asyncLoading': true,
49+
'asyncError': false,
50+
};
51+
52+
let names = Object.keys(asyncData)
53+
.filter(s => !s.endsWith('Default'));
54+
names.forEach(name => {
55+
dataObj[name] = asyncData[`${name}Default`];
56+
});
57+
58+
let loadingNames = names.map(s => `${s}Loading`);
59+
loadingNames.forEach(name => { dataObj[name] = true });
60+
61+
let errorNames = names.map(s => `${s}Error`);
62+
errorNames.forEach(name => { dataObj[name] = undefined });
63+
64+
return dataObj;
65+
}
66+
return {}
67+
}
68+
}
69+
70+
var AsyncDataPlugin = {
71+
install (Vue, options) {
72+
// console.log('Plugin Install', options);
73+
Vue.mixin(AsyncDataMixin)
74+
}
75+
}
76+
77+
var api = {
78+
AsyncDataPlugin: AsyncDataPlugin,
79+
AsyncDataMixin: AsyncDataMixin,
80+
}
81+
82+
if (typeof exports === 'object' && typeof module === 'object') {
83+
module.exports = api
84+
} else if (typeof window !== 'undefined') {
85+
window.AsyncDataMixin = AsyncDataMixin;
86+
window.AsyncDataPlugin = AsyncDataPlugin;
87+
}

src/main.spec.js

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
import Vue from 'vue';
2+
import { AsyncDataMixin } from './main';
3+
4+
describe('AsyncData', () => {
5+
let resolve = (done) => {
6+
return new Vue({
7+
template: `<div></div>`,
8+
mixins: [ AsyncDataMixin ],
9+
asyncData: {
10+
sandbox () {
11+
return new Promise((resolve, reject) => {
12+
this.counter++;
13+
resolve('OK!' + this.counter);
14+
setTimeout(() => {
15+
if (done) done();
16+
}, 10)
17+
});
18+
},
19+
sandboxDefault: 'Default!',
20+
},
21+
data () {
22+
return {
23+
counter: 0
24+
}
25+
}
26+
}).$mount();
27+
};
28+
let reject = (done) => {
29+
return new Vue({
30+
template: `<div></div>`,
31+
mixins: [ AsyncDataMixin ],
32+
asyncData: {
33+
sandbox () {
34+
return new Promise((resolve, reject) => {
35+
this.counter++;
36+
reject('NG!' + this.counter);
37+
setTimeout(() => {
38+
if (done) done();
39+
}, 50)
40+
});
41+
}
42+
},
43+
data () {
44+
return {
45+
counter: 0
46+
}
47+
}
48+
}).$mount();
49+
}
50+
51+
beforeEach(() => {
52+
})
53+
54+
it('If "asyncData" property is not found, mixin does not work.', () => {
55+
let emptyVm = new Vue({
56+
template: `<div></div>`,
57+
mixins: [ AsyncDataMixin ],
58+
}).$mount();
59+
expect(emptyVm.asyncLoading).toEqual(undefined);
60+
})
61+
62+
it('Default property is set.', () => {
63+
let resolveVm = resolve();
64+
expect(resolveVm.asyncLoading).toEqual(true);
65+
expect(resolveVm.asyncError).toEqual(false);
66+
expect(resolveVm.sandbox).toEqual('Default!');
67+
})
68+
69+
it('Resolve promise.', (done) => {
70+
let resolveVm = resolve(() => {
71+
expect(resolveVm.sandbox).toEqual('OK!1');
72+
expect(resolveVm.sandboxLoading).toEqual(false);
73+
expect(resolveVm.asyncLoading).toEqual(false);
74+
expect(resolveVm.asyncError).toEqual(false);
75+
done();
76+
});
77+
expect(resolveVm.asyncError).toEqual(false);
78+
})
79+
80+
it('Reject promise.', (done) => {
81+
let rejectVm = reject(() => {
82+
expect(rejectVm.sandboxError).toEqual('NG!1');
83+
expect(rejectVm.sandboxLoading).toEqual(false);
84+
expect(rejectVm.asyncError).toEqual(true);
85+
done();
86+
});
87+
expect(rejectVm.asyncError).toEqual(false);
88+
})
89+
})

0 commit comments

Comments
 (0)