React实现双向数据绑定
Wscats opened this issue · 0 comments
Wscats commented
利用Proxy
对数据进行劫持,自动触发this.setState
import { define, WeElement, html, h, extend, get, set } from "omi";
export interface appOptions {
name: string;
view(props?: any, state?: any, ref?: any);
state?: any;
propTypes?: any;
props?: any;
defaultProps?: any;
css?: string;
install?(props?: any, state?: any, ref?: any);
installed?(props?: any, state?: any, ref?: any);
uninstall?(props?: any, state?: any, ref?: any);
beforeUpdate?(props?: any, state?: any, ref?: any);
updated?(props?: any, state?: any, ref?: any);
beforeRender?(props?: any, state?: any, ref?: any);
receiveProps?(props?: any, state?: any, ref?: any);
}
// Added code
const isObject = obj => Object.prototype.toString.call(obj) === '[object Object]';
// Added code
const observify = (obj, that) => {
if (!isObject(obj)) {
return obj;
}
Object.keys(obj).forEach(key => {
obj[key] = observify(obj[key], that);
});
return Observer(obj, that);
}
// Added code
const Observer = (obj, that) => {
return new Proxy(obj, {
set(obj, prop, value) {
const res = Reflect.set(obj, prop, value);
that.update();
return res;
}
});
}
const app = ({
name,
view,
state,
propTypes,
props,
defaultProps,
css,
install,
installed,
uninstall,
beforeUpdate,
updated,
beforeRender,
receiveProps
}: appOptions) => {
define(name, class extends WeElement {
state = Object.assign({}, state);
static props = props;
static propTypes = propTypes;
static defaultProps = defaultProps;
static css = css;
private ref;
constructor() {
super();
(that => {
// Added code
that.state = observify(that.state, that)
})(this);
}
install() {
install &&
install(
this.props ? this.props : {},
this.state ? this.state : {},
this
);
}
installed() {
installed &&
installed(
this.props ? this.props : {},
this.state ? this.state : {},
this
);
}
uninstall() {
uninstall &&
uninstall(
this.props ? this.props : {},
this.state ? this.state : {},
this
);
}
render(oProps, oState) {
return view(
this.props ? this.props : oProps,
this.state ? this.state : oState,
this
);
}
});
};
extend("model", (el: any, path, scope) => {
el.value = get(scope, path);
el.addEventListener("input", () => {
set(scope, path, el.value);
scope.update();
});
});
export { html, h, app };