omis - lifecycle
* receiveProps `return false` will prevent update action * Add unit testing * Build & publish
This commit is contained in:
parent
8685bc0e61
commit
3f7eea04e8
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"props": {
|
||||
"cname": 42,
|
||||
"cname": 43,
|
||||
"props": {
|
||||
"$_dirty": "__d",
|
||||
"$_disable": "__x",
|
||||
|
@ -41,7 +41,8 @@
|
|||
"$_customStyleElement": "N",
|
||||
"$_customStyleContent": "O",
|
||||
"$__hasChildren": "P",
|
||||
"$__prevProps": "Q"
|
||||
"$__prevProps": "Q",
|
||||
"$__needUpdate_": "R"
|
||||
}
|
||||
},
|
||||
"vars": {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/**
|
||||
* omis v0.3.0 http://omijs.org
|
||||
* omis v0.4.0 http://omijs.org
|
||||
* Omi === Preact + Scoped CSS + Store System + Native Support in 3kb javascript.
|
||||
* By dntzhang https://github.com/dntzhang
|
||||
* Github: https://github.com/Tencent/omis
|
||||
|
@ -487,7 +487,8 @@
|
|||
addStyleToHead(c.props.css, '_ds' + c.elementId);
|
||||
}
|
||||
if (options.afterMount) options.afterMount(c);
|
||||
if (c.componentDidMount) c.componentDidMount();
|
||||
//if (c.componentDidMount) c.componentDidMount();
|
||||
if (c.store.installed) c.store.installed();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -851,9 +852,15 @@
|
|||
|
||||
if (typeof component.constructor.getDerivedStateFromProps === 'undefined') {
|
||||
if (!component.base || mountAll) {
|
||||
if (component.componentWillMount) component.componentWillMount();
|
||||
} else if (component.componentWillReceiveProps) {
|
||||
component.componentWillReceiveProps(props, context);
|
||||
//if (component.componentWillMount) component.componentWillMount();
|
||||
if (component.store.install) component.store.install();
|
||||
} else {
|
||||
// if (component.componentWillReceiveProps) {
|
||||
// component.componentWillReceiveProps(props, context);
|
||||
// }
|
||||
if (component.store.receiveProps) {
|
||||
component.__needUpdate_ = component.store.receiveProps(props, context);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -916,11 +923,17 @@
|
|||
component.props = previousProps;
|
||||
component.state = previousState;
|
||||
component.context = previousContext;
|
||||
if (renderMode !== 2 && component.shouldComponentUpdate && component.shouldComponentUpdate(props, state, context) === false) {
|
||||
|
||||
if (component.__needUpdate_ !== false) {
|
||||
skip = false;
|
||||
if (component.store.beforeUpdate) {
|
||||
component.store.beforeUpdate(props, state, context);
|
||||
}
|
||||
} else {
|
||||
skip = true;
|
||||
} else if (component.componentWillUpdate) {
|
||||
component.componentWillUpdate(props, state, context);
|
||||
}
|
||||
delete component.__needUpdate_;
|
||||
|
||||
component.props = props;
|
||||
component.state = state;
|
||||
component.context = context;
|
||||
|
@ -931,6 +944,9 @@
|
|||
|
||||
if (!skip) {
|
||||
options.runTimeComponent = component;
|
||||
if (component.store.beforeRender) {
|
||||
component.store.beforeRender();
|
||||
}
|
||||
rendered = component.render(props, state, context);
|
||||
options.runTimeComponent = null;
|
||||
|
||||
|
@ -1017,8 +1033,11 @@
|
|||
// Note: disabled as it causes duplicate hooks, see https://github.com/developit/preact/issues/750
|
||||
// flushMounts();
|
||||
|
||||
if (component.componentDidUpdate) {
|
||||
component.componentDidUpdate(previousProps, previousState, snapshot);
|
||||
// if (component.componentDidUpdate) {
|
||||
// component.componentDidUpdate(previousProps, previousState, snapshot);
|
||||
// }
|
||||
if (component.store.updated) {
|
||||
component.store.updated(previousProps, previousState, snapshot);
|
||||
}
|
||||
if (options.afterUpdate) options.afterUpdate(component);
|
||||
}
|
||||
|
@ -1087,8 +1106,8 @@
|
|||
|
||||
component._disable = true;
|
||||
|
||||
if (component.componentWillUnmount) component.componentWillUnmount();
|
||||
|
||||
//if (component.componentWillUnmount) component.componentWillUnmount();
|
||||
if (component.store.uninstall) component.store.uninstall();
|
||||
component.base = null;
|
||||
|
||||
// recursively tear down & recollect high-order component children:
|
||||
|
@ -1135,7 +1154,7 @@
|
|||
* @type {object}
|
||||
*/
|
||||
this.context = context;
|
||||
|
||||
this.store = {};
|
||||
/**
|
||||
* @public
|
||||
* @type {object}
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -1,5 +1,5 @@
|
|||
/**
|
||||
* omis v0.3.0 http://omijs.org
|
||||
* omis v0.4.0 http://omijs.org
|
||||
* Omi === Preact + Scoped CSS + Store System + Native Support in 3kb javascript.
|
||||
* By dntzhang https://github.com/dntzhang
|
||||
* Github: https://github.com/Tencent/omis
|
||||
|
@ -484,7 +484,8 @@ function flushMounts() {
|
|||
addStyleToHead(c.props.css, '_ds' + c.elementId);
|
||||
}
|
||||
if (options.afterMount) options.afterMount(c);
|
||||
if (c.componentDidMount) c.componentDidMount();
|
||||
//if (c.componentDidMount) c.componentDidMount();
|
||||
if (c.store.installed) c.store.installed();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -848,9 +849,15 @@ function setComponentProps(component, props, renderMode, context, mountAll) {
|
|||
|
||||
if (typeof component.constructor.getDerivedStateFromProps === 'undefined') {
|
||||
if (!component.base || mountAll) {
|
||||
if (component.componentWillMount) component.componentWillMount();
|
||||
} else if (component.componentWillReceiveProps) {
|
||||
component.componentWillReceiveProps(props, context);
|
||||
//if (component.componentWillMount) component.componentWillMount();
|
||||
if (component.store.install) component.store.install();
|
||||
} else {
|
||||
// if (component.componentWillReceiveProps) {
|
||||
// component.componentWillReceiveProps(props, context);
|
||||
// }
|
||||
if (component.store.receiveProps) {
|
||||
component.__needUpdate_ = component.store.receiveProps(props, context);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -913,11 +920,17 @@ function renderComponent(component, renderMode, mountAll, isChild) {
|
|||
component.props = previousProps;
|
||||
component.state = previousState;
|
||||
component.context = previousContext;
|
||||
if (renderMode !== 2 && component.shouldComponentUpdate && component.shouldComponentUpdate(props, state, context) === false) {
|
||||
|
||||
if (component.__needUpdate_ !== false) {
|
||||
skip = false;
|
||||
if (component.store.beforeUpdate) {
|
||||
component.store.beforeUpdate(props, state, context);
|
||||
}
|
||||
} else {
|
||||
skip = true;
|
||||
} else if (component.componentWillUpdate) {
|
||||
component.componentWillUpdate(props, state, context);
|
||||
}
|
||||
delete component.__needUpdate_;
|
||||
|
||||
component.props = props;
|
||||
component.state = state;
|
||||
component.context = context;
|
||||
|
@ -928,6 +941,9 @@ function renderComponent(component, renderMode, mountAll, isChild) {
|
|||
|
||||
if (!skip) {
|
||||
options.runTimeComponent = component;
|
||||
if (component.store.beforeRender) {
|
||||
component.store.beforeRender();
|
||||
}
|
||||
rendered = component.render(props, state, context);
|
||||
options.runTimeComponent = null;
|
||||
|
||||
|
@ -1014,8 +1030,11 @@ function renderComponent(component, renderMode, mountAll, isChild) {
|
|||
// Note: disabled as it causes duplicate hooks, see https://github.com/developit/preact/issues/750
|
||||
// flushMounts();
|
||||
|
||||
if (component.componentDidUpdate) {
|
||||
component.componentDidUpdate(previousProps, previousState, snapshot);
|
||||
// if (component.componentDidUpdate) {
|
||||
// component.componentDidUpdate(previousProps, previousState, snapshot);
|
||||
// }
|
||||
if (component.store.updated) {
|
||||
component.store.updated(previousProps, previousState, snapshot);
|
||||
}
|
||||
if (options.afterUpdate) options.afterUpdate(component);
|
||||
}
|
||||
|
@ -1084,8 +1103,8 @@ function unmountComponent(component) {
|
|||
|
||||
component._disable = true;
|
||||
|
||||
if (component.componentWillUnmount) component.componentWillUnmount();
|
||||
|
||||
//if (component.componentWillUnmount) component.componentWillUnmount();
|
||||
if (component.store.uninstall) component.store.uninstall();
|
||||
component.base = null;
|
||||
|
||||
// recursively tear down & recollect high-order component children:
|
||||
|
@ -1132,7 +1151,7 @@ function Component(props, context) {
|
|||
* @type {object}
|
||||
*/
|
||||
this.context = context;
|
||||
|
||||
this.store = {};
|
||||
/**
|
||||
* @public
|
||||
* @type {object}
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -146,7 +146,7 @@
|
|||
if (c.constructor.css) addStyleToHead(c.constructor.css, getCtorName(c.constructor));
|
||||
if (c.props.css) addStyleToHead(c.props.css, '_ds' + c.elementId);
|
||||
if (options.afterMount) options.afterMount(c);
|
||||
if (c.componentDidMount) c.componentDidMount();
|
||||
if (c.store.installed) c.store.installed();
|
||||
}
|
||||
}
|
||||
function diff(dom, vnode, context, mountAll, parent, componentRoot, store) {
|
||||
|
@ -288,8 +288,8 @@
|
|||
delete props.ref;
|
||||
delete props.key;
|
||||
if (void 0 === component.constructor.getDerivedStateFromProps) if (!component.base || mountAll) {
|
||||
if (component.componentWillMount) component.componentWillMount();
|
||||
} else if (component.componentWillReceiveProps) component.componentWillReceiveProps(props, context);
|
||||
if (component.store.install) component.store.install();
|
||||
} else if (component.store.receiveProps) component.R = component.store.receiveProps(props, context);
|
||||
if (context && context !== component.context) {
|
||||
if (!component.__c) component.__c = component.context;
|
||||
component.context = context;
|
||||
|
@ -312,7 +312,11 @@
|
|||
component.props = previousProps;
|
||||
component.state = previousState;
|
||||
component.context = previousContext;
|
||||
if (2 !== renderMode && component.shouldComponentUpdate && !1 === component.shouldComponentUpdate(props, state, context)) skip = !0; else if (component.componentWillUpdate) component.componentWillUpdate(props, state, context);
|
||||
if (!1 !== component.R) {
|
||||
skip = !1;
|
||||
if (component.store.beforeUpdate) component.store.beforeUpdate(props, state, context);
|
||||
} else skip = !0;
|
||||
delete component.R;
|
||||
component.props = props;
|
||||
component.state = state;
|
||||
component.context = context;
|
||||
|
@ -321,6 +325,7 @@
|
|||
component.__d = !1;
|
||||
if (!skip) {
|
||||
options.runTimeComponent = component;
|
||||
if (component.store.beforeRender) component.store.beforeRender();
|
||||
rendered = component.render(props, state, context);
|
||||
options.runTimeComponent = null;
|
||||
if (component.getChildContext) context = extend(extend({}, context), component.getChildContext());
|
||||
|
@ -367,7 +372,7 @@
|
|||
}
|
||||
}
|
||||
if (!isUpdate || mountAll) mounts.push(component); else if (!skip) {
|
||||
if (component.componentDidUpdate) component.componentDidUpdate(previousProps, previousState, snapshot);
|
||||
if (component.store.updated) component.store.updated(previousProps, previousState, snapshot);
|
||||
if (options.afterUpdate) options.afterUpdate(component);
|
||||
}
|
||||
while (component.__h.length) component.__h.pop().call(component);
|
||||
|
@ -403,7 +408,7 @@
|
|||
if (options.beforeUnmount) options.beforeUnmount(component);
|
||||
var base = component.base;
|
||||
component.__x = !0;
|
||||
if (component.componentWillUnmount) component.componentWillUnmount();
|
||||
if (component.store.uninstall) component.store.uninstall();
|
||||
component.base = null;
|
||||
var inner = component._component;
|
||||
if (inner) unmountComponent(inner); else if (base) {
|
||||
|
@ -419,6 +424,7 @@
|
|||
this.__d = !0;
|
||||
this.elementId = id++;
|
||||
this.context = context;
|
||||
this.store = {};
|
||||
this.props = props;
|
||||
this.state = this.state || {};
|
||||
this.__h = [];
|
||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "omis",
|
||||
"version": "0.3.0",
|
||||
"version": "0.4.0",
|
||||
"description": "Functional Component with store, scoped css and easy hyperscript.",
|
||||
"main": "dist/omis.js",
|
||||
"jsnext:main": "dist/omis.esm.js",
|
||||
|
|
|
@ -34,7 +34,7 @@ export function setComponentProps(component, props, renderMode, context, mountAl
|
|||
// component.componentWillReceiveProps(props, context);
|
||||
// }
|
||||
if (component.store.receiveProps) {
|
||||
component.store.receiveProps(props, context)
|
||||
component.__needUpdate_ = component.store.receiveProps(props, context)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -99,19 +99,17 @@ export function renderComponent(component, renderMode, mountAll, isChild) {
|
|||
component.props = previousProps;
|
||||
component.state = previousState;
|
||||
component.context = previousContext;
|
||||
if (renderMode!==FORCE_RENDER
|
||||
&& component.shouldComponentUpdate
|
||||
&& component.shouldComponentUpdate(props, state, context) === false) {
|
||||
skip = true;
|
||||
}
|
||||
else {
|
||||
// if (component.componentWillUpdate) {
|
||||
// component.componentWillUpdate(props, state, context);
|
||||
// }
|
||||
if(component.store.beforeUpdate){
|
||||
|
||||
if (component.__needUpdate_ !== false) {
|
||||
skip = false
|
||||
if (component.store.beforeUpdate) {
|
||||
component.store.beforeUpdate(props, state, context)
|
||||
}
|
||||
} else {
|
||||
skip = true
|
||||
}
|
||||
delete component.__needUpdate_
|
||||
|
||||
component.props = props;
|
||||
component.state = state;
|
||||
component.context = context;
|
||||
|
|
|
@ -105,4 +105,89 @@ describe('lifecycle', () => {
|
|||
expect(arr).to.deep.equal(['install', 'beforeRender', 'installed', 'beforeUpdate', 'beforeRender', 'updated', 'receiveProps', 'beforeUpdate', 'beforeRender', 'updated', 'uninstall'])
|
||||
})
|
||||
|
||||
|
||||
|
||||
it('receiveProps return false test', () => {
|
||||
|
||||
const arr = []
|
||||
const Counter = (props, store) => {
|
||||
return (
|
||||
<div>
|
||||
<button class='simple-test-a' onClick={store.sub}>-</button>
|
||||
<span>{store.count}</span>
|
||||
<button onClick={store.add}>+</button>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
Counter.store = _ => {
|
||||
return {
|
||||
count: 1,
|
||||
add(e) {
|
||||
this.count++
|
||||
this.update()
|
||||
_.props.onChange(this.count)
|
||||
},
|
||||
sub() {
|
||||
this.count--
|
||||
this.update()
|
||||
_.props.onChange(this.count)
|
||||
},
|
||||
install() {
|
||||
arr.push('install')
|
||||
},
|
||||
installed() {
|
||||
arr.push('installed')
|
||||
},
|
||||
uninstall() {
|
||||
arr.push('uninstall')
|
||||
},
|
||||
beforeUpdate() {
|
||||
arr.push('beforeUpdate')
|
||||
},
|
||||
updated() {
|
||||
arr.push('updated')
|
||||
},
|
||||
beforeRender() {
|
||||
arr.push('beforeRender')
|
||||
},
|
||||
receiveProps() {
|
||||
arr.push('receiveProps')
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const App = (props, store) => {
|
||||
return (
|
||||
<div>
|
||||
<div class='simple-test-b' onClick={store.toggle}>Count from child event: {store.count}</div>
|
||||
{store.show && <Counter onChange={store.changeHandle}></Counter>}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
App.store = _ => {
|
||||
class Store {
|
||||
count = null
|
||||
show = true
|
||||
changeHandle = (count) => {
|
||||
this.count = count
|
||||
this.update()
|
||||
}
|
||||
toggle = () => {
|
||||
this.show = !this.show
|
||||
this.update()
|
||||
}
|
||||
}
|
||||
|
||||
return new Store
|
||||
}
|
||||
|
||||
render(<App />, scratch)
|
||||
|
||||
document.querySelector('.simple-test-a').click()
|
||||
document.querySelector('.simple-test-b').click()
|
||||
expect(arr).to.deep.equal(['install', 'beforeRender', 'installed', 'beforeUpdate', 'beforeRender', 'updated', 'receiveProps', 'uninstall'])
|
||||
})
|
||||
})
|
||||
|
|
|
@ -0,0 +1,43 @@
|
|||
## Lifecycle
|
||||
|
||||
| Lifecycle method | When it gets called |
|
||||
| ---------------- | -------------------------------------------- |
|
||||
| `install` | before the component gets mounted to the DOM |
|
||||
| `installed` | after the component gets mounted to the DOM |
|
||||
| `uninstall` | prior to removal from the DOM |
|
||||
| `beforeUpdate` | before update |
|
||||
| `updated` | after update |
|
||||
| `beforeRender` | before `render()` |
|
||||
| `receiveProps` | parent element re-render will trigger it, `return false` will prevent update action |
|
||||
|
||||
For example:
|
||||
|
||||
```js
|
||||
import { render, WeElement, define } from 'omi'
|
||||
|
||||
define('my-timer', class extends WeElement {
|
||||
static observe = true
|
||||
|
||||
data = {
|
||||
seconds: 0
|
||||
}
|
||||
|
||||
tick() {
|
||||
this.data.seconds++
|
||||
}
|
||||
|
||||
install() {
|
||||
this.interval = setInterval(() => this.tick(), 1000)
|
||||
}
|
||||
|
||||
uninstall() {
|
||||
clearInterval(this.interval)
|
||||
}
|
||||
|
||||
render() {
|
||||
return <div>Seconds: {this.data.seconds}</div>
|
||||
}
|
||||
})
|
||||
|
||||
render(<my-timer />, 'body')
|
||||
```
|
|
@ -0,0 +1,43 @@
|
|||
|
||||
### 生命周期
|
||||
|
||||
| 方法名 | 执行时机 |
|
||||
| ---------------- | -------------------------------------------- |
|
||||
| `install` | 准备插入到文档 |
|
||||
| `installed` | 插入到文档之后 |
|
||||
| `uninstall` | 从文档中移除 |
|
||||
| `beforeUpdate` | update 之前 |
|
||||
| `updated` | update 之后 |
|
||||
| `beforeRender` | `render()` 之前 |
|
||||
| `receiveProps` | 父元素重新渲染触发,返回 false 可阻止更新 |
|
||||
|
||||
举个例子:
|
||||
|
||||
```js
|
||||
import { render, WeElement, define } from 'omi'
|
||||
|
||||
define('my-timer', class extends WeElement {
|
||||
data = {
|
||||
seconds: 0
|
||||
}
|
||||
|
||||
tick() {
|
||||
this.data.seconds++
|
||||
this.update()
|
||||
}
|
||||
|
||||
install() {
|
||||
this.interval = setInterval(() => this.tick(), 1000)
|
||||
}
|
||||
|
||||
uninstall() {
|
||||
clearInterval(this.interval)
|
||||
}
|
||||
|
||||
render() {
|
||||
return <div>Seconds: {this.data.seconds}</div>
|
||||
}
|
||||
})
|
||||
|
||||
render(<my-timer />, 'body')
|
||||
```
|
Loading…
Reference in New Issue