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

网站上那些轮播图视频怎么做的网站改版对排名的影响

网站上那些轮播图视频怎么做的,网站改版对排名的影响,北京电力建设公司现状,佛山外贸网站建设效果[React 进阶系列] useSyncExternalStore hook 前情提要#xff0c;包括 yup 的实现在这里#xff1a;yup 基础使用以及 jest 测试 简单的提一下#xff0c;需要实现的功能是#xff1a; yup schema 需要访问外部的 storage外部的 storage 是可变的React 内部也需要访问同…[React 进阶系列] useSyncExternalStore hook 前情提要包括 yup 的实现在这里yup 基础使用以及 jest 测试 简单的提一下需要实现的功能是 yup schema 需要访问外部的 storage外部的 storage 是可变的React 内部也需要访问同样的 storage 基于这几个前提条件再加上我们的项目已经从 React 17 升级到了 React 18因此就比较顺利的找到了一个新的 hookuseSyncExternalStore 这个新的 hook 可以监听到 React 外部 store——通常情况下可以是 local storage/session storage 这种——的变化随后在 React 组件内部去更新对应的状态 官方文档其实解释的比较清楚了使用 useSyncExternalStore 监听的 store 必须要实现以下两个功能 subscribe 其作用是一个 subscriber主要提供的功能在当变化被监听到时就会调用当前的 subscriber 我个人理解相比于传统的 Consumer/Subscriber 模式React 提供的这个 hook 是一个弱化的版本subscriber 的主要目的是为了提示 React 这里有一个状态变化所以很多情况下还是需要开发手动在 useEffect 中实现对应的功能 当然也是可以通过 event emitter 去出发 subscriber 的变化这点还需要研究一下怎么实现 getSnapshot 这个是会被返回的最新状态 这也是 useSyncExternalStore 必须的两个参数。另一参数是为初始状态为可选项 const snapshot useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot?)实现 store import { useSyncExternalStore } from react;export class PrerequisiteStore {private prerequisite: string | undefined;private listeners: Set() void new Set();private initListeners: Set() void new Set();private isInitialized false;subscribe(listener: () void) {this.listeners.add(listener);return () {this.listeners.delete(listener);};}getSnapshot() {return this.prerequisite;}setPrerequisite(prerequisite: string | undefined) {this.prerequisite prerequisite;this.isInitialized true;this.listeners.forEach((listener) listener());this.initListeners.forEach((listener) listener());this.initListeners.clear();}onInitialized(cb: () void) {if (this.isInitialized) {cb();} else {this.initListeners.add(cb);}} }const prerequisteStore new PrerequisiteStore();export const getPrerequisite () prerequisteStore.getSnapshot(); export const setPrerequisite (prerequisite: undefined | string) prerequisteStore.setPrerequisite(prerequisite);const subscribe (cb: () void) prerequisteStore.subscribe(cb); const getSnapshot () prerequisteStore.getSnapshot(); const getPrerequisiteSnapshot getSnapshot;export const onPrerequisiteStoreInitialized (cb: () void) prerequisteStore.onInitialized(cb);export const usePrerequisiteSyncStore () {return useSyncExternalStore(subscribe, getSnapshot, getPrerequisiteSnapshot); };这个实现方法是用 class……其主要原因是想要基于一个 singleton 实现这样全局访问 prerequisteStore 的时候只能访问这一个 store 不过同样的问题似乎也可以使用 object 来解决就像 React 官方文档实现的那样 // This is an example of a third-party store // that you might need to integrate with React.// If your app is fully built with React, // we recommend using React state instead.let nextId 0; let todos [{ id: nextId, text: Todo #1 }]; let listeners [];export const todosStore {addTodo() {todos [...todos, { id: nextId, text: Todo # nextId }];emitChange();},subscribe(listener) {listeners [...listeners, listener];return () {listeners listeners.filter((l) l ! listener);};},getSnapshot() {return todos;}, };function emitChange() {for (let listener of listeners) {listener();} }而且目前的实现实际上是无法自由绑定 listener 的所以之后可能会修改一下这部分而且还是需要花点时间琢磨一下 subscribe 这个功能怎么用 使用 store 错误实现 useEffect(() {setTimeout(() {setPrerequisite(A);initDemoSchema();}, 1000);setTimeout(() {setPrerequisite(C);}, 2000); }, []);useEffect(() {console.log(prerequisiteStore, new Date().toISOString());if (prerequisiteStore) {const res demoSchema.cast({});demoSchema.validate(res).then((res) console.log(res)).catch((e) {if (e instanceof ValidationError) {console.log(e.path, ,, e.message);}});} }, [prerequisiteStore]);这是 App.tsx 中的变化实现效果如下 这里可以看到有个问题那就是在 useEffect(() {}, [prerequisiteStore]) 获取变化的时候第一个 useEffect 没有获取更新的状态 修正 首先 store 的初始化在当前的版本不是非常的必须所以这里可以省略掉直接保留 subscribe 等即可……不过因为测试代码已经添加了的关系这里不会继续修改。主要就是修改一下 initDemoSchema: // 重命名 export const updateDemoSchema (prerequisite: string | undefined) {if (prerequisite) {demoSchema demoSchema.shape({enumField: string().required().default(prerequisite).oneOf(Object.keys(getTestEnum() || [])),});} };随后在 App.tsx 中更新 useEffect(() {setTimeout(() {setPrerequisite(A);}, 1000);setTimeout(() {setPrerequisite(C);}, 2000); }, []);useEffect(() {console.log(prerequisiteStore, new Date().toISOString());if (prerequisiteStore) {updateDemoSchema(prerequisiteStore);const res demoSchema.cast({});demoSchema.validate(res).then((res) console.log(res)).catch((e) {if (e instanceof ValidationError) {console.log(e.path, ,, e.message);}});} }, [prerequisiteStore]);这样就可以实现正常更新了 补充发现之前没有写 initDemoSchema之前旧的实现大致上没有特别大的区别不过 prerequisite 的方式是通过 getPrerequisite 获取的。但是我没注意到的是这只是一个 reference同时也没有绑定 subscribe因此这里返回的永远是最初值也就是在 initialized 后的值也就是 A 下一步 下一步想做的就是把 schema 的变化抽离出来并且尝试使用 todo 案例中的 emitChange这样 schema 的变化就不局限在 component 层级 虽然目前的业务情况来说1 个 schema 基本上只会被用在 1 个页面上不过还是想要将其剥离出来减少对 react 组建的依赖性而是直接想办法监听 store 的变化 测试代码 这个测试代码写的就比较含糊基本上就是测试了一下 subscriber 被调用了几次 相对而言比较复杂的实现功能还是得回到 yup schema 去做……这等到实际上有这个需求再说吧感觉那个写起来太痛苦了 import { PrerequisiteStore } from ../store/prerequisiteStore;describe(PrerequisiteStore, () {let store: PrerequisiteStore;beforeEach(() {store new PrerequisiteStore();});test(should subscribe and unsubscribe listeners, () {const listener jest.fn();const unsubscribe store.subscribe(listener);store.setPrerequisite(test);expect(listener).toHaveBeenCalledTimes(1);// 这里注意每个 subscribe 会返回的那个函数// 调用后就会 unsubscribe 当前行为unsubscribe();store.setPrerequisite(new test);expect(listener).toHaveBeenCalledTimes(1);});test(should return the current state with getSnapshot, () {expect(store.getSnapshot()).toBeUndefined();store.setPrerequisite(test);expect(store.getSnapshot()).toBe(test);});test(should notify listeners when state changes, () {const listener1 jest.fn();const listener2 jest.fn();store.subscribe(listener1);store.subscribe(listener2);store.setPrerequisite(test);expect(listener1).toHaveBeenCalledTimes(1);expect(listener2).toHaveBeenCalledTimes(1);});test(should handle initialization correctly, () {const initListener jest.fn();store.onInitialized(initListener);store.setPrerequisite(test);expect(initListener).toHaveBeenCalledTimes(1);const anotherInitListener jest.fn();store.onInitialized(anotherInitListener);expect(anotherInitListener).toHaveBeenCalledTimes(1);});test(should clear initListeners after initialization, () {const initListener jest.fn();store.onInitialized(initListener);store.setPrerequisite(test);expect(initListener).toHaveBeenCalledTimes(1);store.setPrerequisite(new test);expect(initListener).toHaveBeenCalledTimes(1);});test(should handle multiple initialization listeners correctly, () {const initListener1 jest.fn();const initListener2 jest.fn();store.onInitialized(initListener1);store.onInitialized(initListener2);store.setPrerequisite(test);expect(initListener1).toHaveBeenCalledTimes(1);expect(initListener2).toHaveBeenCalledTimes(1);}); });event emitter 这里新增一下 event emitter 的实现 class EventEmitter {private events: { [key: string]: SetFunction } {};on(event: string, listener: Function) {if (!this.events[event]) {this.events[event] new Set();}this.events[event].add(listener);}off(event: string, listener: Function) {if (!this.events[event]) return;this.events[event].delete(listener);}emit(event: string, ...args: any[]) {if (!this.events[event]) return;for (const listener of this.events[event]) {listener(...args);}} }const eventEmitter new EventEmitter(); export default eventEmitter;调用方法也很简单在 schema 中实现 eventEmitter.on(prerequisiteChange, updateDemoSchema);app 中更新代码如下 useEffect(() {console.log(Prerequisite Store changed:,prerequisiteStore,new Date().toISOString());if (prerequisiteStore) {const res demoSchema.cast({});demoSchema.validate(res).then((validatedRes) console.log(validatedRes)).catch((e: ValidationError) {console.log(Validation error:, e.path, e.message);});} }, [prerequisiteStore]);这样就可以有效的剥离 data schema 和 react component 之间的关系而是通过事件触发进行正常的更新 最后渲染结果如下 有的时候就不得不感叹 React 和 Angular 越到后面越有种……天下文章一大抄的感觉…… 比如说这是之前学习 Angular 的 EventEmitter 的使用 export class CockpitComponent {Output() serverCreated new EventEmitterOmitServerElement, type();Output() blueprintCreated new EventEmitterOmitServerElement, type();newServerName ;newServerContent ;onAddServer() {this.serverCreated.emit({name: this.newServerName,content: this.newServerContent,});}onAddBlueprint() {this.blueprintCreated.emit({name: this.newServerName,content: this.newServerContent,});} }学了一下 Angular 还真有助于理解 18 这个新 hook 的运用和延伸…… 我感觉下意识的选择 class 可能也是受到了一点 Angular 的影响……
http://www.hkea.cn/news/14536465/

相关文章:

  • 泰州建设网站网站设计psd
  • 四川建设网网站抖音排名优化
  • 台州建设局招标投标网站网页制作素材去哪找
  • 在线网站生成器网站建设岗位工作职责
  • 网站怎么做伪静态页面百度快照优化培训班
  • 保山市建设局网站登录免费软件下载平台
  • 单位网站建设费合同印花税wordpress分类目录最简化404
  • 兰州网站关键词优化西域数码网站建设
  • 如何取消网站备案网站怎么设置404页面
  • 黑龙江省机场建设集团官网网站哪里有营销型网站公司
  • 企业运营与发展形考作业答案网站seo诊断的主要内容
  • 招商加盟网站推广方案南阳网站营销外包
  • 自己的网站怎么做跳转网站开发简称
  • 加强网站建设管理办法网站后台管理系统的重要技术指标
  • 南京网站建设电话铁路网站建设
  • 心理健康网站建设论文网上的推广
  • 沐川移动网站建设石家庄网站模板建站
  • 网站跳转qq哪家建站公司好
  • 在linux上做网站搭建教育网站案例
  • 购物网站建立手机网页微信
  • 上海尚海整装官方网站网站建设服务哪个便宜啊
  • 余杭建设局网站微信小程序开发制作教程
  • wordpress站点目录晋江网络推广公司
  • 淘宝客网站做一种还是做好几种seo推广是什么
  • 大沥做网站东莞做网站seo优化
  • 江苏省 建设 注册中心网站首页域名收录查询
  • 网站建设价格表金融行业网站建设公司
  • 优秀企业网站的特点flash 网站欣赏
  • 微信上的小说网站是怎么做的佛山定制建站公司推荐
  • 游戏网站怎么做营销qq下载