├── src ├── index.scss ├── depend-component │ ├── .gitkeep │ ├── TestHooks │ │ └── index.tsx │ ├── ReactiveCounter │ │ └── index.tsx │ ├── ProxyCounter │ │ └── index.tsx │ └── ContextCounter │ │ └── index.tsx ├── component │ ├── index.module.scss.d.ts │ ├── index.module.scss │ └── index.tsx ├── util │ ├── index.ts │ ├── jsontostring.ts │ ├── hook.ts │ ├── context.tsx │ ├── reactiveproxy.ts │ └── proxy.ts ├── index.tsx └── index.html ├── lib ├── types │ ├── index.d.ts │ ├── util │ │ ├── hook.d.ts │ │ ├── index.d.ts │ │ ├── jsontostring.d.ts │ │ ├── proxy.d.ts │ │ ├── reactiveproxy.d.ts │ │ └── context.d.ts │ ├── depend-component │ │ ├── TestHooks │ │ │ └── index.d.ts │ │ ├── ProxyCounter │ │ │ └── index.d.ts │ │ ├── ContextCounter │ │ │ └── index.d.ts │ │ └── ReactiveCounter │ │ │ └── index.d.ts │ └── component │ │ └── index.d.ts ├── jsontostring.js ├── index.js ├── reactiveproxy.js ├── hook.js ├── context.js └── proxy.js ├── tslint.json ├── .gitignore ├── tsconfig.json ├── md ├── rxhook.md ├── reactivecontext.md ├── origincontext.md └── proxy.md ├── README.md └── package.json /src/index.scss: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/depend-component/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /lib/types/index.d.ts: -------------------------------------------------------------------------------- 1 | export {}; 2 | -------------------------------------------------------------------------------- /src/component/index.module.scss.d.ts: -------------------------------------------------------------------------------- 1 | export {}; 2 | -------------------------------------------------------------------------------- /src/component/index.module.scss: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | } -------------------------------------------------------------------------------- /lib/types/util/hook.d.ts: -------------------------------------------------------------------------------- 1 | export declare function rxhook(obj: T, isasync?: boolean): T; 2 | -------------------------------------------------------------------------------- /lib/types/depend-component/TestHooks/index.d.ts: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | export declare const ProxyCounter: React.FC; 3 | -------------------------------------------------------------------------------- /src/util/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./hook"; 2 | export * from "./reactiveproxy"; 3 | export * from "./proxy"; 4 | export * from "./jsontostring"; 5 | export * from "./context"; 6 | -------------------------------------------------------------------------------- /lib/types/util/index.d.ts: -------------------------------------------------------------------------------- 1 | export * from "./hook"; 2 | export * from "./reactiveproxy"; 3 | export * from "./proxy"; 4 | export * from "./jsontostring"; 5 | export * from "./context"; 6 | -------------------------------------------------------------------------------- /lib/types/util/jsontostring.d.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * 将对象中的函数转化为字符串 3 | * 所有的内容可以正确打印 4 | * @export 5 | * @param {object} obj 6 | * @returns {string} 7 | */ 8 | export declare function proxyjsonobj(obj: object): string; 9 | -------------------------------------------------------------------------------- /lib/types/util/proxy.d.ts: -------------------------------------------------------------------------------- 1 | import 'reflect-metadata'; 2 | export declare function ProxyState(isproxy?: boolean): (this: any, target: any, prop: string | number | symbol) => void; 3 | export declare function ProxyComponent(): (target: any) => any; 4 | -------------------------------------------------------------------------------- /src/index.tsx: -------------------------------------------------------------------------------- 1 | import { Test } from "./component/index"; 2 | import * as React from 'react'; 3 | import * as ReactDOM from 'react-dom'; 4 | 5 | ReactDOM.render(, document.getElementById('root')); 6 | 7 | 8 | if (module.hot) { 9 | module.hot.accept(); 10 | } -------------------------------------------------------------------------------- /lib/types/depend-component/ProxyCounter/index.d.ts: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | declare type IProxyState = { 3 | count: number; 4 | }; 5 | export declare class ProxyCounter extends React.Component<{}, { 6 | proxystate: IProxyState; 7 | }> { 8 | constructor(props: Readonly<{}>); 9 | proxystate: IProxyState; 10 | render(): JSX.Element; 11 | } 12 | export declare const ProxyCounterChild: React.FC<{ 13 | proxyprop: IProxyState; 14 | }>; 15 | export {}; 16 | -------------------------------------------------------------------------------- /src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Youku development Component 9 | 10 | 11 | 12 | 15 |
16 | 17 | 18 | -------------------------------------------------------------------------------- /lib/types/depend-component/ContextCounter/index.d.ts: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { UnPackReactContext } from "../../util"; 3 | export declare const context: React.Context<{ 4 | count: number; 5 | addcount: () => void; 6 | }>; 7 | export declare const Demo: React.FC; 8 | export declare class ContextCounter extends React.Component> { 9 | render(): JSX.Element; 10 | } 11 | export declare const ContextCounterFC: React.FC>; 12 | -------------------------------------------------------------------------------- /src/util/jsontostring.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * 将对象中的函数转化为字符串 3 | * 所有的内容可以正确打印 4 | * @export 5 | * @param {object} obj 6 | * @returns {string} 7 | */ 8 | export function proxyjsonobj(obj: object): string { 9 | const handler = { 10 | get: (target: object, prop: number | string | symbol): any => { 11 | // 递归创建并返回 12 | if (typeof target[prop] === 'function' && target[prop] !== null) { 13 | return target[prop].toString(); 14 | } 15 | return Reflect.get(target, prop); 16 | }, 17 | }; 18 | 19 | const proxyobj = new Proxy(obj, handler); 20 | 21 | return JSON.stringify(proxyobj); 22 | } 23 | -------------------------------------------------------------------------------- /src/depend-component/TestHooks/index.tsx: -------------------------------------------------------------------------------- 1 | import React, { useEffect } from 'react' 2 | import { rxhook } from '../../util/index'; 3 | 4 | 5 | export const ProxyCounter: React.FC = _props => { 6 | 7 | const state = rxhook({ count: 123, double: 0 }); 8 | 9 | useEffect(() => { 10 | state.double = state.count * 2 11 | }, [state.count]); 12 | 13 | return ( 14 |
15 |
{state.count}
16 |
{state.double}
17 | 24 |
25 | ) 26 | } -------------------------------------------------------------------------------- /lib/types/util/reactiveproxy.d.ts: -------------------------------------------------------------------------------- 1 | import 'reflect-metadata'; 2 | declare type renderUpdateType = ((val: any, prop: number | string | symbol) => void) | { 3 | isasync: boolean; 4 | renderUpdate: (val: any, prop: number | string | symbol) => void; 5 | }; 6 | /** 7 | * 获取Proxy 对象 8 | * 9 | * @export 10 | * @param {object} obj 11 | * @param {() => void} renderUpdate 12 | * @returns {*} 13 | */ 14 | export declare function ReactiveProxy(obj: object, renderUpdate: renderUpdateType): any; 15 | export declare function ReactiveOrigin(proxyobj: T): T; 16 | export declare function ReactiveSingle(this: any, property: string): any; 17 | export {}; 18 | -------------------------------------------------------------------------------- /lib/jsontostring.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | Object.defineProperty(exports, "__esModule", { 4 | value: true 5 | }); 6 | exports.proxyjsonobj = proxyjsonobj; 7 | 8 | /** 9 | * 将对象中的函数转化为字符串 10 | * 所有的内容可以正确打印 11 | * @export 12 | * @param {object} obj 13 | * @returns {string} 14 | */ 15 | function proxyjsonobj(obj) { 16 | var handler = { 17 | get: function get(target, prop) { 18 | // 递归创建并返回 19 | if (typeof target[prop] === 'function' && target[prop] !== null) { 20 | return target[prop].toString(); 21 | } 22 | 23 | return Reflect.get(target, prop); 24 | } 25 | }; 26 | var proxyobj = new Proxy(obj, handler); 27 | return JSON.stringify(proxyobj); 28 | } -------------------------------------------------------------------------------- /lib/types/depend-component/ReactiveCounter/index.d.ts: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { UnPackReactContext } from "../../util"; 3 | export declare const context: React.Context<{ 4 | proxystate: { 5 | count: number; 6 | }; 7 | }>; 8 | declare type IProxyState = { 9 | count: number; 10 | }; 11 | export declare class Demo extends React.Component<{}, { 12 | proxystate: IProxyState; 13 | }> { 14 | state: { 15 | proxystate: { 16 | count: number; 17 | }; 18 | }; 19 | render(): JSX.Element; 20 | } 21 | export declare class ReactiveCounter extends React.Component> { 22 | render(): JSX.Element; 23 | } 24 | export {}; 25 | -------------------------------------------------------------------------------- /lib/types/util/context.d.ts: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | declare type Props = { 3 | context: React.Context; 4 | initialidata: T; 5 | }; 6 | export declare class ContextProvider extends React.Component, any> { 7 | constructor(props: Props); 8 | render(): JSX.Element; 9 | } 10 | export declare class ReactiveProvider extends React.Component, any> { 11 | store: {} & T; 12 | constructor(props: Props); 13 | render(): JSX.Element; 14 | } 15 | export declare function consumer(provider: React.Context): (target: U) => U; 16 | export declare type UnPackReactContext = T extends React.Context ? Partial : unknown; 17 | export {}; 18 | -------------------------------------------------------------------------------- /tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["tslint:recommended", "tslint-react", "tslint-config-prettier"], 3 | "linterOptions": { 4 | "exclude": [ 5 | "config/**/*.js", 6 | "node_modules/**/*.ts", 7 | "coverage/lcov-report/*.js", 8 | "src/static/**/*.js" 9 | ] 10 | }, 11 | "rules": { 12 | "ordered-imports": false, 13 | "member-ordering": false, 14 | "object-literal-sort-keys": false, 15 | "strict-type-predicates": false, 16 | "triple-equals": false, 17 | "no-debugger": false, 18 | "no-console": false, 19 | "no-empty": false, 20 | "no-empty-interface": false, 21 | "no-eval": false, 22 | "no-for-in-array": false, 23 | "jsx-no-lambda": false, 24 | "interface-name": false, 25 | "member-access": [true, "no-public", "check-accessor"], 26 | "variable-name": false, 27 | "no-var-requires": false, 28 | "object-literal-shorthand": false, 29 | "only-arrow-functions": [false] 30 | } 31 | } -------------------------------------------------------------------------------- /src/depend-component/ReactiveCounter/index.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { consumer, UnPackReactContext, ReactiveProvider } from "../../util"; 3 | 4 | export const context = React.createContext({ proxystate: { count: 0 } }); 5 | 6 | type IProxyState = { 7 | count: number; 8 | }; 9 | 10 | export class Demo extends React.Component<{}, { proxystate: IProxyState }> { 11 | state = { 12 | proxystate: { 13 | count: 1, 14 | }, 15 | }; 16 | 17 | render() { 18 | return ( 19 | 20 | 21 | 22 | ); 23 | } 24 | } 25 | 26 | @consumer(context) 27 | export class ReactiveCounter extends React.Component< 28 | UnPackReactContext 29 | > { 30 | render() { 31 | return ( 32 |
33 |
{this.props.proxystate!.count}
34 | 41 |
42 | ); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/util/hook.ts: -------------------------------------------------------------------------------- 1 | import { useState } from 'react'; 2 | 3 | export function rxhook(obj: T, isasync = false): T { 4 | let asyncid: NodeJS.Timeout | null = null; 5 | const [originobj, setoriginobj] = useState(obj); 6 | 7 | const handler = { 8 | get: (target: object, prop: number | string | symbol): any => { 9 | // 递归创建并返回 10 | if (typeof target[prop] === 'object' && target[prop] !== null) { 11 | return new Proxy(target[prop], handler); 12 | } 13 | return Reflect.get(target, prop); 14 | }, 15 | set: (target: object, prop: number | string | symbol, value: any) => { 16 | const reuslt = Reflect.set(target, prop, value); 17 | if (isasync) { 18 | if (asyncid) { 19 | clearTimeout(asyncid); 20 | } 21 | asyncid = setTimeout(() => { 22 | setoriginobj(originobj); 23 | }, 0); 24 | } else { 25 | setoriginobj(Object.assign({}, originobj)); 26 | } 27 | return reuslt; 28 | }, 29 | }; 30 | 31 | const proxyobj = new Proxy(originobj, handler); 32 | Reflect.defineMetadata('$$origindata', proxyobj, originobj); 33 | return proxyobj as typeof obj; 34 | } 35 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | 8 | # Runtime data 9 | pids 10 | *.pid 11 | *.seed 12 | *.pid.lock 13 | 14 | # Directory for instrumented libs generated by jscoverage/JSCover 15 | lib-cov 16 | 17 | # Coverage directory used by tools like istanbul 18 | coverage 19 | 20 | # nyc test coverage 21 | .nyc_output 22 | 23 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 24 | .grunt 25 | 26 | # Bower dependency directory (https://bower.io/) 27 | bower_components 28 | 29 | # node-waf configuration 30 | .lock-wscript 31 | 32 | # Compiled binary addons (http://nodejs.org/api/addons.html) 33 | build/Release 34 | 35 | # Dependency directories 36 | node_modules/ 37 | jspm_packages/ 38 | 39 | # Typescript v1 declaration files 40 | typings/ 41 | 42 | # Optional npm cache directory 43 | .npm 44 | 45 | # Optional eslint cache 46 | .eslintcache 47 | 48 | # Optional REPL history 49 | .node_repl_history 50 | 51 | # Output of 'npm pack' 52 | *.tgz 53 | 54 | # Yarn Integrity file 55 | .yarn-integrity 56 | 57 | # dotenv environment variables file 58 | .env 59 | 60 | app 61 | sop-test 62 | 63 | temp 64 | 65 | .vscode 66 | 67 | .DS_Store -------------------------------------------------------------------------------- /lib/types/component/index.d.ts: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import './index.module.scss'; 3 | interface ITestProps { 4 | } 5 | interface ITestState { 6 | proxystate: { 7 | name: string; 8 | age: number; 9 | children: any[]; 10 | pad?: any; 11 | id?: any; 12 | info: { 13 | address: string; 14 | }; 15 | }; 16 | student: { 17 | mat: number; 18 | address: string; 19 | }; 20 | myname: string; 21 | } 22 | export declare class Test extends React.Component { 23 | proxystate: { 24 | name: string; 25 | age: number; 26 | children: (string | number | { 27 | name: string; 28 | age: number; 29 | })[]; 30 | pad: null; 31 | id: undefined; 32 | info: { 33 | address: string; 34 | }; 35 | }; 36 | student: { 37 | mat: number; 38 | address: string; 39 | }; 40 | myname: string; 41 | constructor(props: any); 42 | componentDidMount(): void; 43 | render(): JSX.Element; 44 | } 45 | export declare class ChildTest extends React.Component { 46 | rendercount: number; 47 | componentDidMount(): void; 48 | render(): JSX.Element; 49 | } 50 | export {}; 51 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "declaration": true, 4 | "declarationDir": "./lib/types", 5 | "baseUrl": ".", 6 | "outDir": "./temp", 7 | "module": "esnext", 8 | "target": "esnext", 9 | "sourceMap": true, 10 | "moduleResolution": "node", 11 | "rootDir": "src", 12 | "forceConsistentCasingInFileNames": true, 13 | "noImplicitReturns": true, 14 | "noImplicitThis": true, 15 | "noImplicitAny": true, 16 | "suppressImplicitAnyIndexErrors": true, 17 | "strict": true, 18 | "lib": [ 19 | "dom", 20 | "dom.iterable", 21 | "esnext" 22 | ], 23 | "experimentalDecorators": true, 24 | "emitDecoratorMetadata": true, 25 | "charset": "utf8", 26 | "pretty": true, 27 | "jsx": "preserve", 28 | "noEmitOnError": false, 29 | "noUnusedLocals": true, 30 | "noUnusedParameters": true, 31 | "esModuleInterop": true, 32 | "allowUnreachableCode": false, 33 | "allowUnusedLabels": false, 34 | "strictPropertyInitialization": false, 35 | "noFallthroughCasesInSwitch": true, 36 | "skipLibCheck": true, 37 | "skipDefaultLibCheck": true, 38 | "importHelpers": true, 39 | "allowSyntheticDefaultImports": true, 40 | "resolveJsonModule": true, 41 | "strictNullChecks": true 42 | }, 43 | "exclude": [ 44 | "node_modules", 45 | "build", 46 | "lib", 47 | "dist" 48 | ] 49 | } -------------------------------------------------------------------------------- /src/depend-component/ProxyCounter/index.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { ProxyComponent, ProxyState } from "../../util/index"; 3 | 4 | type IProxyState = { 5 | count: number; 6 | }; 7 | 8 | @ProxyComponent() 9 | export class ProxyCounter extends React.Component< 10 | {}, 11 | { proxystate: IProxyState } 12 | > { 13 | constructor(props: Readonly<{}>) { 14 | super(props); 15 | } 16 | 17 | @ProxyState() 18 | proxystate: IProxyState = { 19 | count: 0, 20 | }; 21 | 22 | render() { 23 | return ( 24 |
25 |
Own component is valid
26 |
{this.state.proxystate.count}
27 | 35 | 36 |
37 | ); 38 | } 39 | } 40 | 41 | export const ProxyCounterChild: React.FC<{ proxyprop: IProxyState }> = ( 42 | prop 43 | ) => { 44 | return ( 45 |
46 |
Child component is valid
47 |
{prop.proxyprop.count}
48 | 56 |
57 | ); 58 | }; 59 | -------------------------------------------------------------------------------- /src/depend-component/ContextCounter/index.tsx: -------------------------------------------------------------------------------- 1 | import React, { useState } from "react"; 2 | import { ContextProvider, consumer, UnPackReactContext } from "../../util"; 3 | 4 | export const context = React.createContext({ count: 0, addcount: () => {} }); 5 | 6 | export const Demo: React.FC = () => { 7 | const [count, setCount] = useState(1); 8 | 9 | return ( 10 | { 15 | setCount(count + 1); 16 | }, 17 | }} 18 | > 19 | 20 | 21 | 22 | ); 23 | }; 24 | 25 | @consumer(context) 26 | export class ContextCounter extends React.Component< 27 | UnPackReactContext 28 | > { 29 | render() { 30 | return ( 31 |
32 |
{this.props.count}
33 | 40 |
41 | ); 42 | } 43 | } 44 | 45 | export const ContextCounterFC: React.FC> = consumer(context)((props) => { 48 | return ( 49 |
50 |
{props.count}
51 | 58 |
59 | ); 60 | }); 61 | -------------------------------------------------------------------------------- /md/rxhook.md: -------------------------------------------------------------------------------- 1 | # function rxhook 2 | 3 | ## introduction 4 | ``` 5 | Instead of using usestate in react hooks, instead of returning [object setobject], it is changed to a proxy object. The modification of the proxy object will trigger the rendering update of function components 6 | ``` 7 | 8 | ## Counter example 9 | 10 | ```typescript 11 | import React, { useEffect } from 'react' 12 | import { rxhook } from 'automatic-react'; 13 | 14 | 15 | export const ProxyCounter: React.FC = _props => { 16 | 17 | const state = rxhook({ count: 123, double: 0 }); 18 | 19 | useEffect(() => { 20 | state.double = state.count * 2 21 | }, [state.count]); 22 | 23 | return ( 24 |
25 |
{state.count}
26 |
{state.double}
27 | 34 |
35 | ) 36 | } 37 | ``` 38 | 39 | ## 简介 40 | ``` 41 | 在ReactHooks 中替代 useState 来使用,不再返回 [object setobject] 而是改为 代理对象, 对代理对象的修改则会触发 函数组件的渲染更新 42 | ``` 43 | 44 | ```typescript 45 | import React, { useEffect } from 'react' 46 | import { rxhook } from 'automatic-react'; 47 | 48 | 49 | export const ProxyCounter: React.FC = _props => { 50 | 51 | const state = rxhook({ count: 123, double: 0 }); 52 | 53 | useEffect(() => { 54 | state.double = state.count * 2 55 | }, [state.count]); 56 | 57 | return ( 58 |
59 |
{state.count}
60 |
{state.double}
61 | 68 |
69 | ) 70 | } 71 | ``` -------------------------------------------------------------------------------- /lib/index.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | Object.defineProperty(exports, "__esModule", { 4 | value: true 5 | }); 6 | 7 | var _hook = require("./hook"); 8 | 9 | Object.keys(_hook).forEach(function (key) { 10 | if (key === "default" || key === "__esModule") return; 11 | Object.defineProperty(exports, key, { 12 | enumerable: true, 13 | get: function get() { 14 | return _hook[key]; 15 | } 16 | }); 17 | }); 18 | 19 | var _reactiveproxy = require("./reactiveproxy"); 20 | 21 | Object.keys(_reactiveproxy).forEach(function (key) { 22 | if (key === "default" || key === "__esModule") return; 23 | Object.defineProperty(exports, key, { 24 | enumerable: true, 25 | get: function get() { 26 | return _reactiveproxy[key]; 27 | } 28 | }); 29 | }); 30 | 31 | var _proxy = require("./proxy"); 32 | 33 | Object.keys(_proxy).forEach(function (key) { 34 | if (key === "default" || key === "__esModule") return; 35 | Object.defineProperty(exports, key, { 36 | enumerable: true, 37 | get: function get() { 38 | return _proxy[key]; 39 | } 40 | }); 41 | }); 42 | 43 | var _jsontostring = require("./jsontostring"); 44 | 45 | Object.keys(_jsontostring).forEach(function (key) { 46 | if (key === "default" || key === "__esModule") return; 47 | Object.defineProperty(exports, key, { 48 | enumerable: true, 49 | get: function get() { 50 | return _jsontostring[key]; 51 | } 52 | }); 53 | }); 54 | 55 | var _context = require("./context"); 56 | 57 | Object.keys(_context).forEach(function (key) { 58 | if (key === "default" || key === "__esModule") return; 59 | Object.defineProperty(exports, key, { 60 | enumerable: true, 61 | get: function get() { 62 | return _context[key]; 63 | } 64 | }); 65 | }); -------------------------------------------------------------------------------- /src/util/context.tsx: -------------------------------------------------------------------------------- 1 | /* eslint-disable react/display-name */ 2 | import React from 'react'; 3 | import { ProxyComponent, ProxyState } from './proxy'; 4 | 5 | type Props = { 6 | context: React.Context; 7 | 8 | initialidata: T; 9 | }; 10 | 11 | export class ContextProvider extends React.Component, any> { 12 | constructor(props: Props) { 13 | super(props); 14 | } 15 | 16 | render(): JSX.Element { 17 | const Providerlayout = this.props.context.Provider; 18 | return ( 19 | 20 | {this.props.children} 21 | 22 | ); 23 | } 24 | } 25 | 26 | @ProxyComponent() 27 | export class ReactiveProvider extends React.Component, any> { 28 | @ProxyState() 29 | public store = Object.assign({}, this.props.initialidata); 30 | 31 | constructor(props: Props) { 32 | super(props); 33 | } 34 | 35 | render(): JSX.Element { 36 | const Providerlayout = this.props.context.Provider; 37 | return ( 38 | 39 | {this.props.children} 40 | 41 | ); 42 | } 43 | } 44 | 45 | export function consumer(provider: React.Context) { 46 | return function(target: U): U { 47 | const serivce = provider; 48 | return ((props: any) => { 49 | return ( 50 | 51 | {value => { 52 | return React.createElement(target as any, Object.assign({}, value, props)); 53 | }} 54 | 55 | ); 56 | }) as any; 57 | }; 58 | } 59 | 60 | export type UnPackReactContext = T extends React.Context ? Partial : unknown; 61 | -------------------------------------------------------------------------------- /src/util/reactiveproxy.ts: -------------------------------------------------------------------------------- 1 | import 'reflect-metadata'; 2 | 3 | type renderUpdateType = 4 | | ((val: any, prop: number | string | symbol) => void) 5 | | { isasync: boolean; renderUpdate: (val: any, prop: number | string | symbol) => void }; 6 | 7 | /** 8 | * 获取Proxy 对象 9 | * 10 | * @export 11 | * @param {object} obj 12 | * @param {() => void} renderUpdate 13 | * @returns {*} 14 | */ 15 | export function ReactiveProxy(obj: object, renderUpdate: renderUpdateType): any { 16 | let asyncid: NodeJS.Timeout | null = null; 17 | 18 | const handler = { 19 | get: (target: object, prop: number | string | symbol): any => { 20 | // 递归创建并返回 21 | if (typeof target[prop] === 'object' && target[prop] !== null) { 22 | return new Proxy(target[prop], handler); 23 | } 24 | return Reflect.get(target, prop); 25 | }, 26 | set: (target: object, prop: number | string | symbol, value: any) => { 27 | const reuslt = Reflect.set(target, prop, value); 28 | if (typeof renderUpdate === 'object' && renderUpdate.isasync === true) { 29 | if (asyncid) { 30 | clearTimeout(asyncid); 31 | } 32 | asyncid = setTimeout(() => { 33 | renderUpdate.renderUpdate(value, prop); 34 | }, 0); 35 | } else if (typeof renderUpdate === 'object' && renderUpdate.isasync === false) { 36 | renderUpdate.renderUpdate(value, prop); 37 | } else if (typeof renderUpdate === 'function') { 38 | renderUpdate(value, prop); 39 | } 40 | return reuslt; 41 | }, 42 | }; 43 | 44 | const proxyobj = new Proxy(obj, handler); 45 | 46 | Reflect.defineMetadata('$$origindata', proxyobj, obj); 47 | return proxyobj; 48 | } 49 | 50 | export function ReactiveOrigin(proxyobj: T): T { 51 | return Reflect.getMetadata('$$origindata', proxyobj); 52 | } 53 | 54 | export function ReactiveSingle(this: any, property: string) { 55 | return Reflect.getMetadata(`$$single_${property}`, this); 56 | } 57 | -------------------------------------------------------------------------------- /lib/reactiveproxy.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | Object.defineProperty(exports, "__esModule", { 4 | value: true 5 | }); 6 | exports.ReactiveProxy = ReactiveProxy; 7 | exports.ReactiveOrigin = ReactiveOrigin; 8 | exports.ReactiveSingle = ReactiveSingle; 9 | 10 | require("reflect-metadata"); 11 | 12 | function _typeof(obj) { "@babel/helpers - typeof"; if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); } 13 | 14 | /** 15 | * 获取Proxy 对象 16 | * 17 | * @export 18 | * @param {object} obj 19 | * @param {() => void} renderUpdate 20 | * @returns {*} 21 | */ 22 | function ReactiveProxy(obj, renderUpdate) { 23 | var asyncid = null; 24 | var handler = { 25 | get: function get(target, prop) { 26 | // 递归创建并返回 27 | if (_typeof(target[prop]) === 'object' && target[prop] !== null) { 28 | return new Proxy(target[prop], handler); 29 | } 30 | 31 | return Reflect.get(target, prop); 32 | }, 33 | set: function set(target, prop, value) { 34 | var reuslt = Reflect.set(target, prop, value); 35 | 36 | if (_typeof(renderUpdate) === 'object' && renderUpdate.isasync === true) { 37 | if (asyncid) { 38 | clearTimeout(asyncid); 39 | } 40 | 41 | asyncid = setTimeout(function () { 42 | renderUpdate.renderUpdate(value, prop); 43 | }, 0); 44 | } else if (_typeof(renderUpdate) === 'object' && renderUpdate.isasync === false) { 45 | renderUpdate.renderUpdate(value, prop); 46 | } else if (typeof renderUpdate === 'function') { 47 | renderUpdate(value, prop); 48 | } 49 | 50 | return reuslt; 51 | } 52 | }; 53 | var proxyobj = new Proxy(obj, handler); 54 | Reflect.defineMetadata('$$origindata', proxyobj, obj); 55 | return proxyobj; 56 | } 57 | 58 | function ReactiveOrigin(proxyobj) { 59 | return Reflect.getMetadata('$$origindata', proxyobj); 60 | } 61 | 62 | function ReactiveSingle(property) { 63 | return Reflect.getMetadata("$$single_".concat(property), this); 64 | } -------------------------------------------------------------------------------- /src/component/index.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import './index.module.scss'; 3 | import { ProxyState, ProxyComponent } from '../util/proxy'; 4 | 5 | interface ITestProps { } 6 | 7 | interface ITestState { 8 | 9 | proxystate: { 10 | name: string; 11 | age: number; 12 | children: any[], 13 | pad?: any; 14 | id?: any; 15 | info: { address: string } 16 | } 17 | 18 | student: { 19 | mat: number; 20 | address: string; 21 | }; 22 | 23 | myname: string; 24 | } 25 | 26 | @ProxyComponent() 27 | export class Test extends React.Component{ 28 | 29 | @ProxyState() 30 | public proxystate = { 31 | name: "tom", 32 | age: 16, 33 | children: ["mike", 22, { name: "tolar", age: 11 }], 34 | pad: null, 35 | id: undefined, 36 | info: { 37 | address: "ksilxi os l66" 38 | } 39 | } 40 | 41 | @ProxyState() 42 | public student = { 43 | mat: 8928, 44 | address: "home in beijing" 45 | } 46 | 47 | @ProxyState() 48 | public myname = "mike jackson" 49 | 50 | constructor(props: any) { 51 | super(props); 52 | } 53 | 54 | componentDidMount() { 55 | /** 修改引用值触发渲染 */ 56 | this.student.mat = 2737; 57 | } 58 | 59 | render(): JSX.Element { 60 | return ( 61 |
62 | student name is {this.state.student.mat} 63 |
64 | myname is {this.state.myname} 65 |
66 | student name is {this.state.student.mat} 67 |
68 | myname is {this.myname} 69 | { 73 | this.myname = name; 74 | }} 75 | student={this.student} 76 | changestudent={(student: any) => { 77 | this.student = student 78 | }} 79 | /> 80 |
81 | ); 82 | } 83 | } 84 | 85 | 86 | @ProxyComponent() 87 | export class ChildTest extends React.Component{ 88 | 89 | public rendercount = 0; 90 | 91 | componentDidMount() { 92 | /** 重新设置单值 */ 93 | this.props.changename("upolsy"); 94 | /** 在引用对象上改值 */ 95 | this.props.student.mat = 9999; 96 | /** 重新设置引用 */ 97 | this.props.changestudent({ 98 | mat: 2523, 99 | address: "home in sydeny" 100 | }) 101 | /** 在引用对象上改值 */ 102 | this.props.obj.name = "jack 666"; 103 | this.props.obj.children.push({ age: 99 }); 104 | } 105 | 106 | render(): JSX.Element { 107 | this.rendercount = this.rendercount + 1; 108 | console.log(this.rendercount); 109 | const text = JSON.stringify(this.props.obj, null, 4); 110 | return ( 111 |
112 | ChildTest myname is {this.props.name} 113 |
114 |           {text}
115 |         
116 |
117 | ); 118 | } 119 | } 120 | 121 | -------------------------------------------------------------------------------- /lib/hook.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | Object.defineProperty(exports, "__esModule", { 4 | value: true 5 | }); 6 | exports.rxhook = rxhook; 7 | 8 | var _react = require("react"); 9 | 10 | function _typeof(obj) { "@babel/helpers - typeof"; if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); } 11 | 12 | function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); } 13 | 14 | function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } 15 | 16 | function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(n); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); } 17 | 18 | function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; } 19 | 20 | function _iterableToArrayLimit(arr, i) { if (typeof Symbol === "undefined" || !(Symbol.iterator in Object(arr))) return; var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } 21 | 22 | function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; } 23 | 24 | function rxhook(obj) { 25 | var isasync = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false; 26 | var asyncid = null; 27 | 28 | var _useState = (0, _react.useState)(obj), 29 | _useState2 = _slicedToArray(_useState, 2), 30 | originobj = _useState2[0], 31 | setoriginobj = _useState2[1]; 32 | 33 | var handler = { 34 | get: function get(target, prop) { 35 | // 递归创建并返回 36 | if (_typeof(target[prop]) === 'object' && target[prop] !== null) { 37 | return new Proxy(target[prop], handler); 38 | } 39 | 40 | return Reflect.get(target, prop); 41 | }, 42 | set: function set(target, prop, value) { 43 | var reuslt = Reflect.set(target, prop, value); 44 | 45 | if (isasync) { 46 | if (asyncid) { 47 | clearTimeout(asyncid); 48 | } 49 | 50 | asyncid = setTimeout(function () { 51 | setoriginobj(originobj); 52 | }, 0); 53 | } else { 54 | setoriginobj(Object.assign({}, originobj)); 55 | } 56 | 57 | return reuslt; 58 | } 59 | }; 60 | var proxyobj = new Proxy(originobj, handler); 61 | Reflect.defineMetadata('$$origindata', proxyobj, originobj); 62 | return proxyobj; 63 | } -------------------------------------------------------------------------------- /md/reactivecontext.md: -------------------------------------------------------------------------------- 1 | # HocClassComponent ReactiveProvider 2 | 3 | ## introduction 4 | 5 | - ReactiveProvider 6 |

7 | You can understand that 'contextprovider' adds an upgraded version of auto rendering. Different from the previous react.context, development not only needs to pass in 'data' but also 'modify data' methods. The 'reactiveprovider' can let you pass in the data, as a proxy rendering object, directly assign the 'data' value, which will trigger. Under all the components, the components included in the '@ consumer' method will be used for rendering and updating. 8 |

9 | 10 | ## Counter example 11 | 12 | ```typescript 13 | import React from "react"; 14 | import { 15 | consumer, 16 | UnPackReactContext, 17 | ReactiveProvider, 18 | } from "automatic-react"; 19 | 20 | export const context = React.createContext({ proxystate: { count: 0 } }); 21 | 22 | type IProxyState = { 23 | count: number; 24 | }; 25 | 26 | export class Demo extends React.Component<{}, { proxystate: IProxyState }> { 27 | state = { 28 | proxystate: { 29 | count: 1, 30 | }, 31 | }; 32 | 33 | render() { 34 | return ( 35 | 36 | 37 | 38 | ); 39 | } 40 | } 41 | 42 | @consumer(context) 43 | export class ReactiveCounter extends React.Component< 44 | UnPackReactContext 45 | > { 46 | render() { 47 | return ( 48 |
49 |
{this.props.proxystate!.count}
50 | 57 |
58 | ); 59 | } 60 | } 61 | ``` 62 | 63 | ## 简介 64 | 65 | - ReactiveProvider 66 |

67 | 你可以理解为‘ContextProvider’增加自动渲染功能的升级版。不同于以往的React.context,开发不仅需要传入 ‘数据’ 还需要传入 ‘修改数据’ 的方法, ‘ReactiveProvider’ 可以让你传入的数据,作为代理渲染对象,直接对 ‘数据’赋值,则会触发,所有该组件下,被‘@consumer’方法包含的组件去进行渲染更新。 68 |

69 | 70 | 71 | ## 计数器示例 72 | 73 | ```typescript 74 | import React from "react"; 75 | import { 76 | consumer, 77 | UnPackReactContext, 78 | ReactiveProvider, 79 | } from "automatic-react"; 80 | 81 | export const context = React.createContext({ proxystate: { count: 0 } }); 82 | 83 | type IProxyState = { 84 | count: number; 85 | }; 86 | 87 | export class Demo extends React.Component<{}, { proxystate: IProxyState }> { 88 | state = { 89 | proxystate: { 90 | count: 1, 91 | }, 92 | }; 93 | 94 | render() { 95 | return ( 96 | 97 | 98 | 99 | ); 100 | } 101 | } 102 | 103 | @consumer(context) 104 | export class ReactiveCounter extends React.Component< 105 | UnPackReactContext 106 | > { 107 | render() { 108 | return ( 109 |
110 |
{this.props.proxystate!.count}
111 | 118 |
119 | ); 120 | } 121 | } 122 | ``` -------------------------------------------------------------------------------- /src/util/proxy.ts: -------------------------------------------------------------------------------- 1 | import 'reflect-metadata'; 2 | import { ReactiveProxy } from './reactiveproxy'; 3 | 4 | export function ProxyState(isproxy = true) { 5 | return function(this: any, target: any, prop: string | number | symbol) { 6 | const list: any[] = Reflect.getMetadata('$$renderstate', target); 7 | if (!list) { 8 | Reflect.defineMetadata('$$renderstate', [{ key: prop, isproxy: isproxy }], target); 9 | } else { 10 | list.push({ key: prop, isproxy: isproxy }); 11 | } 12 | }; 13 | } 14 | 15 | export function ProxyComponent() { 16 | return function(target: any) { 17 | return class extends target { 18 | constructor(...args: any[]) { 19 | super(...args); 20 | const keys: any[] = Reflect.getMetadata('$$renderstate', this); 21 | if (keys) { 22 | keys.forEach(p => { 23 | let origin_object = Reflect.get(this, p.key); 24 | const base_object = {}; 25 | Reflect.set(base_object, p.key, origin_object); 26 | this.state = Object.assign(base_object, this.state); 27 | /** 处理单值必须增加伪引用层 */ 28 | Reflect.deleteProperty(this, p.key); 29 | Object.defineProperty(this, p.key, { 30 | enumerable: true, 31 | configurable: true, 32 | get: function() { 33 | if (p.isproxy) { 34 | if (Object.keys(origin_object).includes('$$issingle') && origin_object.$$issingle === true) { 35 | return origin_object[`single_${p.key}`]; 36 | } else { 37 | const base_object = {}; 38 | Reflect.set(base_object, p.key, { ...origin_object }); 39 | const reactiveobject = ReactiveProxy(origin_object, (_value, _prop) => { 40 | const proxystate = {}; 41 | Reflect.set(proxystate, p.key, { ...origin_object }); 42 | this.setState(proxystate); 43 | }); 44 | return reactiveobject; 45 | } 46 | } else { 47 | return origin_object; 48 | } 49 | }, 50 | set: (value: any) => { 51 | if (p.isproxy) { 52 | if (typeof value !== 'object') { 53 | if (typeof origin_object !== 'object') { 54 | const inderit_object = {}; 55 | inderit_object[`single_${p.key}`] = value; 56 | inderit_object[`$$issingle`] = true; 57 | const reactiveobject = ReactiveProxy(inderit_object, val => { 58 | const temp = {}; 59 | Reflect.set(temp, p.key, val); 60 | this.setState(temp); 61 | }); 62 | Reflect.defineMetadata(`$$single_${p.key}`, reactiveobject, this); 63 | origin_object = reactiveobject; 64 | } else { 65 | origin_object[`single_${p.key}`] = value; 66 | } 67 | } else { 68 | origin_object = value; 69 | if (this.state[p.key] !== value) { 70 | const temp = {}; 71 | Reflect.set(temp, p.key, value); 72 | this.setState(temp); 73 | } 74 | } 75 | } else { 76 | origin_object = value; 77 | } 78 | }, 79 | }); 80 | this[p.key] = origin_object; 81 | }); 82 | } 83 | } 84 | } as any; 85 | }; 86 | } 87 | -------------------------------------------------------------------------------- /md/origincontext.md: -------------------------------------------------------------------------------- 1 | # HocClassComponent ContextProvider && Decorator consumer && type UnPackReactContext 2 | 3 | ## introduction 4 | 5 | - ContextProvider 6 |

7 | Using 'contextprovider' hocclasscomponent, you can treat react.context.provider equally. It needs to input a 'react context' you created at prop 'context' on the component,And declare the initialization data and input it to the initialidata property on the hoc component. 8 |

9 | 10 | - @consumer 11 |

12 | After react 16.1 +, you can use context.consumer to inject data or methods on your component. But writing experience is bad for developers. Developers can simply decorate their components with @consumer, and quickly inject content into the components they need. 13 |

14 | 15 | ## Counter example 16 | 17 | ```typescript 18 | import React, { useState } from "react"; 19 | import { ContextProvider, consumer, UnPackReactContext } from "automatic-react"; 20 | 21 | export const context = React.createContext({ count: 0, addcount: () => {} }); 22 | 23 | export const Demo: React.FC = () => { 24 | const [count, setCount] = useState(1); 25 | 26 | return ( 27 | { 32 | setCount(count + 1); 33 | }, 34 | }} 35 | > 36 | 37 | 38 | 39 | ); 40 | }; 41 | 42 | @consumer(context) 43 | export class ContextCounter extends React.Component< 44 | UnPackReactContext 45 | > { 46 | render() { 47 | return ( 48 |
49 |
{this.props.count}
50 | 57 |
58 | ); 59 | } 60 | } 61 | 62 | export const ContextCounterFC: React.FC> = consumer(context)((props) => { 65 | return ( 66 |
67 |
{props.count}
68 | 75 |
76 | ); 77 | }); 78 | ``` 79 | 80 | ## 简介 81 | 82 | - ContextProvider 83 |

84 | 使用 ‘ContextProvider’ HocClassComponent 你可以把React.Context.Provider同等来看待,它需要传入一个你创建好的 'context', 85 | 并且声明好初始化数据,传入给HOC组件上的 initialidata 属性。 86 |

87 | 88 | - @consumer 89 | 90 |

91 | 在 React 16.1+ 后,你可以使用Context.Consumer去注入你的context上的数据 或方法。但是书写形式给开发者体验很差,利用 ‘@consumer’,开发者可以很简单的装饰自己的组件,将内容快速注入自己需要的业务组件内部。 92 |

93 | 94 | - UnPackReactContext 95 |

96 | 利用该 ‘UnPackReactContext’ 类型,开发者可以快速在typescript react app的 组件上,声明自己组件注入的 context 的 成员类型。 97 |

98 | 99 | ## 计数器示例 100 | 101 | ```typescript 102 | import React, { useState } from "react"; 103 | import { ContextProvider, consumer, UnPackReactContext } from "automatic-react"; 104 | 105 | export const context = React.createContext({ count: 0, addcount: () => {} }); 106 | 107 | export const Demo: React.FC = () => { 108 | const [count, setCount] = useState(1); 109 | 110 | return ( 111 | { 116 | setCount(count + 1); 117 | }, 118 | }} 119 | > 120 | 121 | 122 | 123 | ); 124 | }; 125 | 126 | @consumer(context) 127 | export class ContextCounter extends React.Component< 128 | UnPackReactContext 129 | > { 130 | render() { 131 | return ( 132 |
133 |
{this.props.count}
134 | 141 |
142 | ); 143 | } 144 | } 145 | 146 | export const ContextCounterFC: React.FC> = consumer(context)((props) => { 149 | return ( 150 |
151 |
{props.count}
152 | 159 |
160 | ); 161 | }); 162 | ``` 163 | -------------------------------------------------------------------------------- /md/proxy.md: -------------------------------------------------------------------------------- 1 | # ProxyState && ProxyComponen 2 | 3 | ## introduction 4 | 5 | @ProxyComponent 6 | 7 | ``` 8 | The reactclasscomponent decorated by the @ proxycomponent decorator will automatically check whether there are proxy members on @ proxystate on all class members 9 | 10 | At the same time, after constructing the common react constructor method, all class members with the same name will be assigned to react state. Use as raw value. Class members 11 | 12 | The proxy object will be converted to the proxy object, and the assignment of the proxy object will trigger the rendering of the assignment of the member with the same name on the corresponding state. 13 | ``` 14 | 15 | - @ProxyState 16 | 17 | ``` 18 | The reactclasscomponentproperties decorated by the '@ proxystate' decorator will automatically change to {key: string, isproxy: Boolean} object 19 | 20 | On the '$$renderstate' key of metadata of the prototype of the class. Form an array of the object. In this way, the array is batched when the proxy constructor is used. 21 | ``` 22 | 23 | 24 | ## Counter example 25 | 26 | ```typescript 27 | import React from "react"; 28 | import { ProxyComponent } from "automatic-react"; 29 | 30 | type IProxyState = { 31 | count: number; 32 | }; 33 | 34 | @ProxyComponent() 35 | export class ProxyCounter extends React.Component< 36 | {}, 37 | { proxystate: IProxyState } 38 | > { 39 | constructor(props: Readonly<{}>) { 40 | super(props); 41 | } 42 | 43 | @ProxyState() 44 | proxystate: IProxyState = { 45 | count: 0, 46 | }; 47 | 48 | render() { 49 | return ( 50 |
51 |
Own component is valid
52 |
{this.state.proxystate.count}
53 | 61 | 62 |
63 | ); 64 | } 65 | } 66 | 67 | export const ProxyCounterChild: React.FC<{ proxyprop: IProxyState }> = ( 68 | prop 69 | ) => { 70 | return ( 71 |
72 |
Child component is valid
73 |
{prop.proxyprop.count}
74 | 82 |
83 | ); 84 | }; 85 | ``` 86 | 87 | ## 简介 88 | 89 | - @ProxyComponent 90 | 91 | ``` 92 | 被‘@ProxyComponent’装饰器修饰过的 ReactClassComponent 将会自动检查所有的类成员上是否有 ‘@ProxyState’ 上的代理成员 93 | 同时 在构造完普通的React Constructor 方法后,会将所有 同名类成员赋值给 React State 上。作为原始值来去使用。 而类成员则 94 | 会转化为Proxy的代理对象,对代理对象的赋值则会去触发对应State上 同名成员的赋值渲染。 95 | ``` 96 | 97 | - @ProxyState 98 | 99 | ``` 100 | 被 ‘@ProxyState’ 装饰器修饰过的 ReactClassComponentProperties 会自动转为 {key: string, isproxy:boolean} 的对象存在 101 | 该Class 的 prototype 的 metadata 的 ‘$$renderstate’ key 上。形成一个该对象的数组。从而在代理构造函数时,对该数组做批处理。 102 | ``` 103 | 104 | ## 计数器 Demo 105 | 106 | ```typescript 107 | import React from "react"; 108 | import { ProxyComponent } from "../../util/index"; 109 | 110 | type IProxyState = { 111 | count: number; 112 | }; 113 | 114 | @ProxyComponent() 115 | export class ProxyCounter extends React.Component< 116 | {}, 117 | { proxystate: IProxyState } 118 | > { 119 | constructor(props: Readonly<{}>) { 120 | super(props); 121 | } 122 | 123 | @ProxyState() 124 | proxystate: IProxyState = { 125 | count: 0, 126 | }; 127 | 128 | render() { 129 | return ( 130 |
131 |
Own component is valid
132 |
{this.state.proxystate.count}
133 | 141 | 142 |
143 | ); 144 | } 145 | } 146 | 147 | export const ProxyCounterChild: React.FC<{ proxyprop: IProxyState }> = ( 148 | prop 149 | ) => { 150 | return ( 151 |
152 |
Child component is valid
153 |
{prop.proxyprop.count}
154 | 162 |
163 | ); 164 | }; 165 | ``` -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # automatic-react 2 | 3 | ## introduction 4 | 5 | A set of decorators can transform your react | react hooks | react context app convert into a reative app, 6 | Development mode similar to Vue | Vue composition | vuex 7 | 8 | ## 简介 9 | 10 | 一组装饰器可以将你的 react | react-hooks | react-context 应用 改造为 响应式应用, 11 | 类似 vue | vue-composition | vuex 的开发模式 12 | 13 | ## Export Member(导出成员) 14 | 15 | - automatic-react -> 16 | Remove react setstate as the render operation, and directly modify the properties on proxystate to trigger rendering directly 17 | (将react setState 作为render的操作移除,转而直接修改 proxystate上的属性直接触发渲染。) 18 | 19 | - [decorator @ProxyState && @ProxyComponent](https://github.com/zhusjfaker/React-Reactive-Proxy-State/wiki/ProxyState-&&-ProxyComponent) 20 | - [function rxhook](https://github.com/zhusjfaker/automatic-react/wiki/function-rxhook) 21 | - [HocClassComponent ContextProvider && Decorator consumer && type UnPackReactContext](https://github.com/zhusjfaker/automatic-react/wiki/HocClassComponent-ContextProvider-&&-Decorator-consumer-&&-type-UnPackReactContext) 22 | - [HocClassComponent ReactiveProvider](https://github.com/zhusjfaker/automatic-react/wiki/HocClassComponent-ReactiveProvider) 23 | 24 | ## Counter example 25 | 26 | ```typescript 27 | import React, { useEffect } from 'react' 28 | import { rxhook } from 'automatic-react'; 29 | 30 | 31 | export const ProxyCounter: React.FC = _props => { 32 | 33 | const state = rxhook({ count: 123, double: 0 }); 34 | 35 | useEffect(() => { 36 | state.double = state.count * 2 37 | }, [state.count]); 38 | 39 | return ( 40 |
41 |
{state.count}
42 |
{state.double}
43 | 50 |
51 | ) 52 | } 53 | ``` 54 | 55 | ```typescript 56 | import React from "react"; 57 | import { ProxyComponent } from "automatic-react"; 58 | 59 | type IProxyState = { 60 | count: number; 61 | }; 62 | 63 | @ProxyComponent() 64 | export class ProxyCounter extends React.Component< 65 | {}, 66 | { proxystate: IProxyState } 67 | > { 68 | constructor(props: Readonly<{}>) { 69 | super(props); 70 | } 71 | 72 | @ProxyState() 73 | proxystate: IProxyState = { 74 | count: 0, 75 | }; 76 | 77 | render() { 78 | return ( 79 |
80 |
Own component is valid
81 |
{this.state.proxystate.count}
82 | 90 | 91 |
92 | ); 93 | } 94 | } 95 | ``` 96 | 97 | ```typescript 98 | import React from "react"; 99 | import { 100 | consumer, 101 | UnPackReactContext, 102 | ReactiveProvider, 103 | } from "automatic-react"; 104 | 105 | export const context = React.createContext({ proxystate: { count: 0 } }); 106 | 107 | type IProxyState = { 108 | count: number; 109 | }; 110 | 111 | export class Demo extends React.Component<{}, { proxystate: IProxyState }> { 112 | state = { 113 | proxystate: { 114 | count: 1, 115 | }, 116 | }; 117 | 118 | render() { 119 | return ( 120 | 121 | 122 | 123 | ); 124 | } 125 | } 126 | 127 | @consumer(context) 128 | export class ReactiveCounter extends React.Component< 129 | UnPackReactContext 130 | > { 131 | render() { 132 | return ( 133 |
134 |
{this.props.proxystate!.count}
135 | 142 |
143 | ); 144 | } 145 | } 146 | ``` 147 | 148 | ## ContactInformation 149 | * Email 439453290@qq.com 150 | * Email zhushijie.jayson@bytedance.com 151 | 152 | ## WorkTogether 153 |

154 | The development of the project is relatively fast, and there may be many areas to be refined. If you like Vue, but at the same time you have to write react. If you like this' lightweight 'solution, you can contact me to improve' automatic react '. Contact address please see the email address in "contact information" above 155 |

156 |

157 | 项目开发的比较快,可能还有很多的地方需要细化。如果喜欢Vue,但同时又必须要写React的小伙伴,喜欢这个比较‘轻量级’的解决方案,可以联系我,共同把 ‘automatic-react’ 进行完善。联系地址请看上方的‘联系方式’中的邮箱地址 158 |

159 | 160 | 161 | 162 | 163 | 164 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "automatic-react", 3 | "version": "0.0.17", 4 | "description": "make your react app into reactive mode", 5 | "main": "lib/index.js", 6 | "types": "lib/types/util/index", 7 | "author": { 8 | "email": "439453290@qq.com", 9 | "name": "zhusj", 10 | "url": "https://github.com/zhusjfaker" 11 | }, 12 | "repository": { 13 | "type": "git", 14 | "url": "https://github.com/zhusjfaker/automatic-react.git" 15 | }, 16 | "bugs": { 17 | "url": "https://github.com/zhusjfaker/automatic-react/issues", 18 | "email": "439453290@qq.com" 19 | }, 20 | "license": "MIT", 21 | "engines": { 22 | "node": ">=8.9.0" 23 | }, 24 | "scripts": { 25 | "build:html": "rm -rf lib && NODE_ENV=production webpack --config build/webpack.config.js --type component && tsc && rm -rf ./temp", 26 | "build": "rm -rf lib && tsc && cp ./temp/util/* ./lib && rm -rf ./temp", 27 | "start": "NODE_ENV=development webpack-dev-server --host 127.0.0.1 --port 8000 --hot --config build/webpack.config.js --type page" 28 | }, 29 | "dependencies": { 30 | "react": "^16.8.6", 31 | "react-dom": "^16.8.6", 32 | "reflect-metadata": "^0.1.13" 33 | }, 34 | "devDependencies": { 35 | "lodash": "^4.17.11", 36 | "react-app-polyfill": "^1.0.1", 37 | "react-dev-utils": "^9.0.1", 38 | "resolve": "1.10.0", 39 | "react-router-dom": "^5.0.0", 40 | "@babel/core": "7.4.3", 41 | "@babel/plugin-proposal-class-properties": "^7.3.0", 42 | "@babel/plugin-proposal-decorators": "^7.8.3", 43 | "@babel/plugin-transform-runtime": "^7.4.4", 44 | "@babel/preset-env": "^7.4.5", 45 | "@babel/preset-react": "^7.0.0", 46 | "@babel/preset-typescript": "^7.3.3", 47 | "@babel/runtime": "^7.4.5", 48 | "@types/node": "^10.12.18", 49 | "@types/react": "^16.0.11", 50 | "@types/react-dom": "^16.0.11", 51 | "@types/webpack-env": "^1.13.6", 52 | "@typescript-eslint/eslint-plugin": "1.6.0", 53 | "@typescript-eslint/parser": "1.6.0", 54 | "autoprefixer": "^9.4.6", 55 | "autoprefixer-core": "^6.0.1", 56 | "babel-loader": "^8.0.5", 57 | "babel-plugin-named-asset-import": "^0.3.2", 58 | "babel-plugin-transform-class-properties": "^6.24.1", 59 | "babel-preset-mobx": "^2.0.0", 60 | "browserslist": "4.6.3", 61 | "camelcase": "^5.2.0", 62 | "caniuse-lite": "1.0.30000974", 63 | "case-sensitive-paths-webpack-plugin": "2.2.0", 64 | "css-hot-loader": "^1.4.4", 65 | "css-loader": "^1.0.1", 66 | "dotenv": "6.2.0", 67 | "dotenv-expand": "4.2.0", 68 | "eslint": "^5.16.0", 69 | "eslint-config-react-app": "^4.0.1", 70 | "eslint-loader": "2.1.2", 71 | "eslint-plugin-flowtype": "2.50.1", 72 | "eslint-plugin-import": "2.16.0", 73 | "eslint-plugin-jsx-a11y": "6.2.1", 74 | "eslint-plugin-react": "7.12.4", 75 | "eslint-plugin-react-hooks": "^1.5.0", 76 | "extract-text-webpack-plugin": "^3.0.2", 77 | "file-loader": "3.0.1", 78 | "fs-extra": "7.0.1", 79 | "html-webpack-plugin": "4.0.0-beta.5", 80 | "identity-obj-proxy": "3.0.0", 81 | "is-wsl": "^1.1.0", 82 | "mini-css-extract-plugin": "^0.7.0", 83 | "node-sass": "^4.12.0", 84 | "optimize-css-assets-webpack-plugin": "5.0.1", 85 | "pnp-webpack-plugin": "1.2.1", 86 | "postcss-flexbugs-fixes": "4.1.0", 87 | "postcss-loader": "3.0.0", 88 | "postcss-normalize": "7.0.1", 89 | "postcss-preset-env": "6.6.0", 90 | "postcss-safe-parser": "4.0.1", 91 | "resolve-url-loader": "^3.0.0", 92 | "sass-loader": "7.1.0", 93 | "semver": "6.0.0", 94 | "style-loader": "^0.23.1", 95 | "ts-pnp": "1.1.2", 96 | "tslib": "^1.9.0", 97 | "tslint": "^5.17.0", 98 | "tslint-config-egg": "^1.0.0", 99 | "tslint-config-prettier": "^1.18.0", 100 | "typescript": "3.4.5", 101 | "typings-for-css-modules-loader": "^1.7.0", 102 | "url-loader": "^1.1.2", 103 | "webpack": "4.29.6", 104 | "webpack-bundle-analyzer": "^3.3.2", 105 | "webpack-cli": "^3.3.4", 106 | "webpack-dev-server": "3.7.1", 107 | "webpack-merge": "^4.2.1", 108 | "webpack-node-externals": "^1.7.2" 109 | }, 110 | "browserslist": [ 111 | ">0.2%", 112 | "not dead", 113 | "not ie <= 11", 114 | "not op_mini all" 115 | ], 116 | "resolutions": { 117 | "browserslist": "4.6.3", 118 | "caniuse-lite": "1.0.30000974" 119 | }, 120 | "babel": { 121 | "presets": [ 122 | "@babel/preset-typescript", 123 | "@babel/preset-react", 124 | "@babel/env", 125 | "mobx" 126 | ], 127 | "plugins": [ 128 | [ 129 | "@babel/plugin-proposal-decorators", 130 | { 131 | "legacy": true 132 | } 133 | ], 134 | "transform-class-properties", 135 | [ 136 | "@babel/plugin-transform-runtime", 137 | { 138 | "absoluteRuntime": false, 139 | "corejs": false, 140 | "helpers": true, 141 | "regenerator": true, 142 | "useESModules": false 143 | } 144 | ] 145 | ] 146 | }, 147 | "files": [ 148 | "lib" 149 | ] 150 | } 151 | -------------------------------------------------------------------------------- /lib/context.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | Object.defineProperty(exports, "__esModule", { 4 | value: true 5 | }); 6 | exports.consumer = consumer; 7 | exports.ReactiveProvider = exports.ContextProvider = void 0; 8 | 9 | var tslib_1 = _interopRequireWildcard(require("tslib")); 10 | 11 | var _react = _interopRequireDefault(require("react")); 12 | 13 | var _proxy = require("./proxy"); 14 | 15 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 16 | 17 | function _getRequireWildcardCache() { if (typeof WeakMap !== "function") return null; var cache = new WeakMap(); _getRequireWildcardCache = function _getRequireWildcardCache() { return cache; }; return cache; } 18 | 19 | function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || _typeof(obj) !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; } 20 | 21 | function _instanceof(left, right) { if (right != null && typeof Symbol !== "undefined" && right[Symbol.hasInstance]) { return !!right[Symbol.hasInstance](left); } else { return left instanceof right; } } 22 | 23 | function _typeof(obj) { "@babel/helpers - typeof"; if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); } 24 | 25 | function _classCallCheck(instance, Constructor) { if (!_instanceof(instance, Constructor)) { throw new TypeError("Cannot call a class as a function"); } } 26 | 27 | function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } 28 | 29 | function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; } 30 | 31 | function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); } 32 | 33 | function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); } 34 | 35 | function _createSuper(Derived) { return function () { var Super = _getPrototypeOf(Derived), result; if (_isNativeReflectConstruct()) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; } 36 | 37 | function _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } return _assertThisInitialized(self); } 38 | 39 | function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; } 40 | 41 | function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Date.prototype.toString.call(Reflect.construct(Date, [], function () {})); return true; } catch (e) { return false; } } 42 | 43 | function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); } 44 | 45 | var ContextProvider = /*#__PURE__*/function (_React$Component) { 46 | _inherits(ContextProvider, _React$Component); 47 | 48 | var _super = _createSuper(ContextProvider); 49 | 50 | function ContextProvider(props) { 51 | _classCallCheck(this, ContextProvider); 52 | 53 | return _super.call(this, props); 54 | } 55 | 56 | _createClass(ContextProvider, [{ 57 | key: "render", 58 | value: function render() { 59 | var Providerlayout = this.props.context.Provider; 60 | return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement(Providerlayout, { 61 | value: this.props.initialidata 62 | }, this.props.children)); 63 | } 64 | }]); 65 | 66 | return ContextProvider; 67 | }(_react.default.Component); 68 | 69 | exports.ContextProvider = ContextProvider; 70 | 71 | var ReactiveProvider = /*#__PURE__*/function (_React$Component2) { 72 | _inherits(ReactiveProvider, _React$Component2); 73 | 74 | var _super2 = _createSuper(ReactiveProvider); 75 | 76 | function ReactiveProvider(props) { 77 | var _this; 78 | 79 | _classCallCheck(this, ReactiveProvider); 80 | 81 | _this = _super2.call(this, props); 82 | _this.store = Object.assign({}, _this.props.initialidata); 83 | return _this; 84 | } 85 | 86 | _createClass(ReactiveProvider, [{ 87 | key: "render", 88 | value: function render() { 89 | var Providerlayout = this.props.context.Provider; 90 | return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement(Providerlayout, { 91 | value: Object.assign({}, this.store) 92 | }, this.props.children)); 93 | } 94 | }]); 95 | 96 | return ReactiveProvider; 97 | }(_react.default.Component); 98 | 99 | exports.ReactiveProvider = ReactiveProvider; 100 | 101 | tslib_1.__decorate([(0, _proxy.ProxyState)(), tslib_1.__metadata("design:type", Object)], ReactiveProvider.prototype, "store", void 0); 102 | 103 | exports.ReactiveProvider = ReactiveProvider = tslib_1.__decorate([(0, _proxy.ProxyComponent)(), tslib_1.__metadata("design:paramtypes", [Object])], ReactiveProvider); 104 | 105 | function consumer(provider) { 106 | return function (target) { 107 | var serivce = provider; 108 | return function (props) { 109 | return /*#__PURE__*/_react.default.createElement(serivce.Consumer, null, function (value) { 110 | return _react.default.createElement(target, Object.assign({}, value, props)); 111 | }); 112 | }; 113 | }; 114 | } -------------------------------------------------------------------------------- /lib/proxy.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | Object.defineProperty(exports, "__esModule", { 4 | value: true 5 | }); 6 | exports.ProxyState = ProxyState; 7 | exports.ProxyComponent = ProxyComponent; 8 | 9 | require("reflect-metadata"); 10 | 11 | var _reactiveproxy = require("./reactiveproxy"); 12 | 13 | function _instanceof(left, right) { if (right != null && typeof Symbol !== "undefined" && right[Symbol.hasInstance]) { return !!right[Symbol.hasInstance](left); } else { return left instanceof right; } } 14 | 15 | function _typeof(obj) { "@babel/helpers - typeof"; if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); } 16 | 17 | function _classCallCheck(instance, Constructor) { if (!_instanceof(instance, Constructor)) { throw new TypeError("Cannot call a class as a function"); } } 18 | 19 | function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); } 20 | 21 | function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); } 22 | 23 | function _createSuper(Derived) { return function () { var Super = _getPrototypeOf(Derived), result; if (_isNativeReflectConstruct()) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; } 24 | 25 | function _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } return _assertThisInitialized(self); } 26 | 27 | function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; } 28 | 29 | function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Date.prototype.toString.call(Reflect.construct(Date, [], function () {})); return true; } catch (e) { return false; } } 30 | 31 | function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); } 32 | 33 | function ProxyState() { 34 | var isproxy = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true; 35 | return function (target, prop) { 36 | var list = Reflect.getMetadata('$$renderstate', target); 37 | 38 | if (!list) { 39 | Reflect.defineMetadata('$$renderstate', [{ 40 | key: prop, 41 | isproxy: isproxy 42 | }], target); 43 | } else { 44 | list.push({ 45 | key: prop, 46 | isproxy: isproxy 47 | }); 48 | } 49 | }; 50 | } 51 | 52 | function ProxyComponent() { 53 | return function (target) { 54 | return /*#__PURE__*/function (_target) { 55 | _inherits(_class, _target); 56 | 57 | var _super = _createSuper(_class); 58 | 59 | function _class() { 60 | var _this; 61 | 62 | _classCallCheck(this, _class); 63 | 64 | for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { 65 | args[_key] = arguments[_key]; 66 | } 67 | 68 | _this = _super.call.apply(_super, [this].concat(args)); 69 | var keys = Reflect.getMetadata('$$renderstate', _assertThisInitialized(_this)); 70 | 71 | if (keys) { 72 | keys.forEach(function (p) { 73 | var origin_object = Reflect.get(_assertThisInitialized(_this), p.key); 74 | var base_object = {}; 75 | Reflect.set(base_object, p.key, origin_object); 76 | _this.state = Object.assign(base_object, _this.state); 77 | /** 处理单值必须增加伪引用层 */ 78 | 79 | Reflect.deleteProperty(_assertThisInitialized(_this), p.key); 80 | Object.defineProperty(_assertThisInitialized(_this), p.key, { 81 | enumerable: true, 82 | configurable: true, 83 | get: function get() { 84 | var _this2 = this; 85 | 86 | if (p.isproxy) { 87 | if (Object.keys(origin_object).includes('$$issingle') && origin_object.$$issingle === true) { 88 | return origin_object["single_".concat(p.key)]; 89 | } else { 90 | var _base_object = {}; 91 | Reflect.set(_base_object, p.key, { ...origin_object 92 | }); 93 | var reactiveobject = (0, _reactiveproxy.ReactiveProxy)(origin_object, function (_value, _prop) { 94 | var proxystate = {}; 95 | Reflect.set(proxystate, p.key, { ...origin_object 96 | }); 97 | 98 | _this2.setState(proxystate); 99 | }); 100 | return reactiveobject; 101 | } 102 | } else { 103 | return origin_object; 104 | } 105 | }, 106 | set: function set(value) { 107 | if (p.isproxy) { 108 | if (_typeof(value) !== 'object') { 109 | if (_typeof(origin_object) !== 'object') { 110 | var inderit_object = {}; 111 | inderit_object["single_".concat(p.key)] = value; 112 | inderit_object["$$issingle"] = true; 113 | var reactiveobject = (0, _reactiveproxy.ReactiveProxy)(inderit_object, function (val) { 114 | var temp = {}; 115 | Reflect.set(temp, p.key, val); 116 | 117 | _this.setState(temp); 118 | }); 119 | Reflect.defineMetadata("$$single_".concat(p.key), reactiveobject, _assertThisInitialized(_this)); 120 | origin_object = reactiveobject; 121 | } else { 122 | origin_object["single_".concat(p.key)] = value; 123 | } 124 | } else { 125 | origin_object = value; 126 | 127 | if (_this.state[p.key] !== value) { 128 | var temp = {}; 129 | Reflect.set(temp, p.key, value); 130 | 131 | _this.setState(temp); 132 | } 133 | } 134 | } else { 135 | origin_object = value; 136 | } 137 | } 138 | }); 139 | _this[p.key] = origin_object; 140 | }); 141 | } 142 | 143 | return _this; 144 | } 145 | 146 | return _class; 147 | }(target); 148 | }; 149 | } --------------------------------------------------------------------------------