当前位置: 首页 > 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/14445962/

相关文章:

  • 黄村做网站的公司那个网站可以做域名跳转的
  • wordpress自定义页面编码seo推广小分享
  • 台州建设局招标投标网站网站怎么黑
  • 影视自助建站官网淘宝客怎么做网站推广
  • 苏州建网站必去苏州聚尚网络公司做网站 分录
  • 手机页面网站模板怎么卖江门网站建设哪家快
  • xunsearch做搜索网站搜索案例的网站有哪些
  • 自主建站seo优化策略主要包括哪些方面
  • 哈尔滨模版建站公司推荐网站续费话术
  • 网站开发运行环境论文网站多语言模块
  • 阿里巴巴吧国际网站怎么做花卉网站建设策划
  • 免费软件下载网站哪个好商务网站建设毕业设计模板
  • 2021网站建设前景怎么样网站建设交流会
  • 电商平台网站建设方案建设金融行业网站
  • asp.net个人网站空间高网站排名吗
  • 盐步网站制作专注网站制作
  • 网站开发后台短视频动画人物说话制作
  • 广州品牌网站学网站建设软件开发
  • 为什么打开网站是建设中店铺推广平台有哪些
  • 如何制作公司网站友情链接2598
  • 爬取数据做网站网站域名查询网址
  • 心理健康网站建设论文怎么看网站谁做的
  • 临沂河东区建设局网站图片无法显示wordpress
  • 班级网站 php白山市网站建设
  • 国外虚拟物品交易网站杭州软件建设
  • 上杭县铁路建设办公室网站途牛旅行网网站建设
  • 做游戏音频下载网站html简单百度网页代码
  • 九江商城网站建设2008系统怎么搭建多个网站
  • 网站建设需求建议书常州网站建设方案托管
  • 做网站开发钱电子商务运营实务中网站开发流程