当前位置: 首页 > news >正文

网站推广公司兴田德润在哪里关键词排名关键词快速排名

网站推广公司兴田德润在哪里,关键词排名关键词快速排名,网站网页怎么设计,新网站建设公司Redux 太繁琐,Mbox 很酷但我们可能没必要引入新的包,那就让我们亲自在 react.js 中通过代理实现一套钩子来达到类似 vue 的响应式状态: 实现 reactive hooks 代理类声明 代理状态的类应当提供可访问的状态,和订阅变化的接口。 …

Redux 太繁琐,Mbox 很酷但我们可能没必要引入新的包,那就让我们亲自在 react.js 中通过代理实现一套钩子来达到类似 vue 的响应式状态:

实现 reactive hooks

代理类声明

代理状态的类应当提供可访问的状态,和订阅变化的接口。

export type Listener<T> = (state: T) => any;export interface ReactiveCtxModel<T = any> {value: T;subscribe(listener: Listener<T>): () => void;
}

代理类实现

使用 es6 class 来实现代理类,es6 class 提供了属性的 get/set 访问器,让我们在通过 obj.key 的方式访问时不是直接访问,而是经过了代理,真实的值则通过 private 被设置为私有属性。

类的构造器,我们传入用 React.useState 获得的返回,没错,想在 react 中让页面响应数据的变化,我们仍然需要 useState,不传 setState 的话,这个 Reactive 将是惰性的,因为他无法触发页面的重渲染。

私有属性除了要保存的 state,还有 listeners 数组来保存监听变化要触发的函数,这些函数在 state 每次被 set 访问器调用时跟着调用。

export class Reactive<T = any> implements ReactiveCtxModel {private _state: T;private _setState: any = (newState: T) => {this._state = newState;};private _listeners: Listener<Readonly<T>>[] = [];constructor(state: T, setState?: any) {this._state = state;setState ? (this._setState = setState) : void 0;}get value(): T {return this._state;}set value(newState: T) {this._setState?.(newState);this._listeners.forEach((listener) => listener(newState));}subscribe(listener: Listener<T>) {this._listeners.push(listener);return () => {this._listeners = this._listeners.filter((l) => l !== listener);};}static isReactive(obj: any) {return Reactive.prototype.isPrototypeOf(obj);}
}

实现创建代理的钩子函数

每次在代码里手动创建 useState() 然后还要 new Reactive() 太麻烦了,我们将这几个操作封装成一个 hook Reactify,然后再赋给 reactive,这样我们就可以直接使用 reactive(initialValue) 创建响应式对象。(为什么要先创建 Reactify?因为 react 约定 react 的 use 钩子的顶部空间应当命名为 useXXX 或者是 大写字母 开头,因为我喜欢 reactive 这个名字,所以做了一个交换)

const Reactify = <T = any>(initialValue: T): Reactive<T> => {const [state, setState] = React.useState<T>(initialValue);const observer = new Reactive(state, setState);return observer;
};
/*** reactive is same with Reactify*/
export const reactive = Reactify;

example:

const Demo: React.FC = () => {let state = reactive(0);const num = state.value;return (<><ButtononClick={() => {state.value = state.value + 1;}}>{num}</Button></>);
};

实现监听函数

直接在 Reactive 对象上调用 subscribe 很棒,但有时候我更喜欢这个操作可以抽出来,于是有了下面这个 listen 函数,传入要监听的 Reactive 对象,接着在 then 中链式传入要触发的回调,观感上更优雅。

/*** When store.state changes, call the given function.* @param target listened Reactive store* @returns unlistener*/
export function listen<T = any>(target: Omit<Reactive<T>, "_state" | "_setState">) {return {then: (...fns: ((value: T) => any)[]) => {const fn = (value: T) => fns.forEach((f) => f(value));const dispose = target.subscribe(fn);return dispose;},};
}

example:

  listen(obj).then((newVal) => {console.log(`newVal: ${newVal}`);});

借助 Context 传递 Reactive

以上的 reactive 只能在单组件局部使用,即使通过 props 传递给子组件,子组件也只有只读的权利。如果需要跨组件共享 Reactive 代理,我们可以借助 React.Context:

创建默认 Context

import { createContext } from "react";
import { Listener, Reactive } from "./model";export const createReactiveContext = <T = any>(initialValue?: T) => {const reactiveObject = new Reactive(initialValue);return createContext<ReactiveCtxModel<T> | undefined>(reactiveObject as any);
};const ReactiveCtx = createReactiveContext();export default ReactiveCtx;

实现 useReactive 钩子

useReactive 可以接收一个初值,如果得到了初值就开辟一个新的 context 和 Reactive 对象,否则延用上一步创建的 ReactiveCtx。

/*** Accept a value and return a reactive object. When initalValue is valid a new reactive object will be created.*/
export const useReactive = <T = any>(initialValue?: T): Reactive<T> => {const [state, setState] = React.useState<T>(initialValue ?? (undefined as T));const reactiveObj = new Reactive(state, setState);const defaultContextModel = React.useContext((initialValue as any) ?? ReactiveCtx);if (initialValue !== undefined && initialValue !== null) {return reactiveObj as Reactive<T>;}return defaultContextModel as Reactive<T>;
};

实现 useReactiveContext 钩子

useReactive 接收初值后新建的 context 不能为其它组件获取,要让其它组件共享非默认的 context,我们就需要在外部额外创建并导出新的 context,并实现一个 useReactiveContext 钩子来接收新的context,这样就可以共享新的 context,同样如果没有传入新的 context,我们将沿用默认的 ReactiveCtx。

export const useReativeContext = <T = any>(context?: React.Context<ReactiveCtxModel<T> | undefined>): Reactive<T> => {const reactiveCtxModel = React.useContext(context || ReactiveCtx);return reactiveCtxModel as Reactive<T>;
};

现在,我们将原先 demo 中使用的 raective 替换为 useReactive,然后我们即可自由的跨组件共享 Reactive。
example:

const Demo: React.FC = () => {let state = useReactive(0);const num = state.value;listen(state).then((newVal) => {console(`newVal: ${newVal}`);});return (<><Button$click={() => {state.value = state.value + 1;}}>{num}</Button><ReactiveCtx.Provider value={state}><Kid /></ReactiveCtx.Provider></>);
};

Kid:

function Kid() {const state = useReactive<number>();return (<><Taglightstyle={{ cursor: "pointer" }}onClick={() => {state.value++;}}>state : {state.value}</Tag><Taglightstyle={{ cursor: "pointer" }}onClick={() => {state2.value++;}}>state2 : {state2.value}</Tag><context.Provider value={state2}><KidKid /></context.Provider></>);
}

Bingo! 到这里我们就基本实现了 reactive 啦,拜拜~

http://www.khdw.cn/news/33058.html

相关文章:

  • 个人简历免费模板石家庄百度seo排名
  • 微信app网站新乡seo优化
  • wordpress做公司网站app代理推广平台
  • 电子产品商务网站模板百度怎么创建自己的网站
  • 网站升级改版需要几天樱桃电视剧西瓜视频在线观看
  • 做网站需要交钱吗seo站长教程
  • html网站建设代码seo一般包括哪些内容
  • 在浏览器上建设网站搜索引擎优化的作用
  • 小说网站分页关键字怎么做短视频推广平台有哪些
  • 网站建设税收编码产品推广计划怎么写
  • 怎么自己做网站服务器linux信息流广告素材网站
  • 建站网站模板长春网络推广优化
  • 做网站商城靠谱360搜索引擎优化
  • 做网站图片失真seo排名软件怎么做
  • 网站开发人员任职资格seo关键词优化举例
  • 网站3级目录可以做导航分类么无限制搜索引擎排名
  • 苏州工业园区两学一做教育网站大数据营销案例分析
  • 手机的网站有哪些海外网站seo优化
  • 西安网站seo推广销售网络平台
  • 做的好的中医网站口碑营销的产品有哪些
  • 东莞外贸网站设计企业qq
  • 桂林北站客服咨询电话花钱推广的网络平台
  • 开发一个社交软件需要多少钱优化营商环境心得体会2023
  • 网站内页标题怎么填晋城今日头条新闻
  • wordpress备份整站新站seo快速排名 排名
  • h5网站开发流程环球网广东疫情最新消息
  • Linux做视频网站网速均衡便宜的seo官网优化
  • 网站建设 手机app百度app最新版本
  • 用dreamware做网站网络优化工程师工作内容
  • 做新闻源网站采集站赚钱做网销的一天都在干嘛