Skip to content

Commit 54a77d2

Browse files
author
Ken Berkeley
committed
v2 enhanced
1 parent 462ed4f commit 54a77d2

File tree

11 files changed

+359
-145
lines changed

11 files changed

+359
-145
lines changed

README.md

Lines changed: 100 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -13,41 +13,128 @@
1313
* Vue Router 0.7.x
1414

1515
### Installation
16-
1716
`npm i vue-sync-query-mixin -S`
1817

19-
alternatively:
20-
`<script src="dist/vue-sync-query-mixin.min.js"></script>`
18+
alternatively:`<script src="dist/vue-sync-query-mixin.min.js"></script>`
19+
which exposes **`VueSyncQuery`** as a global variable
2120

22-
### Usage
21+
### Example
22+
See [here](https://kenberkeley.github.io/vue-sync-query-mixin/example.html), source in [`example.html`](./example.html)
2323

24+
### Usage
2425
```js
2526
// This is a Vue component
2627
import syncQuery from 'vue-sync-query-mixin'
2728

2829
export default {
2930
mixins: [syncQuery],
30-
data: () => ({ limit: 10, offset: 0 }),
31+
data: () => ({ limit: 10 }),
3132
ready () {
32-
this.syncQuery(['limit', 'offset'])
3333
// `limit` will keep in sync with `$route.query.limit`
34-
// `offset` will keep in sync with `$route.query.offset`
34+
this.syncQuery('limit')
3535
}
3636
}
3737
```
3838

39-
`syncQuery` accepts 3 types of argument:
39+
`syncQuery` accepts 4 types of argument:
40+
41+
* `string|string[]`
42+
43+
```js
44+
this.syncQuery('limit')
45+
this.syncQuery(['limit'])
46+
```
47+
48+
* `object|object[]`
49+
50+
```js
51+
this.syncQuery({
52+
localField: 'limit',
53+
queryField: 'limit',
54+
local2query: {
55+
formatter: v => v,
56+
immediate: false,
57+
deep: false
58+
},
59+
query2local: {
60+
formatter: v => v,
61+
immediate: true,
62+
deep: false
63+
}
64+
})
65+
this.syncQuery([
66+
{
67+
localField: 'limit',
68+
queryField: 'limit',
69+
local2query: {
70+
formatter: v => v,
71+
immediate: false,
72+
deep: false
73+
},
74+
query2local: {
75+
formatter: v => v,
76+
immediate: true,
77+
deep: false
78+
}
79+
}
80+
])
81+
```
82+
83+
### Magic
84+
85+
> More detail in [source code](./src/mixins/syncQuery.js)
86+
> Vue.js official `vm.$watch( expOrFn, callback, [options] )` API documentation is [here](http://v1.vuejs.org/api/#vm-watch)
4087
41-
* `string`, e.g. `syncQuery('limit') // limit will keep in sync with $route.query.limit`
42-
* `array`, see example above
43-
* `object`, e.g. `syncQuery({ limit: 'limitBy' }) // limit will keep in sync with $route.query.limitBy`
88+
```js
89+
_syncQuery ({ localField, queryField, local2query, query2local }) {
90+
(() => {
91+
// backup the default value
92+
const defaultVal = this[localField]
93+
94+
// local ==(sync)==> query
95+
this.$watch(localField, function (v, oldV) {
96+
this.updateQuery({ [queryField]: local2query.formatter(v, oldV) })
97+
}, local2query)
98+
99+
// local <==(sync)== query
100+
this.$watch(`$route.query.${queryField}`, function (v, oldV) {
101+
this[localField] = query2local.formatter(v, oldV) || defaultVal
102+
}, query2local)
103+
})()
104+
}
105+
```
44106

45107
### Notice
108+
* `local <==(sync)== query`, default type is `string`, or else you need to write `formatter` yourself
109+
* default `local2query` and `query2local` shown as below:
46110

47-
* `local state <==(sync)== query string`, the type is `string`
111+
```js
112+
/**
113+
* default descriptor generator for $watch
114+
* @param {String} field
115+
* @return {Object}
116+
*/
117+
function defaultDescGen(field) {
118+
return {
119+
localField: field,
120+
queryField: field,
121+
local2query: { // <----------------------
122+
formatter: v => v,
123+
immediate: false,
124+
deep: false
125+
},
126+
query2local: { // <----------------------
127+
formatter: v => v,
128+
immediate: true,
129+
deep: false // P.S. watching deep of a string makes no sense
130+
}
131+
}
132+
}
133+
```
48134

49-
### Build
135+
But they can be `function` type, and then we regard them as the `formatter`
50136

137+
### Build
51138
`npm run build`
52139

53140
[npm-url]: https://www.npmjs.com/package/vue-sync-query-mixin

dist/vue-sync-query-mixin.min.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

es/mixins/syncQuery.js

Lines changed: 68 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -8,42 +8,84 @@ var _vueUpdateQueryMixin = require('vue-update-query-mixin');
88

99
var _vueUpdateQueryMixin2 = _interopRequireDefault(_vueUpdateQueryMixin);
1010

11-
var _objectify = require('../utils/objectify');
11+
var _typeOf = require('../utils/typeOf');
1212

13-
var _objectify2 = _interopRequireDefault(_objectify);
13+
var _typeOf2 = _interopRequireDefault(_typeOf);
14+
15+
var _mergeDesc = require('../utils/mergeDesc');
16+
17+
var _mergeDesc2 = _interopRequireDefault(_mergeDesc);
1418

1519
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
1620

1721
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
1822

23+
var err = function err(msg) {
24+
throw new Error('[SyncQuery] ' + msg);
25+
};
26+
1927
exports.default = {
2028
mixins: [_vueUpdateQueryMixin2.default],
2129
methods: {
22-
syncQuery: function syncQuery(fieldsMap) {
23-
if (!fieldsMap) throw new Error('syncQuery accepted an empty value');
24-
fieldsMap = (0, _objectify2.default)(fieldsMap);
25-
for (var localField in fieldsMap) {
26-
var queryField = fieldsMap(localField);
27-
this._local2query(localField, queryField);
28-
this._query2local(queryField, localField);
30+
syncQuery: function syncQuery(fields) {
31+
var _this = this;
32+
33+
if (!fields) err('empty fields');
34+
switch ((0, _typeOf2.default)(fields)) {
35+
case 'string':
36+
this._syncQuery(defaultDescGen(fields));
37+
break;
38+
case 'object':
39+
this._syncQuery((0, _mergeDesc2.default)(defaultDescGen(fields.localField), fields));
40+
break;
41+
case 'array':
42+
fields.forEach(function (field) {
43+
return _this.syncQuery(field);
44+
});
45+
break;
46+
default:
47+
err('invalid type of field');
2948
}
3049
},
31-
_local2query: function _local2query(localField, queryField) {
32-
this._backup(localField);
33-
this.$watch(localField, function (v) {
34-
this.updateQuery(_defineProperty({}, queryField, v));
35-
});
36-
},
37-
_query2local: function _query2local(queryField, localField) {
38-
this.$watch('$route.query.' + queryField, function (v) {
39-
v ? this[localField] = v : this._restore(localField);
40-
});
41-
},
42-
_backup: function _backup(localField) {
43-
this.$data['$' + localField] = this[localField];
44-
},
45-
_restore: function _restore(localField) {
46-
this[localField] = this.$data['$' + localField];
50+
_syncQuery: function _syncQuery(_ref) {
51+
var _this2 = this;
52+
53+
var localField = _ref.localField,
54+
queryField = _ref.queryField,
55+
local2query = _ref.local2query,
56+
query2local = _ref.query2local;
57+
58+
(function () {
59+
var defaultVal = _this2[localField];
60+
61+
_this2.$watch(localField, function (v, oldV) {
62+
this.updateQuery(_defineProperty({}, queryField, local2query.formatter(v, oldV)));
63+
}, local2query);
64+
65+
_this2.$watch('$route.query.' + queryField, function (v, oldV) {
66+
this[localField] = query2local.formatter(v, oldV) || defaultVal;
67+
}, query2local);
68+
})();
4769
}
4870
}
49-
};
71+
};
72+
73+
function defaultDescGen(field) {
74+
return {
75+
localField: field,
76+
queryField: field,
77+
local2query: {
78+
formatter: function formatter(v) {
79+
return v;
80+
},
81+
immediate: false,
82+
deep: false
83+
},
84+
query2local: {
85+
formatter: function formatter(v) {
86+
return v;
87+
},
88+
immediate: true,
89+
deep: false }
90+
};
91+
}

es/utils/mergeDesc.js

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
'use strict';
2+
3+
Object.defineProperty(exports, "__esModule", {
4+
value: true
5+
});
6+
7+
var _typeOf = require('./typeOf');
8+
9+
var _typeOf2 = _interopRequireDefault(_typeOf);
10+
11+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
12+
13+
function mergeDesc(distDesc, srcDesc) {
14+
for (var k in srcDesc) {
15+
var v = srcDesc[k];
16+
if (!distDesc[k]) distDesc[k] = {};
17+
18+
switch ((0, _typeOf2.default)(v)) {
19+
case 'object':
20+
mergeDesc(distDesc[k], v);
21+
break;
22+
case 'function':
23+
distDesc[k].formatter = v;
24+
break;
25+
default:
26+
distDesc[k] = v;
27+
break;
28+
}
29+
}
30+
return distDesc;
31+
}
32+
33+
exports.default = mergeDesc;

es/utils/objectify.js

Lines changed: 0 additions & 41 deletions
This file was deleted.

0 commit comments

Comments
 (0)