Skip to content

Commit 4009aef

Browse files
committed
[ Add ] "render" & "rendered" events
[ Optimize ] Speed up Getter & Setter of View [ Optimize ] Reduce Memory usage of Model [ Optimize ] stringifyDOM() supports Document-level Nodes [ Fix ] Several detail bugs
1 parent 50bbcaa commit 4009aef

File tree

11 files changed

+229
-83
lines changed

11 files changed

+229
-83
lines changed

ReadMe.md

Lines changed: 36 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010

1111
## Data binding
1212

13-
[`index.json`](https://github.com/EasyWebApp/DOM-Renderer/blob/master/test/source/index.json)
13+
[`source/index.json`](https://github.com/EasyWebApp/DOM-Renderer/blob/master/test/source/index.json)
1414

1515
```JSON
1616
{
@@ -27,7 +27,7 @@
2727
}
2828
```
2929

30-
[`index.html`](https://github.com/EasyWebApp/DOM-Renderer/blob/master/test/source/index.html)
30+
[`source/index.html`](https://github.com/EasyWebApp/DOM-Renderer/blob/master/test/source/index.html)
3131

3232
```HTML
3333
<template>
@@ -52,23 +52,23 @@
5252
</template>
5353
```
5454

55-
`index.js`
55+
`source/index.js`
5656

5757
```JavaScript
58-
import View from 'dom-renderer';
58+
import View, { parseDOM } from 'dom-renderer';
5959

6060
import template from './index.html';
6161
import data from './index.json';
6262

63-
const view = new View( template );
63+
const view = new View( parseDOM( template ).firstChild.innerHTML );
6464

6565
view.render( data ).then(() => console.log(view + ''));
6666
```
6767

6868
**Console output** (formatted)
6969

7070
```HTML
71-
<h1>TechQuery</h1>
71+
<h1>Hello, TechQuery !</h1>
7272

7373
<ul data-view="profile">
7474
<template>
@@ -112,38 +112,49 @@ import 'dom-renderer/dist/polyfill';
112112
import View from 'dom-renderer';
113113
```
114114

115-
## Babel configuration
115+
## Compile & bundle
116116

117117
```Shell
118118
npm install -D \
119-
@babel/cli \
120-
@babel/core \
119+
web-cell \
121120
@babel/preset-env \
122121
babel-plugin-inline-import
123122
```
124123

125-
`.babelrc`
124+
`package.json`
126125

127126
```JSON
128127
{
129-
"presets": [
130-
"@babel/preset-env"
131-
],
132-
"plugins": [
133-
[
134-
"babel-plugin-inline-import",
135-
{
136-
"extensions": [
137-
".html",
138-
".css",
139-
".json"
140-
]
141-
}
128+
"directories": {
129+
"lib": "source/"
130+
},
131+
"scripts": {
132+
"build": "web-cell pack"
133+
},
134+
"babel": {
135+
"presets": [
136+
"@babel/preset-env"
137+
],
138+
"plugins": [
139+
[
140+
"babel-plugin-inline-import",
141+
{
142+
"extensions": [
143+
".html",
144+
".css",
145+
".json"
146+
]
147+
}
148+
]
142149
]
143-
]
150+
}
144151
}
145152
```
146153

154+
```Shell
155+
npm run build
156+
```
157+
147158
## Advanced usage
148159

149160
Follow [the example above](#data-binding)
@@ -181,7 +192,7 @@ view.name = 'tech-query';
181192

182193
nextTick().then(() => {
183194

184-
console.log( document.querySelector('h1').textContent ); // 'tech-query'
195+
console.log( document.querySelector('h1').textContent ); // 'Hello, tech-query !'
185196
});
186197
```
187198

package-lock.json

Lines changed: 7 additions & 7 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "dom-renderer",
3-
"version": "0.6.0",
3+
"version": "0.7.0",
44
"description": "Template engine based on HTML 5 & ECMAScript 6",
55
"keywords": [
66
"template",
@@ -19,6 +19,7 @@
1919
"url": "https://github.com/EasyWebApp/DOM-Renderer/issues"
2020
},
2121
"module": "source/index.js",
22+
"main": "dist/dom-renderer.js",
2223
"browser": "dist/dom-renderer.min.js",
2324
"directories": {
2425
"lib": "source",
@@ -56,7 +57,7 @@
5657
"husky": "^1.3.1",
5758
"jsdom": "^13.2.0",
5859
"koapache": "^1.0.5",
59-
"mocha": "^6.0.0",
60+
"mocha": "^6.0.1",
6061
"prettier": "^1.16.4",
6162
"should": "^13.2.3",
6263
"should-sinon": "0.0.6",

source/Model.js

Lines changed: 34 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -41,11 +41,41 @@ export default class Model {
4141
value = {};
4242

4343
for (let key in data)
44-
if (data.hasOwnProperty(key)) value[key] = data[key];
44+
if (data.hasOwnProperty(key)) {
45+
let _data_ = data[key];
46+
47+
value[key] =
48+
_data_ instanceof Object ? _data_.valueOf() : _data_;
49+
}
4550

4651
return value;
4752
}
4853

54+
/**
55+
* @param {String} key - Property name of `this`
56+
* @param {Object} [descriptor] - More configuration of `key`
57+
*/
58+
watch(key, descriptor) {
59+
const meta = Object.assign(
60+
Object.getOwnPropertyDescriptor(this, key) || {},
61+
descriptor
62+
);
63+
64+
(meta.configurable = true), (meta.enumerable = true);
65+
66+
if (!meta.get)
67+
meta.get = function() {
68+
return this.data[key];
69+
};
70+
71+
if (!meta.set)
72+
meta.set = function(value) {
73+
this.commit(key, value);
74+
};
75+
76+
Object.defineProperty(this, key, meta);
77+
}
78+
4979
/**
5080
* @param {Object} data
5181
*
@@ -58,21 +88,10 @@ export default class Model {
5888
Object.assign(_data_, data);
5989

6090
for (let key in _data_) {
61-
if (!_data_.hasOwnProperty(key)) continue;
62-
63-
if (!(key in this))
64-
Object.defineProperty(this, key, {
65-
get: function() {
66-
return this.data[key];
67-
},
68-
set: function(value) {
69-
this.commit(key, value);
70-
}
71-
});
72-
7391
if (
74-
typeof data[key] === 'object' ||
75-
typeof _data_[key] !== 'object'
92+
_data_.hasOwnProperty(key) &&
93+
(typeof data[key] === 'object' ||
94+
typeof _data_[key] !== 'object')
7695
)
7796
update[key] = _data_[key];
7897
}

source/Template.js

Lines changed: 39 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
const template_raw = Symbol('Template raw'),
22
template_scope = Symbol('Template scope'),
3+
scope_key = new WeakMap(),
34
template_value = Symbol('Template value');
45

56
export default class Template extends Array {
@@ -16,6 +17,8 @@ export default class Template extends Array {
1617
onChange: onChange instanceof Function && onChange
1718
});
1819

20+
scope_key.set(this, {});
21+
1922
this.parse(), this.reset();
2023
}
2124

@@ -45,11 +48,37 @@ export default class Template extends Array {
4548
parse() {
4649
this[template_raw] = this[template_raw].replace(
4750
Template.Expression,
48-
(_, expression) =>
49-
'${' + (this.push(this.evaluatorOf(expression)) - 1) + '}'
51+
(_, expression) => {
52+
expression.replace(Template.Reference, (_, scope, key) => {
53+
if (
54+
scope !== 'this' &&
55+
!this[template_scope].includes(scope)
56+
)
57+
return;
58+
59+
const map = scope_key.get(this);
60+
61+
(map[scope] = map[scope] || []).push(key);
62+
});
63+
64+
return (
65+
'${' + (this.push(this.evaluatorOf(expression)) - 1) + '}'
66+
);
67+
}
5068
);
5169
}
5270

71+
/**
72+
* @param {String} scope - Name of a Scoped varible
73+
*
74+
* @return {String[]} Reference keys
75+
*/
76+
keysOf(scope) {
77+
const map = scope_key.get(this);
78+
79+
return scope ? map[scope] : [].concat.apply([], Object.values(map));
80+
}
81+
5382
/**
5483
* @private
5584
*
@@ -87,11 +116,12 @@ export default class Template extends Array {
87116
* @return {*}
88117
*/
89118
evaluate(context, ...scope) {
90-
var value = this[1]
91-
? this[template_raw].replace(/\$\{(\d+)\}/g, (_, index) =>
92-
this.eval(index, context, scope)
93-
)
94-
: this.eval(0, context, scope);
119+
var value =
120+
this[template_raw] !== '${0}'
121+
? this[template_raw].replace(/\$\{(\d+)\}/g, (_, index) =>
122+
this.eval(index, context, scope)
123+
)
124+
: this.eval(0, context, scope);
95125

96126
if (this[template_value] !== value) {
97127
if (this.onChange) this.onChange(value, this[template_value]);
@@ -114,3 +144,5 @@ export default class Template extends Array {
114144
}
115145

116146
Template.Expression = /\$\{([^}]+)\}/g;
147+
148+
Template.Reference = /(\w+)(?:\.|\[['"])([^'"]+)/g;

0 commit comments

Comments
 (0)