关于react.js:TS泛型粗浅理解-一

在应用react-router-dom的时候,用到了useMatches的办法,ts始终提醒报错,如下: 依据提醒,找到了这个类型: export interface UIMatch<Data = unknown, Handle = unknown> { id: string; pathname: string; params: AgnosticRouteMatch["params"]; data: Data; handle: Handle;}import type {UIMatch} from "react-router-dom"这才对泛型有了一丢丢了解。应用时的场景: const location = useLocation() let matches = useMatches(); useEffect(() => { let match = matches.find((item: any) => item.pathname == location.pathname) if(match) { let arr = match?.handle?.breadcrumb.map((item: string) => { return { title: item } }) } }, [location.pathname])breadcrumb始终提醒报错发现matches的数据类型为UIMatch<unknown, unknown>所以报错 依据UIMatch的类型提醒,咱们发现Data和Handle的类型为unknown,所以这时候须要应用any进行强制类型转换, 代码如下: let matches = useMatches() as any;``或者将matches的类型申明:let matches:UIMatch<any, any>[] = useMatches() ...

March 1, 2024 · 1 min · jiezi

关于react.js:一个支持Sora模型文本生成视频的Web客户端

大家好,我是 Java陈序员。 最近 Open AI 又火了一把,其新推出的文本生成视频模型 —— Sora,引起了微小的关注。 Sora 目前仅仅只是公布预报视频,还未凋谢出具体的 API. 明天,给大家举荐一个最近非常炽热的开源我的项目,一个反对应用 Sora 模型将文本生成视频的 Web 客户端。 关注微信公众号:【Java陈序员】,获取开源我的项目分享、AI副业分享、超200本经典计算机电子书籍等。我的项目介绍SoraWebui —— 一个开源的我的项目,容许用户应用 OpenAI 的 Sora 模型应用文本在线生成视频,反对一键部署。 SoraWebui 我的项目创立不到两个礼拜,就斩获了 1000 多个 Star! 因为 OpenAI 还未凋谢 Sora 的 API,因而 SoraWebui 目前只是一个空壳框架。 期待后续 API 开发,即可疾速集成 Sora. 此外,SoraWebui 须要 FakeSoraAPI 服务提供的接口反对。 疾速开始SoraWebui1、克隆我的项目 git clone https://github.com/SoraWebui/SoraWebui.git2、装置依赖 cd SoraWebui && yarn#orcd SoraWebui && npm install#orcd SoraWebui && pnpm install3、批改配置文件复制 .env.example 并将其重命名为 .env.local # website URLNEXT_PUBLIC_SITE_URL=http://localhost# openai configOPENAI_API_KEY=sk-XXXXXXOPENAI_API_BASE_URL=http://localhost:8081OPENAI_API_MODEL=sora-1.0-turbo4、运行 ...

February 26, 2024 · 1 min · jiezi

关于react.js:当useEffect遇到函数依赖

上面的代码实现了一个繁难的登录性能(为了缩小代码量,去掉了明码)。 import React, { useState } from 'react';const api = { login(username) { console.log('username', username); },};function Login() { const [username, setUsername] = useState(''); const onSubmit = () => { if (!username) { alert('Please input username'); return; } api.login(username,); }; return ( <div> <h1>Login</h1> <input type="text" value={username} onChange={(e) => setUsername(e.target.value)} /> <button onClick={onSubmit}>submit</button> </div> );}export default Login;当初咱们要减少一个需要:监听页面上的回车事件,而后发动登录,代码如下: useEffect(() => { const onKeyup = (e) => { if (e.key === 'Enter') { onSubmit(); } } window.addEventListener('keyup', onKeyup);}, []);代码看起来没问题,但运行一下,咱们就会发现并没有依照预期倒退,在输入框曾经输出用户名的前提下,页面上还是会始终提醒让咱们输出用户名。 ...

February 24, 2024 · 2 min · jiezi

关于react.js:React-中父子组件的渲染与副作用执行顺序

原文地址--全栈小册:https://skillgroup.cn/framework/react/render-order.html在理论开发过程中,咱们常常会遇到父子组件的嵌套应用。这时,理解组件的渲染程序和副作用(Side Effects)的执行程序就显得尤为重要。本文将深入探讨这两个方面,并通过具体的案例来进行解释。 父子组件的渲染程序根本准则在 React 中,组件的渲染过程是从父组件开始的。当一个父组件被触发渲染时,它的所有子组件也会随之渲染。这个过程是递归的,也就是说,子组件的子组件也会被渲染,依此类推。 示例与剖析思考以下代码: const Parent = () => { console.log("Parent Render"); return ( <div> <Child /> </div> );};const Child = () => { console.log("Child Render"); return <div>Child</div>;};在这个例子中,当Parent组件被触发渲染时,控制台的输入程序会是: Parent RenderChild Render这表明父组件首先被渲染,而后是子组件。 函数组件与useEffect根本准则在函数组件中,useEffect是用于执行副作用的次要钩子。当波及到父子组件时,子组件的useEffect会在父组件的useEffect之前执行。 示例与剖析思考以下代码: const Parent = () => { useEffect(() => { console.log("Parent useEffect"); }, []); return ( <div> <Child /> </div> );};const Child = () => { useEffect(() => { console.log("Child useEffect"); }, []); return <div>Child</div>;};在这个例子中,控制台的输入程序会是: ...

September 22, 2023 · 1 min · jiezi

关于react.js:React-18生命周期

原文地址--全栈小册:https://skillgroup.cn/framework/react/life-cycle.htmlReact 生命周期流程图 React 生命周期线上地址 React.Component 构造函数1. 目标构造函数在 React 组件的生命周期中十分晚期被调用,它产生在组件实例被创立并插入到 DOM 之前。这使得它成为初始化组件的本地状态和绑定事件处理函数的现实地位。 2. 应用如果您的组件不须要初始化状态或绑定事件处理函数,那么您不须要显式地定义一个构造函数。然而,如果您的确这样做了,那么在构造函数的第一行调用super(props)是必要的。 3. 为什么要调用 super(props)?在 JavaScript 类中,子类的构造函数必须在应用this之前调用super。在 React 组件中,super援用的是React.Component的构造函数。调用super(props)确保您能够在构造函数中应用this.props。 4. 初始化状态构造函数是为this.state设置初始值的中央。这是通过间接为this.state调配一个对象来实现的。例如: this.state = { counter: 0 };请留神,您不应该在构造函数中调用setState()。 5. 绑定事件处理函数为了确保事件处理函数中的this援用的是组件实例,您须要在构造函数中绑定它。例如: this.handleClick = this.handleClick.bind(this);6. 防止的做法不要在构造函数中调用setState():这是因为this.state能够间接在构造函数中进行初始化。防止引入副作用或订阅:构造函数不是执行网络申请、设置订阅或手动更改 DOM 的中央。这些都应该在componentDidMount()或其余生命周期办法中进行。防止将 props 间接复制到 state:这是因为当 props 更改时,state 不会自动更新,可能导致组件的渲染状态与 props 不同步。7. 示例代码class MyComponent extends React.Component { constructor(props) { super(props); this.state = { counter: 0 }; this.handleClick = this.handleClick.bind(this); } handleClick() { // 事件处理逻辑 } // ...其余办法和渲染逻辑}8. 不应用构造函数的代替办法constructor在 React 组件中是能够省略的。然而,是否省略取决于您的组件须要执行哪些初始化操作。以下是一些状况阐明: ...

September 22, 2023 · 3 min · jiezi

关于react.js:react18arco网页聊天室react-hooks高仿微信聊天

一、我的项目介绍react18聊天我的项目ReactChat 基于vite4+react18+acro design+zustand等技术架构实现开发仿微信电脑端界面聊天实例。反对图文混排、图片/视频预览、红包/朋友圈等性能。 二、编码技术编辑器:vscode技术栈:react18+vite4+react-router-dom+zustand+sass组件库:@arco-design/web-react (字节跳动react组件库)状态治理:zustand^4.4.1路由治理:react-router-dom^6.15.0className拼合:clsx^2.0.0对话框组件:rdialog (基于react18 hooks自定义桌面端弹窗组件)滚动条组件:rscroll (基于react18 hooks自定义丑化滚动条)预处理款式:sass^1.66.1 三、我的项目构造目录 整个我的项目采纳react18 hooks标准编码开发页面。 react18自定义弹窗/滚动条组件我的项目中利用到的对话框及滚动条插件均是基于react18 hooks自定义组件实现成果。 // 引入弹窗组件import RDialog, { rdialog } from '@/components/rdialog'// 组件式调用<RDialog visible={confirmVisible} title="题目信息" content="对话框内容信息" closeable shadeClose={false} zIndex="2050" dragOut maxmin btns={[ {text: '勾销', click: () => setConfirmVisible(false)}, {text: '确定', click: handleInfo} ]} onClose={()=>setConfirmVisible(false)}/>// 函数式调用rdialog({ title: '题目信息', content: '对话框内容信息', closeable: true, shadeClose: false, zIndex: 2050, dragOut: true, maxmin: true, btns: [ {text: '勾销', click: rdialog.close()}, {text: '确定', click: handleInfo} ]})// 引入滚动条组件import RScroll from '@/components/rscroll'<RScroll autohide maxHeight={100}> 包裹须要滚动的内容块。。。</RScroll>main.jsx入口文件import React from 'react'import ReactDOM from 'react-dom/client'import App from './App.jsx'import '@arco-design/web-react/dist/css/arco.css'import './style.scss'ReactDOM.createRoot(document.getElementById('root')).render(<App />)App.jsx模板import { HashRouter } from 'react-router-dom'// 引入useRoutes集中式路由配置文件import Router from './router'function App() { return ( <> <HashRouter> <Router /> </HashRouter> </> )}export default App ...

September 12, 2023 · 4 min · jiezi

关于react.js:axiosjs解析后端返回的流文件

1.电脑系统 windows11专业版2.开发环境 react18+ant53.在开发的过程中,咱们会遇到后端返回流文件,前端应该怎么解析呢?上面我来分享一下办法: export const ExportApi = (data) => { return axios({ url: 'file/export', method: 'post', data, responseType: "blob", });}const exportApi = async (type) => { await ExportApi({ type }).catch(error => { exportFileApi(error, "数据汇总"); }); }/*导出文件办法 fileData : 当值是json格局的时候,示意接口失败,提醒 导出数据失败 当值不是 json格局的时候,示意导出胜利,fileName : 示意下载的文件名称 */export const exportFileApi = (fileData, fileName) => { if (fileData.type == "application/json") { message.error(fileData.message || "导出数据失败"); } else { let blob = new Blob([fileData], { type: "application/vnd.ms-excel" }); let objectUrl = (window.URL || window.webkitURL).createObjectURL(blob); let downFile = document.createElement("a"); downFile.style.display = "none"; downFile.href = objectUrl; downFile.download = fileName; document.body.appendChild(downFile); downFile.click(); document.body.removeChild(downFile); window.URL.revokeObjectURL(objectUrl); }}99.本期的分享到了这里就完结啦,心愿对你有所帮忙,让咱们一起致力走向巅峰。 ...

September 6, 2023 · 1 min · jiezi

关于react.js:React初始化渲染

初始化渲染的过程,咱们能够间接对应到React程序中ReactDOM.render函数调用后的后果。 1.环境筹备初始化我的项目:npx create-react-app simple-react删除一些代码,最要害的内容就是:src/index.jspublic/index.htmlpackage.json中的dependencies和scripts: 2.JSX介绍JSX是JavaScript的一种语法扩大。JSX到一般Javascript的代码的转化是通过babel实现的。 3.React.createElement编写DISABLE_NEW_JSX_TRANSFORM=true 禁用掉新的jsxdev转换,应用React.createElement 这个迷你的包(cross-env)可能提供一个设置环境变量的scripts,让你可能以unix形式设置环境变量,而后在windows上也能兼容运行。npm i cross-env -Dpackage.json "start": "cross-env DISABLE_NEW_JSX_TRANSFORM=true react-scripts start", react17之前通过Babel把jsx转换为虚构DOM<div> Hello Simple React </div>React.createElement("div", null, "Hello Simple React") react.js import { REACT_ELEMENT } from "./utils"function createElement(type, properties, children) { // debugger let ref = properties.ref || null let key = properties.key || null // 属性能够是可读的、可写的或可删除的。 // 属性能够是可枚举的(能够通过for…in循环枚举)或不可枚举的。 // 能够通过Object.defineProperty()等办法定义属性的个性。 ;['key', 'ref', '__self', '__source'].forEach(key => { delete properties[key] }) let props = { ...properties } //传参大于3 if (arguments.length > 3) { console.log(arguments) props.children = Array.prototype.slice.call(arguments, 2) } else { props.children = children } return { //$$--唯一性,jsx转换成为的类型 $$typeof: REACT_ELEMENT, type, ref,//操作DOM key,//diff比拟 props }}const React = { createElement}export default React4.ReactDOM.render函数编写初始化渲染第一步:实现函数React.createElement初始化渲染第二步:实现函数ReactDOM.render ...

September 5, 2023 · 2 min · jiezi

关于react.js:React-Hooks最佳实践

React自从16.8版本减少Hooks概念以来,其老版官网文档对于Hooks的解释是基于类组件来类比的,很容易让人感觉Hooks是不一样写法的类组件实现。目前React出了一份全新的官网文档,齐全基于Hooks与函数式组件来形容React机制,与之前的文档天壤之别,这就导致了很多老旧我的项目的Hooks代码是过期的,并不合乎其新文档的理念,这里将对Hooks最佳实际进行总结。 为什么须要HooksHooks公布之初React就在其老版官网文档介绍了动机,次要有如下几个起因。 很难在组件之间复用有状态的逻辑 对于之前的类组件,状态都是与组件绑定到一起的,能够对待成组件的公有属性。这样的话,波及到有状态逻辑在组件间重用就变得很艰难,类组件的解决办法为render props或者高阶组件。然而当你用到这两种模式的时候,你须要扭转你的组件构造,并且会带来很多不必要的组件嵌套,让调试变得艰难,代码的复杂程度也会晋升很多。而Hooks将状态齐全与组件抽来到来,是一个独立的货色,这样就可能让咱们封装一般函数一样封装有状态逻辑,并且能轻松的在不同组件中复用。 简单的类组件很难了解与保护 因为单向数据流与状态晋升的起因,咱们很容易遇到须要同时解决很多逻辑的巨型组件,这带来了很重大的耦合性,一个componentDidMount生命周期里可能会蕴含很多不相干的代码,并且一个1000行的组件保护起来也足够令人头疼。 类的学习老本很高 React组件分为两种,类组件与函数式组件,这两者的复杂度相差微小,类组件带来了相当多的模板代码与难以了解的this指向。在Hooks诞生之前,函数式组件是无状态的,应用场景十分受限,然而当有Hooks之后,咱们所有的组件都能够应用更简洁更容易了解的函数式组件。 老版文档对于Hooks应用引起的误导对于Hooks产生动机方面,老版文档解释的十分分明,然而对于Hooks如何应用,老版文档只具体说了useState,useEffect以及自定义Hooks,其中useEffect的应用很具备误导性,至于其余的Hooks只列了一个api列表简略的形容了一下各自的作用。 useState的应用根本没什么争议,咱们次要看useEffect。 import React, { useState, useEffect } from 'react';function Example() { const [count, setCount] = useState(0); // Similar to componentDidMount and componentDidUpdate: useEffect(() => { // Update the document title using the browser API document.title = `You clicked ${count} times`; }); return ( <div> <p>You clicked {count} times</p> <button onClick={() => setCount(count + 1)}> Click me </button> </div> );}留神其官网示例中对于useEffect的正文,相当于让开发者认为它是生命周期的平替,这在最新的React文档中恰好是谬误的做法。当然,可能思考到开发者刚开始从类组件转换到Hooks函数式组件须要一个参照或者一个最简略的上手示例,这样是最明了的表达方式。不过现如今新文档曾经公布,对于Hooks的解释十分清晰且深刻,这次咱们就专一于新文档重塑对于Hooks的认知。 ...

August 24, 2023 · 6 min · jiezi

关于react.js:antd的选择框如何增加tab选中

antd的抉择框默认是不容许tab选中的,如果有这种需要,那么须要批改源码。通过剖析,antd的抉择框应用的是rc-select,将node_modules里的rc-select/lib/OptionList.js和rc-select/es/OptionList.js里减少Tab即可。(留神:每次npm install,rc-select都会变动,须要从新笼罩,如果更新了antd版本,须要从新测试tab性能是否失常,防止因为其降级导致有效) /lib/OptionList.js "use strict";var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard");Object.defineProperty(exports, "__esModule", { value: true});exports.default = void 0;var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));var _objectWithoutProperties2 = _interopRequireDefault(require("@babel/runtime/helpers/objectWithoutProperties"));var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));var React = _interopRequireWildcard(require("react"));var _KeyCode = _interopRequireDefault(require("rc-util/lib/KeyCode"));var _omit = _interopRequireDefault(require("rc-util/lib/omit"));var _pickAttrs = _interopRequireDefault(require("rc-util/lib/pickAttrs"));var _useMemo = _interopRequireDefault(require("rc-util/lib/hooks/useMemo"));var _classnames = _interopRequireDefault(require("classnames"));var _rcVirtualList = _interopRequireDefault(require("rc-virtual-list"));var _TransBtn = _interopRequireDefault(require("./TransBtn"));var _platformUtil = require("./utils/platformUtil");var _useBaseProps2 = _interopRequireDefault(require("./hooks/useBaseProps"));var _SelectContext = _interopRequireDefault(require("./SelectContext"));var _excluded = ["disabled", "title", "children", "style", "className"];/** * Using virtual list of option display. * Will fallback to dom if use customize render. */var OptionList = function OptionList(_, ref) { var _useBaseProps = (0, _useBaseProps2.default)(), prefixCls = _useBaseProps.prefixCls, id = _useBaseProps.id, open = _useBaseProps.open, multiple = _useBaseProps.multiple, searchValue = _useBaseProps.searchValue, toggleOpen = _useBaseProps.toggleOpen, notFoundContent = _useBaseProps.notFoundContent, onPopupScroll = _useBaseProps.onPopupScroll; var _React$useContext = React.useContext(_SelectContext.default), flattenOptions = _React$useContext.flattenOptions, onActiveValue = _React$useContext.onActiveValue, defaultActiveFirstOption = _React$useContext.defaultActiveFirstOption, onSelect = _React$useContext.onSelect, menuItemSelectedIcon = _React$useContext.menuItemSelectedIcon, rawValues = _React$useContext.rawValues, fieldNames = _React$useContext.fieldNames, virtual = _React$useContext.virtual, listHeight = _React$useContext.listHeight, listItemHeight = _React$useContext.listItemHeight; var itemPrefixCls = "".concat(prefixCls, "-item"); var memoFlattenOptions = (0, _useMemo.default)(function () { return flattenOptions; }, [open, flattenOptions], function (prev, next) { return next[0] && prev[1] !== next[1]; }); // =========================== List =========================== var listRef = React.useRef(null); var onListMouseDown = function onListMouseDown(event) { event.preventDefault(); }; var scrollIntoView = function scrollIntoView(index) { if (listRef.current) { listRef.current.scrollTo({ index: index }); } }; // ========================== Active ========================== var getEnabledActiveIndex = function getEnabledActiveIndex(index) { var offset = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 1; var len = memoFlattenOptions.length; for (var i = 0; i < len; i += 1) { var current = (index + i * offset + len) % len; var _memoFlattenOptions$c = memoFlattenOptions[current], group = _memoFlattenOptions$c.group, data = _memoFlattenOptions$c.data; if (!group && !data.disabled) { return current; } } return -1; }; var _React$useState = React.useState(function () { return getEnabledActiveIndex(0); }), _React$useState2 = (0, _slicedToArray2.default)(_React$useState, 2), activeIndex = _React$useState2[0], setActiveIndex = _React$useState2[1]; var setActive = function setActive(index) { var fromKeyboard = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false; setActiveIndex(index); var info = { source: fromKeyboard ? 'keyboard' : 'mouse' }; // Trigger active event var flattenItem = memoFlattenOptions[index]; if (!flattenItem) { onActiveValue(null, -1, info); return; } onActiveValue(flattenItem.data.value, index, info); }; // Auto active first item when list length or searchValue changed (0, React.useEffect)(function () { setActive(defaultActiveFirstOption !== false ? getEnabledActiveIndex(0) : -1); }, [memoFlattenOptions.length, searchValue]); // Auto scroll to item position in single mode (0, React.useEffect)(function () { /** * React will skip `onChange` when component update. * `setActive` function will call root accessibility state update which makes re-render. * So we need to delay to let Input component trigger onChange first. */ var timeoutId = setTimeout(function () { if (!multiple && open && rawValues.size === 1) { var value = Array.from(rawValues)[0]; var index = memoFlattenOptions.findIndex(function (_ref) { var data = _ref.data; return data.value === value; }); if (index !== -1) { setActive(index); scrollIntoView(index); } } }); // Force trigger scrollbar visible when open if (open) { var _listRef$current; (_listRef$current = listRef.current) === null || _listRef$current === void 0 ? void 0 : _listRef$current.scrollTo(undefined); } return function () { return clearTimeout(timeoutId); }; }, [open, searchValue]); // ========================== Values ========================== var onSelectValue = function onSelectValue(value) { if (value !== undefined) { onSelect(value, { selected: !rawValues.has(value) }); } // Single mode should always close by select if (!multiple) { toggleOpen(false); } }; // ========================= Keyboard ========================= React.useImperativeHandle(ref, function () { return { onKeyDown: function onKeyDown(event) { var which = event.which, ctrlKey = event.ctrlKey; switch (which) { // >>> Arrow keys & ctrl + n/p on Mac case _KeyCode.default.N: case _KeyCode.default.P: case _KeyCode.default.UP: case _KeyCode.default.DOWN: { var offset = 0; if (which === _KeyCode.default.UP) { offset = -1; } else if (which === _KeyCode.default.DOWN) { offset = 1; } else if ((0, _platformUtil.isPlatformMac)() && ctrlKey) { if (which === _KeyCode.default.N) { offset = 1; } else if (which === _KeyCode.default.P) { offset = -1; } } if (offset !== 0) { var nextActiveIndex = getEnabledActiveIndex(activeIndex + offset, offset); scrollIntoView(nextActiveIndex); setActive(nextActiveIndex, true); } break; } // >>> Select case _KeyCode.default.TAB:增加tab键选中切换 { // value var item = memoFlattenOptions[activeIndex]; if (item && !item.data.disabled) { onSelectValue(item.data.value); } else { onSelectValue(undefined); } break; } case _KeyCode.default.ENTER: { // value var item = memoFlattenOptions[activeIndex]; if (item && !item.data.disabled) { onSelectValue(item.data.value); } else { onSelectValue(undefined); } if (open) { event.preventDefault(); } break; } // >>> Close case _KeyCode.default.ESC: { toggleOpen(false); if (open) { event.stopPropagation(); } } } }, onKeyUp: function onKeyUp() {}, scrollTo: function scrollTo(index) { scrollIntoView(index); } }; }); // ========================== Render ========================== if (memoFlattenOptions.length === 0) { return /*#__PURE__*/React.createElement("div", { role: "listbox", id: "".concat(id, "_list"), className: "".concat(itemPrefixCls, "-empty"), onMouseDown: onListMouseDown }, notFoundContent); } var omitFieldNameList = Object.keys(fieldNames).map(function (key) { return fieldNames[key]; }); var getLabel = function getLabel(item) { return item.label; }; var renderItem = function renderItem(index) { var item = memoFlattenOptions[index]; if (!item) return null; var itemData = item.data || {}; var value = itemData.value; var group = item.group; var attrs = (0, _pickAttrs.default)(itemData, true); var mergedLabel = getLabel(item); return item ? /*#__PURE__*/React.createElement("div", (0, _extends2.default)({ "aria-label": typeof mergedLabel === 'string' && !group ? mergedLabel : null }, attrs, { key: index, role: group ? 'presentation' : 'option', id: "".concat(id, "_list_").concat(index), "aria-selected": rawValues.has(value) }), value) : null; }; return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("div", { role: "listbox", id: "".concat(id, "_list"), style: { height: 0, width: 0, overflow: 'hidden' } }, renderItem(activeIndex - 1), renderItem(activeIndex), renderItem(activeIndex + 1)), /*#__PURE__*/React.createElement(_rcVirtualList.default, { itemKey: "key", ref: listRef, data: memoFlattenOptions, height: listHeight, itemHeight: listItemHeight, fullHeight: false, onMouseDown: onListMouseDown, onScroll: onPopupScroll, virtual: virtual }, function (item, itemIndex) { var _classNames; var group = item.group, groupOption = item.groupOption, data = item.data, label = item.label, value = item.value; var key = data.key; // Group if (group) { return /*#__PURE__*/React.createElement("div", { className: (0, _classnames.default)(itemPrefixCls, "".concat(itemPrefixCls, "-group")) }, label !== undefined ? label : key); } var disabled = data.disabled, title = data.title, children = data.children, style = data.style, className = data.className, otherProps = (0, _objectWithoutProperties2.default)(data, _excluded); var passedProps = (0, _omit.default)(otherProps, omitFieldNameList); // Option var selected = rawValues.has(value); var optionPrefixCls = "".concat(itemPrefixCls, "-option"); var optionClassName = (0, _classnames.default)(itemPrefixCls, optionPrefixCls, className, (_classNames = {}, (0, _defineProperty2.default)(_classNames, "".concat(optionPrefixCls, "-grouped"), groupOption), (0, _defineProperty2.default)(_classNames, "".concat(optionPrefixCls, "-active"), activeIndex === itemIndex && !disabled), (0, _defineProperty2.default)(_classNames, "".concat(optionPrefixCls, "-disabled"), disabled), (0, _defineProperty2.default)(_classNames, "".concat(optionPrefixCls, "-selected"), selected), _classNames)); var mergedLabel = getLabel(item); var iconVisible = !menuItemSelectedIcon || typeof menuItemSelectedIcon === 'function' || selected; var content = mergedLabel || value; // https://github.com/ant-design/ant-design/issues/26717 var optionTitle = typeof content === 'string' || typeof content === 'number' ? content.toString() : undefined; if (title !== undefined) { optionTitle = title; } return /*#__PURE__*/React.createElement("div", (0, _extends2.default)({}, passedProps, { "aria-selected": selected, className: optionClassName, title: optionTitle, onMouseMove: function onMouseMove() { if (activeIndex === itemIndex || disabled) { return; } setActive(itemIndex); }, onClick: function onClick() { if (!disabled) { onSelectValue(value); } }, style: style }), /*#__PURE__*/React.createElement("div", { className: "".concat(optionPrefixCls, "-content") }, content), /*#__PURE__*/React.isValidElement(menuItemSelectedIcon) || selected, iconVisible && /*#__PURE__*/React.createElement(_TransBtn.default, { className: "".concat(itemPrefixCls, "-option-state"), customizeIcon: menuItemSelectedIcon, customizeIconProps: { isSelected: selected } }, selected ? '✓' : null)); }));};var RefOptionList = /*#__PURE__*/React.forwardRef(OptionList);RefOptionList.displayName = 'OptionList';var _default = RefOptionList;exports.default = _default;/es/OptionList.js ...

August 23, 2023 · 11 min · jiezi

关于react.js:React-18TS的根本概念

React 18+TS的基本概念TypeScriptTypeScript是一种动态类型的编程语言,它可能在编译时查看代码中的类型谬误,从而提高代码的可读性和可维护性1。TypeScript还支持ES6+的新个性,如类,模块,箭头函数,解构赋值等,使得代码更加简洁和现代化1。 TypeScript可能与React框架无缝集成,只需要安装相应的类型定义文件即可。例如,要使用React 18+TS开发利用,可能执行以下命令: npm install --save react@next react-dom@nextnpm install --save-dev typescript @types/react @types/react-dom这样就可能在.ts或.tsx文件中使用React和TypeScript了。 React 18React 18是React框架的最新版本,它蕴含了一些重大的更新和改进2。其中最引人瞩目的是Server Components,它可能让开发者在服务器端渲染组件,并将后果发送给客户端3。这样可能缩小客户端的代码量和网络传输量,提高利用的加载速度和响应速度3。 另一个重要的个性是Suspense,它可能让开发者在组件中申明数据依赖,并在数据加载时浮现一个占位符4。这样可能避免组件在渲染过程中出现闪动或空白的情况,提高用户体验4。 还有一个值得关注的个性是Concurrent Rendering,它可能让React在后盾渲染更新,并在合适的时机浮现给用户5。这样可能避免长时间的渲染工作阻塞用户交互,提高利用的流畅度和稳定性5。 要使用React 18+TS开发利用,需要配置一些实验性的个性。例如,在tsconfig.json文件中增加以下内容: { "compilerOptions": { "jsx": "react-jsx", "jsxImportSource": "react", "experimentalDecorators": true, "useDefineForClassFields": true }}这样就可能在.tsx文件中使用JSX语法,并启用装璜器和类字段等个性了。 React 18+TS的劣势使用React 18+TS开发前端利用有以下几个劣势: 可能利用TypeScript的类型零碎和ES6+的新个性,编写更加健壮、简洁和现代化的代码。可能利用React 18的新个性,如Server Components, Suspense, Concurrent Rendering等,提高利用的性能和用户体验。可能享受React生态系统中丰富的资源和工具,如 Create React App, Next.js, React Router, Redux, Material UI等,疾速搭建和部署利用。 React 18+TS在线教育平台示例为了展示如何使用React 18+TS构建一个在线教育平台,简略实现一个前端页面,浮现课程列表和课程详情。 首先,咱们需要创建一个React 18+TS我的项目,可能使用Create React App工具,执行以下命令: npx create-react-app react18-ts-edu --template typescriptcd react18-ts-edunpm start这样就可能在阅读器中看到一个默认的页面了。 接下来,咱们需要安装一些依赖库,如GraphQL, Apollo Client, Material UI等,执行以下命令: ...

August 19, 2023 · 2 min · jiezi

关于react.js:React请求机制优化思路-京东云技术团队

说起数据加载的机制,有一个绕不开的话题就是前端性能,很多电商门户的首页其实都会做一些垂直的定制优化,比方让申请在页面最早加载,或者在前一个页面就进行预加载等等。随着react18的公布,申请机制这一块也是被一直谈起,并且在后续其实也给出了明确的方向。 如果咱们页面中有三个组件C1、C2、C3顺次嵌套,每个组件中有对应的申请F1、F2、F3,通常大多数人会应用useeffect和state变量来实现数据流的获取,这样就意味着必须在组件加载时能力发动申请,所有数据获取都产生在组件的生命周期中,如下图所示,咱们能够将这种获取数据的形式称作瀑布流渲染,然而这种形式有一个问题是,在这种办法中,组件之间的数据获取是按程序进行的,这实际上意味着它们彼此阻塞,如果组件的层级嵌套很深的话,就会导致页面的加载工夫特地长。 为了阻止组件间数据获取的这种程序阻塞,另一种办法就是在组件加载前能够应用Promise.all获取所有的申请数据,这样在组件加载时就曾经获取到所有的数据了。这种形式解决了组件加载程序阻塞彼此数据流获取的问题,然而也产生了一个新的问题,在申请实现之前页面都会是空白的。 基于第二种先申请后渲染的形式,还能够应用Suspense将申请和渲染并行化,Suspense 能够使得组件能够“期待”某些操作完结后,再进行渲染。而这种形式如果要用到理论我的项目中,还须要思考C1、C2、C3对应的申请写在哪里,如果写在组件中,那么加载还是慢的。如果拆分进去,就须要思考文件拆分、code splitting等工程化问题。 在认真的剖析了以上三种形式当前,发现各有优劣,同时基于上述计划,我也提供一个申请优化的思路,首先将申请的JS独自拆分进去打一个文件request.js,在html头部引入request.js并应用async属性让脚本并行执行(如下代码所示),这样既能够保障咱们的申请在最开始就能收回,也能不阻塞后续React代码打包的js文件的执行,相当申请和渲染的代码在并行执行。 // html头部引入request.js<script async src="/js/request.js"></script>在发送完申请之后,须要将返回的数据注入到React组件中,这部分怎么注入呢?简略的代码示例如下: // request.js 中申请局部 evt是公布订阅模式的一个实例window.InitData = { data: null, on: (msg, fn) => evt.on(msg, e => fn(e)), emit: (msg, data) => evt.emit(msg, data),};fetch().then(rs => { InitData.data = rs; InitData.emit("init_data", rs); return rs;});// index.js react代码逻辑…….useEffect(() => { if (InitData.data !== null) { // 这里曾经获取到了申请的返回值 doSomething(); } else { InitData.on("init_data", (data) => { // 利用公布订阅模式获取到数据 doSomething(); }); }}, []);…….总体思路就是在html中最先加载独自打包进去的申请文件并退出async属性使脚本并行执行,将返回的数据挂载到window下或者利用公布订阅模式将数据注入到react组件中。这样其实相似于边申请边渲染的模式,利用提前申请来缩小加载的工夫。后续也是心愿能用工程化的形式去解决数据的申请机制。 ...

August 18, 2023 · 1 min · jiezi

关于react.js:React-Hooks-系列-之-useCallback

React Hooks 系列 之 useCallback原文地址--DapanDocs:https://skillgroup.cn/framework/react/hooks/use-callback.html介绍useCallback 是 React Hooks 中的一个重要成员,它容许咱们在屡次渲染中缓存函数。简略来说,它能够帮忙咱们防止因为函数的从新创立而导致的不必要的从新渲染。 const cachedFn = useCallback(fn, dependencies);用法1、跳过组件的从新渲染当你优化渲染性能的时候,有时须要缓存传递给子组件的函数。例如,当你传递一个函数给一个被 memo 包裹的子组件时,useCallback 能够确保函数在屡次渲染中放弃不变,除非它的依赖产生扭转。 <div ref="useCallback1" /> ::: details demo 代码<<< @/components/react/hooks/memo/FunctionInProps4.jsx::: 在下面的案例中,只有当依赖列表中的值发生变化时,getText 函数才会被从新创立。 2、优化自定义 Hook当你创立自定义Hook时,倡议将返回的任何函数都包裹在useCallback中。这确保了Hook的使用者在须要时可能优化本人的代码。 <div ref="useCallback2" /> ::: details demo 代码<<< @/components/react/hooks/useCallback/useCounter.jsx::: 调用 useCallback 后大抵执行状况graph TD A1[调用useCallback] B1[创立/获取以后组件的Fiber节点] C1[查看Fiber节点上的hooks链表-每个节点对应一个hook] D1[是否存在对应的hook对象?] E1[创立新的hook对象并存储函数] F1[查看hook对象的memoizedState属性] G1[依赖项是否扭转?] H1[从memoizedState获取函数] I1[存储新的函数] J1[更新memoizedState属性] K1[返回memoized函数] A1 --> B1 B1 --> C1 C1 --> D1 D1 -- No --> E1 D1 -- Yes --> F1 E1 --> F1 F1 --> G1 G1 -- No --> H1 --> K1 G1 -- Yes --> I1 --> J1 --> K1

August 17, 2023 · 1 min · jiezi

关于react.js:React-Hooks-系列-之-useMemo

React Hooks 系列 之 useMemo原文地址--DapanDocs:https://skillgroup.cn/framework/react/hooks/use-memo.html介绍useMemo 是 React 的一个 Hook,它用于优化性能,特地是在组件从新渲染时。当组件的某些状态或属性发生变化时,useMemo 能够帮忙咱们防止不必要的计算或渲染。 在简单的 React 利用中,咱们可能会遇到组件频繁从新渲染的状况,这可能会导致利用性能降落。有时,即便状态或属性产生了变动,咱们也不心愿执行某些计算或渲染。这时,useMemo 就派上了用场。 useMemo 承受两个参数:一个函数和一个依赖数组。函数返回咱们想要“记住”的值,而依赖数组通知 React 什么时候从新计算这个值。 const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);::: warning 留神useMemo 第二个参数是一个数组,浅比拟数组中的值,如果是对象或者数组即比拟其援用是否产生了变动,如果有变动则从新计算,否则不从新计算。 案例能够参考 useEffect 中的依赖项。传送门:React Hooks 系列 之 useEffect::: 用法1、跳过代价低廉的从新计算useMemo 返回一个 memoized 值。这意味着它会记住上一次的计算结果,并在依赖项没有发生变化时返回该后果,而不是从新计算。这能够帮忙防止在每次渲染时进行低廉的计算。 <div ref="useMemo1" /> ::: details demo 代码<<< @/components/react/hooks/useMemo/SkipExpensiveCalc.jsx::: 在这个例子中,咱们能够通过比照三个按钮的行为来剖析useMemo的作用: 对于"maxKey - 100"按钮:点击该按钮会更新maxKey的值,因为没有应用useMemo,所以只有有状态更新都会从新计算从 1 到maxKey的数字之和并显示在页面上计算数字之和,即便maxKey的值没有发生变化。对于"maxNumber - 100"按钮:点击该按钮会更新maxNumber的值,然而如果maxNumber没有发生变化,即点击前后的值雷同,那么应用了useMemo的maxNumberSum函数不会从新计算,而是返回之前缓存的后果。只有maxNumber发生变化时,maxNumberSum才须要从新计算。对于"Count + 1"按钮:点击该按钮只会更新count的值,对maxKey和maxNumber没有影响。maxNumberSum 函数不会从新计算,因为它的依赖项没有发生变化。maxKeySum 因为没有应用 useMemo,所以页面从新渲染时,maxKeySum 函数会从新执行。综上所述,useMemo的作用是在依赖项发生变化时进行记忆优化,防止不必要的反复计算,进步性能。在本例中,咱们应用useMemo优化了从 1 到maxNumber的数字之和的计算,确保仅当maxNumber发生变化时才从新计算,防止了在每次渲染时都进行计算的开销。 2、跳过组件的从新渲染useMemo的另一个用处是跳过组件的从新渲染。在某些状况下,咱们心愿组件的某些属性发生变化时,组件不会从新渲染。这时,咱们能够应用useMemo来返回组件的 memoized 值,从而防止组件的从新渲染。 <div ref="useMemo2" /> ...

August 17, 2023 · 1 min · jiezi

关于react.js:基于react18reactvant仿微信聊天IM实例

我的项目介绍react-chat 基于最新版react18.x hooks及react-vant挪动端UI组件库实现仿造微信App聊天实例。 技术框架开发工具:Vscode框架技术:react18+react-dom+vite4.xUI组件库:react-vant (有赞react挪动端UI库)状态治理:zustand^4.3.9路由治理:react-router-dom^6.14.2className混合:clsx^2.0.0弹框组件:rcpop (基于react18 hooks自定义弹框组件)款式解决:sass^1.64.1 我的项目构造整个我的项目采纳react18 hooks函数组件实现页面编码。 react18自定义挪动端弹窗组件RcPoprcpop 基于react18 hook自定义多功能弹框组件。整合了msg/alert/dialog/toast及android/ios弹窗成果。反对组件式+函数式调用形式。 大家感兴趣,能够去看看这篇分享文章。 基于React18 Hooks实现挪动端弹框组件RcPop react18 hooks自定义导航栏+菜单栏组件我的项目中顶部导航栏Navbar和底部菜单栏Tabbar组件均是应用react18自定义组件实现性能。 <Navbar back={false} bgcolor="linear-gradient(to right, #139fcc, #bc8bfd)" title={<span className="ff-gg">React18-Chat</span>} fixed right={ <> <i className="iconfont ve-icon-search"></i> <i className="iconfont ve-icon-plus-circle-o ml-30"></i> </> }/>navbar.jsx模板 function Navbar(props) { const { // 是否显示返回键 back = true, // 自定义返回图标 backIco, // 自定义返回文字 backText, // 题目 title, // 搜寻区 search, // 左侧自定义区 left, // 右侧自定义区 right, // 题目色彩 color = '#fff', // 背景色 bgcolor = '#139fcc', // 题目是否居中 center, // 是否固定 fixed, // 背景镂空通明 transparent, // 层叠 zIndex = 2023, className, ...rest } = props const handleBack = () => { window.history.back() } return ( <div {...rest} className={clsx('rc__navbar', className, {'fixed': fixed, 'transparent fixed': transparent})}> <div className="rc__navbar-wrap flexbox flex-alignc" style={{'background': bgcolor, 'color': color, 'zIndex': zIndex}}> {/* 返回 */} { isTrue(back) && ( <div className="action rc__navbar-action__left" onClick={handleBack}> { backIco ? backIco : <i className="iconfont ve-icon-left"></i> } {backText} </div> )} {left} {/* 题目 */} { !search && <div className={clsx('rc__navbar-title', {'center': center})}>{title}</div> } {/* 搜寻框 */} { search && <div className="action rc__navbar-action__search">{search}</div> } {/* 右侧 */} <div className="action rc__navbar-action__right">{right}</div> </div> </div> )}export default Navbar ...

August 16, 2023 · 4 min · jiezi

关于react.js:Reactmemo-解决了什么问题

React.memo 解决了什么问题?原文地址--DapanDocs:https://skillgroup.cn/framework/react/hooks/memo.htmlReact.memo 是 React 16.6 版本引入的一个新性能,它是一个高阶组件,旨在优化函数组件的性能。那么,它到底解决了什么问题呢? React.memo 根底用法问题:不必要的渲染在 React 中,组件的从新渲染通常是因为状态或 props 的变动引起的。但有时,即便相干数据没有发生变化,组件也可能会进行不必要的渲染。这种不必要的渲染可能会导致性能降落,尤其是在简单的应用程序中。 <div ref="memo1" /> ::: details demo 代码<<< @/components/react/hooks/memo/BasicComponent.jsx::: 在这个例子中,ParentComponent有一个状态count,每当咱们点击按钮时,这个状态就会减少。因为 React 的工作形式,每次count发生变化时,ParentComponent都会从新渲染。这也意味着ChildComponent也会从新渲染,只管传递给它的text prop 并没有产生任何变动。 这就是一个不必要的渲染的例子。每次ParentComponent的状态发生变化时,ChildComponent都会进行不必要的渲染,即便它接管的 props 完全相同。 这种状况在大型应用程序中可能会变得更加重大,因为不必要的渲染可能会在多个组件之间产生连锁反应,导致整个应用程序的性能降落。 解决方案:浅比拟 propsReact.memo 的工作原理是对组件的 props 进行浅比拟。如果传递给组件的 props 没有发生变化,React.memo 会复用上一次的渲染后果,从而防止不必要的渲染。 <div ref="memo2" /> ::: details demo 代码<<< @/components/react/hooks/memo/MemoizedComponent.jsx::: 在上述例子中,即便 ParentComponent 从新渲染(例如,因为 count 状态的变动),因为传递给 MemoizedChildComponent 的 text prop 没有发生变化,ChildComponent 不会从新渲染。如果咱们没有应用 React.memo,每次点击按钮时,ChildComponent 都会从新渲染,即便其 props 没有发生变化。 自定义比拟函数React.memo 的第二个参数是一个比拟函数,它容许咱们自定义比拟 props 的逻辑。如果咱们传递了一个比拟函数,React.memo 将应用它来决定是否从新渲染组件,而不是简略地应用浅比拟。 举例说明: 假如咱们有一个 User 组件,它承受一个 user 对象和一个 onUpdate 函数作为 props。咱们只关怀 user 对象中的 id 和 name 字段,而不关怀其余字段。此外,咱们晓得 onUpdate 函数的援用可能会常常扭转,但它的理论性能不会扭转。 ...

August 15, 2023 · 2 min · jiezi

关于react.js:React-Hooks-系列-之-useRef

React Hooks 系列 之 useRef原文地址--DapanDocs:https://skillgroup.cn/framework/react/hooks/use-ref.htmluseRef 返回一个可变的 ref 对象,其 .current 属性被初始化为传递的参数(initialValue)。返回的对象将在组件的整个生命周期内放弃不变。 返回一个长久的对象<div ref="useRef1" /> ::: details demo 代码<<< @/components/react/hooks/useRef/Timer.jsx::: 上述的 demo 展现了 useRef 的以下个性: 持久性:useRef 返回的 ref 对象在组件的整个生命周期内都是长久的。不会引起组件从新渲染:与 useState 不同,批改 useRef 的 .current 属性不会引起组件从新渲染。在 demo 中,即便咱们减少了 count.current 的值,组件也没有从新渲染。与 DOM 交互<div ref="useRef2" /> ::: details demo 代码<<< @/components/react/hooks/useRef/TextInputWithFocus.jsx::: 这个 demo 次要展现了 useRef 如何在 React 中用于间接与 DOM 元素交互。 保留上一次的值<div ref="useRef3" /> ::: details demo 代码<<< @/components/react/hooks/useRef/PreviousValueComponent.jsx::: 这个 demo 次要展现了 useRef 如何在 React 中用于跟踪上一次的值。 <script setup>import { ref } from 'vue'import renderReact from '@components/react/renderReact'import Timer from '@components/react/hooks/useRef/Timer'import TextInputWithFocus from '@components/react/hooks/useRef/TextInputWithFocus'import PreviousValueComponent from '@components/react/hooks/useRef/PreviousValueComponent'const useRef1 = ref(null)const useRef2 = ref(null)const useRef3 = ref(null)renderReact(Timer, useRef1)renderReact(TextInputWithFocus, useRef2)renderReact(PreviousValueComponent, useRef3)</script> ...

August 15, 2023 · 1 min · jiezi

关于react.js:如何在-PC-Web-页面中使用特性开关发布功能包含代码教程

这是一篇简略的个性开关应用实际教程,次要是展现在 PC Web 页面中是如何应用个性开关来管制产品性能对用户展现的开启与敞开,咱们先理解一下个性开关以及为什么要应用个性开关。 什么是个性开关?个性开关(Feature flag)是软件开发中的一种技术实际,用于控制系统中特定性能的开启和敞开。它容许开发团队在运行时动静地切换不同的性能,而无需批改、构建和部署新的软件版本。 为什么要应用个性开关?- 逐渐公布性能: 通过应用性能开关,你能够逐渐公布新性能,而不是一次性公布给所有用户。 - 升高公布危险:性能开关容许您在应用程序中疾速启用或禁用特定性能,而无需进行从新编译和公布。 - 指标定制和个性化: 通过针对不同用户或用户群体启用或禁用特定性能,您能够依据其需要和偏好提供定制和个性化的体验 - A/B 测试和数据驱动决策: 性能开关使您可能在不同用户之间进行 A/B 测试,比拟不同性能公布后用户反馈数据。 - 灰度公布和回滚: 通过将性能仅对一小部分用户启用,您能够进行灰度公布,逐渐扩大范围。 <p align=center>  -----------------上面是在网页中应用个性开关教程-------------------   </p> 1、首先拜访 https://featureprobe.io/ ,应用你的邮箱登录,无需邮箱验证和明码。 2、登录胜利之后咱们会为您创立一个默认我的项目和环境,点击环境卡片进入开关列表,而后创立一个新的开关,开关名称为「展现学习 React 的链接」、标识为「Show\_Learn\_React」。开关创立的时候须要填写一些必填字段:名称:是一个简短且描述性的词或短语,用于示意该性能开关所管制的性能或个性。标识: 开关的 ID,是开关的惟一标识,不可反复。应用了客户端 SDK:是否在客户端(浏览器、Android 或者 iOS)上应用FeatureProbe。本案例中须要在浏览器端应用,此处抉择应用。返回类型:代码中可能读取到的返回值的类型,可选 boolean、string、number 和 json四种类型。分组:决定了能从开关返回中读取到的返回信息。当开关未失效:指定开关失效状态为未失效时的返回值是哪个分组的值。<!----> 3、开关创立实现后,在开关列表点击开关名称进入开关详情。点击开关「开关名」右上角连贯 SDK 按钮,咱们会在此环节提醒你如何将 SDK 集成至您本人的应用程序中。 4、接下来你须要筹备一个 Web 应用程序。你能够不应用任何 Javascript 框架抉择原生的 html 和 js,能够应用 Create React App 来创立一个 React 应用程序,也能够应用 Vue CLI 创立一个 Vue.js 程序。为了不便演示,咱们以 React 工程为例:第一步:应用 Create React App 创立一个名为 react-demo 的 React 工程。npx create-react-app react-demo && cd react-demo第二步:装置 FeatureProbe 的 JavaScript SDK。npm install featureprobe-client-sdk-js --save第三步:通过 npm start 命令启动应用程序,在浏览器中拜访http://localhost:3000/ 能够看到页面的展现成果如下: ...

July 12, 2023 · 2 min · jiezi

关于react.js:React-中的-JS-报错及容错方案

前言导致白屏的起因大略有两种,一为资源的加载,二为 JS 执行出错 本文就 JS 中执行的报错,会比拟容易造成"白屏"场景,和能解决这些问题的一些办法,作出一个汇总 常见的谬误SyntaxErrorSyntaxError(语法错误)对象代表尝试解析不合乎语法的代码的谬误。当 Javascript 引擎解析代码时,遇到了不合乎语法标准的标记(token)或标记程序,则会抛出 SyntaxError。这里排列下 SyntaxError 的常见谬误 保留字谬误SyntaxError: "x" is a reserved identifier (Firefox)SyntaxError: Unexpected reserved word (Chrome) 如在控制台执行下方代码,则会上述谬误呈现 const enum = 1enum 在严格模式和非严格模式下都是保留字。 而以下标记符只会在严格模式下才作为保留字: implementsinterfaceletpackageprivateprotectedpublicstatic例如: const implements = 1 // ✅"use strict";const implements = 1; // caught SyntaxError: Unexpected strict mode reserved word命名谬误一个 JavaScript 标识符必须以字母结尾,下划线(_)或美元符号($)。他们不能以数字结尾。只有后续字符能够是数字(0-9)。var 1life = 'foo';// SyntaxError: identifier starts immediately after numeric literalvar foo = 1life;// SyntaxError: identifier starts immediately after numeric literal谬误的标点在代码中有非法的或者不冀望呈现的标记符号呈现在不该呈现的地位。“This looks like a string”;// SyntaxError: illegal character42 – 13;// SyntaxError: illegal character代码里应用了中文的引号和横杠,造成了解析谬误,这里就体现了编辑器的重要性 ...

July 11, 2023 · 4 min · jiezi

关于react.js:听说后端的你在学-React

一、React 是什么在 React 之前前端有三个里程碑意义的 library/framework jQuery 解决了浏览器兼容和 DOM 元素快捷操作问题,其链式操作 API 也对后续前端框架产生了深刻影响;Knockout 提出了前端代码 MVVM 分层理念,数据通过模板映射为 UI 视图,大幅度缩小了 DOM 操作;AngularJS 在 MVVM 根底上引入了双向绑定,数据变动主动反映到 UI,视图上的操作也反向自动更新数据;其通过指令拓展 HTML 的格调晋升了模板引擎的灵活性,惋惜作者引入了大量借鉴服务器编程的概念,让 AugularJS 学习老本直线回升,性能也略有有余;React 是一个申明式、高效、灵便的用于构建用户界面的 JavaScript library,React 核心理念在于将一些简短、独立的代码片段组合成简单的 UI 界面,这些代码片段被称作 “Component”。React 不是 MVC 框架,更像是其中 V,仅仅负责用户交互视图的渲染。React 带来了三个颠覆性理念,在接下来的章节中将一一介绍: JSX,应用 JavaScript 表白 UI + 交互,充分利用 JavaScript 的灵活性;fx(props) = UI,数据驱动 UI,单向数据流、函数格调的页面组件;Virtual DOM,服务器、客户端应用同一套代码渲染——同构,解决前端利用 SEO 问题;二、疾速初始化 React 我的项目应用 Create React App [1]能够疾速初始化一个 React Web 我的项目。 $ npx create-react-app learn-react --template typescript$ cd learn-react$ npm start执行 npm start后浏览器会在 http://localhost:3000 关上我的项目首页。 ...

July 10, 2023 · 4 min · jiezi

关于react.js:java同步synchronized详解

synchronized能够润饰代码块也能够润饰办法,还能够作用于静态方法,类和某个实例。 每个对象都有一把锁,当多个线程同时访问共享资源的时候,须要用到synchronized,synchronized分为代码块和办法,代码块须要显示的指定对象,而办法不须要(即以后对象)。 java的内存模型是对每一个过程都有主内存,每个线程也有本人的内存,它们从主内存中取数据,而后在计算,在存入主内存。 例子:当初有两个线程A,B线程,A线程对变量i加1,B线程同时对i加2,这两个线程同时操作,如果没有同步解决则B线程做的操作会笼罩A线程的操作。 这时能够用synchronized解决,synchronized具备原子性,原子操作:取数据,操作数据,存数据。synchronized能够保障同一时间只有一个线程操作该对象。 java中对非Long和Float原始数据类型的存,取为原子操作。其实就是对一个字节的存,取操作,因为Float和Long为两个字节,所以其取,存为非原子操作。如果想把他们变成原子操作能够用volatile. 作用区域次要有两种: (1)、办法 (2)、代码块 对于用一对像的同步操作只能有一个线程,而对于不同对象是互不烦扰的。Public synchronized void change() { //同步办法} Public void change() { Synchronized(this) { //同步语句:(因为效率问题,有时思考应用同步语句块) }}http://www.developcls.comhttp://www.developcls.com/qa/62757677e36d440187842616c7b856b3... 同步办法是针对以后对象的,如果不针对以后对象,而是针对其余对象能够用同步语句,如: private byte[] lock= new byte[0]; Public void change() { Synchronized(lock) {}} 自定义锁留神: a、对象必须为private避免其余类对象拜访 b、geter办法最好clone一个对象返回 其余用法 能够针对静态方法和类Class Foo { public synchronizedstatic void methodAAA()// 同步的static 函数 { //…. } public void methodBBB() { synchronized(Foo.class) // class literal(类名称字面常量) } } 它是针对整个类的,所以只能是同一个类的一个线程进行拜访 synchronized(this)与synchronized(static class)的区别: synchronized就是针对内存区块申请内存锁,this是类的一个对象,也就是针对雷同对象的互斥操作,其余线程能够拜访该类的其余对象。static是针对类,static是整个类共有的,也就是该类的所有成员间互斥。在同一时间只有一个线程能够拜访该类的实例。建设三个线程,A线程打印10次A,B线程打印10次B,C线程打印10次C,要求线程同时运行,交替打印10次ABC。这个问题用Object的wait(),notify()就能够很不便的解决。代码如下: ...

July 7, 2023 · 1 min · jiezi

关于react.js:react18中使用reactrouterdom-v6浏览器前进后退没有正确选中菜单的解决办法

事件起因就是发现在浏览器点击后退后退的时候,menu的选中状态并不会自动更新,如下图所示: 想要的正确成果如下: 那话不多说,开始思考解决办法 应用的ui库是antd的,旁边的menu即Menu, 查阅官网相干组件材料可知,须要在menu组件上加上selectedKeys属性 本地的menu局部代码如下 <Menu theme="dark" mode="inline" defaultSelectedKeys={[defaultSelectedKeys]} onClick={onClick} items={[ { key: '/todolist', icon: <UserOutlined />, label: 'todolist', }, { key: '/form', icon: <VideoCameraOutlined />, label: 'Form', }, { key: '/test', icon: <UploadOutlined />, label: '各种测试', }, ]} />把defaultSelectedKeys换成selectedKeys={[selectedKeys]} <Menu ... selectedKeys={[selectedKeys]} />之所以这么做,是因为在加上了selectedKeys当前,实际上defaultSelectedKeys曾经齐全被前者代替了,后者要不要都不影响页面体现。 然而,很重要的一点就是换成了selectedKeys当前,须要手动在点击事件中更改其对应的值,不然选中的项永远不会扭转,如下图所示 另外,记得给selectedKeys加上初始值,不然页面第一次进来的时候是没有选中项的 替换完后,接下来就是须要获取当前页面上的url地址了,因为selectedKeys是依据Menu中items的key来进行准确匹配的。 引入如下代码 import {useLocation} from 'react-router-dom'const location = useLocation();useEffect(()=>{ window.onpopstate = function (e: PopStateEvent) { console.log('location',location) }; return (()=>{ window.onpopstate = null; })},[])useLocation为react-router-dom自带的办法,返回以后路由的相干信息如下: ...

July 3, 2023 · 1 min · jiezi

关于react.js:React-Hook-和-SCSS-结合的响应式布局方案

背景公司中有多个我的项目须要同时开发 PC 端和 H5 端,大部分中央逻辑和交互比拟相似,次要是款式上有些区别。为了更好地复用代码、进步开发效率,通过一段时间的实际后,咱们总结出这套 React Hook 和 SCSS 联合、px 和 vw 共存的响应式布局计划。 根底代码创立我的项目首先,咱们来创立一个我的项目,这里我用的是 Create React App,抉择了 typescript 模板,通过以下命令即可创立我的项目: npx create-react-app my-app --template typescript逻辑局部逻辑这块,次要思路是通过写一个 Hook,用于检测以后视口是否为挪动端大小,并依据视口大小实时更新返回值,这样咱们在组件中须要的时候间接调用这个 Hook 就行了,十分不便。 首先, App.tsx 负责实时检测是否挪动端,并且将该值通过 Context 传递给所有子组件和后辈组件,代码如下: import { createContext, useState, useEffect } from 'react';import MyComponent from './components/MyComponent/MyComponent';// 判断以后视口是否为挪动端大小export const checkIsMobile = () => { return window.innerWidth <= 620}// 保留是否挪动端状态的 contextexport const IsMobileContext = createContext<boolean>(false)function App() { const [isMobile, setIsMobile] = useState(checkIsMobile) useEffect(() => { const resizeHandler = () => { const currentIsMobile = checkIsMobile() setIsMobile(currentIsMobile) } // 监听 window 的 resize 事件,窗口大小扭转时从新计算 isMobile 的值 window.addEventListener('resize', resizeHandler) // 组件销毁时勾销事件监听 return () => window.removeEventListener('resize', resizeHandler) }, []) return ( // 通过 IsMobileContext 将 isMobile 的值传递给所有子组件 <IsMobileContext.Provider value={isMobile}> <MyComponent/> </IsMobileContext.Provider> );}export default App;而后咱们创立 useIsMobile.ts 这个文件,这外面次要保留咱们的 useIsMobile hook,用于在组件中响应式获取 App.tsx 中传递下来的 isMobile 值,代码很简略: ...

July 1, 2023 · 4 min · jiezi

关于react.js:React-SSR-写个-Demo-一学就会

明天写个小 Demo 来从头实现一下 react 的 SSR,帮忙了解 SSR 是如何实现的,有什么细节。 什么是 SSRSSR 即 Server Side Rendering 服务端渲染,是指将网页内容在服务器端中生成并发送到浏览器的技术。相比于客户端渲染(CSR),SSR 个别用于以下场景: SEO (搜索引擎优化):因为局部搜索引擎对 CSR 内容反对不佳,所以 SSR 能够晋升网站在搜索引擎后果中的排名。首屏加载速度:因为 SSR 能够在服务器端生成残缺的 HTML 页面,用户关上网页时可能更快地看到内容,不会看到长时间的白屏,能够晋升用户体验。暗藏某些数据:因为 CSR 须要从服务器将数据下载下来进行动静渲染,所以一些数据很容易被别人获取,而 SSR 因为数据到渲染的过程在服务端实现,所以能够用来暗藏一些不想让别人轻易取得的数据。如何实现简略的 SSR 其实实现很简略,只须要在服务端导入要渲染的组件,而后调用 react-dom/server 包中提供的 renderToString 办法将该组件的渲染内容输入为字符串后返回客户端即可。 Server 端的组件上面写一个简略的例子: 服务端代码: import express from 'express';import React from 'react';import { renderToString } from 'react-dom/server';import App from '../ui/App';const app = express();app.get('/', (_: unknown, res: express.Response) => { res.send(renderToString(<App />));});app.listen(4000, () => { console.log('Listening on port 4000');});此处要留神服务端须要反对 jsx 语法的解析,我这里间接应用 esno 执行 ts 代码,在 tsconfig.json 中配置 jsx 即可。 ...

June 18, 2023 · 2 min · jiezi

关于react.js:react函数组件使用antd-ui框架-点击按钮清空输入框的值

明天突发奇想,想要用react做一个todolist,性能很简略,即:一个输入框,一个按钮,一个列表输入框中输出内容,点击按钮,列表新增一列,而后清空输入框其余倒没什么好说的,次要的问题就在于最初一步,即点击按钮当前,清空输入框。 作为一个初学者,查阅文档当前,决定采纳ref获取dom的办法批改输入框的值。 能够看到,通过ref,间接拿到了输入框的dom对象,和以后的value值,由此理所应当,间接inputRef.current.input.value=0就能够批改以后输入框的值了 然而,后果是否定的,这样无奈批改输入框的值,查了很多材料,有的说什么通过inputRef.current.state.value=0 能够改,都是骗人的。 最终还是要通过间接对组件的value属性进行操作,才可能扭转输入框的值 首先第一步,绑定value对象 const [value,setValue] = useState('')<Search value={value} />第二步,绑定change事件,不然输入框的值始终都会是默认值 const changeValue = (e:any) =>{ setValue(e.target.value)}<Search value={value} onChange={changeValue}/>第三步,绑定按钮的点击事件,在点击的时候,清空value的值 const onSearch=(e:any)=>{ setValue('')}<Search ... onSearch={onSearch}/>自此,点击清空输入框就实现了。 react在我看来还是十分的不不便的,如果是用anglar来做的话,间接在输入框的value绑定一个值,后续间接改这个值就行了。react并不是双向绑定的,所以不不便

June 12, 2023 · 1 min · jiezi

关于react.js:如何在2023年开启React项目

在这里,我想给你一个新的React我的项目入门的简要概述。我想反思一下长处和毛病,反思一下作为一个开发者所须要的技术水平,反思一下作为一个React开发者,每个启动我的项目都能为你提供哪些性能。最初,你将理解到针对不同需要的3种解决方案。 免责申明:从集体开发者的角度来看,我齐全反对React团队在其新文档中推动的框架/SSR议程。然而,我感觉最近的布告使React初学者和想采纳React的公司处于不利位置。因而,我想在这里给他们提供更多不同的抉择,作为逃生通道。 应用ViteVite是create-react-app(CRA)的明确继承者,因为他们俩没有太大的区别。与create-react-app(CRA)(应用Webpack)相比,它的速度要快得多,因为它在后盾应用了esbuild。 与create-react-app(CRA)雷同,Vite依然偏向于创立单页应用程序(SPA),其客户端路由/渲染性能优于SSR。然而,因为SSR现在正成为一个更重要的话题,因而它在Vite中作为了可选性能。 当我的项目来自CRA时,间接迁徙到Vite是很容易的。像TypeScript、ESLint、SVG和SSR这样的可选性能只需在Vite的vite.config.js文件中进行一些配置,除此之外还能够在一些特定性能文件中进行配置(如tsconfig)。 Vite容许开发者在没有主意的框架下应用React。开发者能够抉择互补的React库进行路由、数据获取、状态治理和测试。与所有的React框架相比,它不会强制你应用任何特定的React性能、库或配置(在我的项目层面)。 最初,Vite激励初学者学习React和它的基本原理,而不被框架所分心。当Vite成为副驾驶时,初学者能够齐全专一于React和它的外围性能。相比之下,在框架环境中学习React时,React简直成了副驾驶,而不得不遵循框架的意见(比方基于文件的路由)。 应用Vite的长处简直能够间接代替CRA仍然对SPA/CSR敌对,但SSR是可选的没有框架/公司的捆绑轻量级在性能层面上不与React一概而论 因而专一于React自身,而不是一个框架理解React基本原理的学习曲线比拟平缓应用Vite的毛病优先思考SPA/CSR没有框架反对无奈应用React为集成框架提供的架构性能 例如,React服务端组件(RSC)为什么可能不是React文档中的默认值应用SPA/CSR而不是SSR技术捆绑使开发者无奈应用所有React性能 例如,React服务端组件(RSC)不利于实现以下愿景 领有一个React框架启用不同的渲染技术启用所有可用的React性能 例如,React服务端组件(RSC)框架无关(这里指React) React不是Vite的重点Vue的缔造者尤雨溪的观点应用NextNext.js作为一个框架是十分成熟的,因而当React开发者想在一个有主意的框架环境中应用React时,它是一个理智的抉择。它蕴含了许多个性(例如基于文件的路由)。如果Next.js不是你的菜,能够看看最近公布的Remix框架,它与Next.js的不同之处在于它专一于web规范。 Next.js优先思考将服务端渲染(SSR)作为渲染技术。然而,它也能够用于动态网站生成(SSG)和客户端渲染(CSR)。在此基础上,还有一些更前沿的渲染技术,如增量式网站渲染(ISR)和React服务端组件(RSC)。是什么让这所有变得更加令人震惊:你能够在Next.js应用程序中混合和匹配渲染技术。尽管营销页面能够应用SSG,但登录/注册背地的理论应用的SSR。 不过,这么大量的新技术也是有代价的:不同的渲染技术会产生工程开销,框架会一直地钻研新的渲染技术,因而最终会扭转其优先级,而且不是所有的程序员都能跟上步调。只管Next.js在过来没有引入破坏性变动方面做得很好,但在将JavaScript/React渲染技术引入后端这个前沿畛域工作时,总会有新的规范/配置。 总的来说,尽管Next.js蕴含了许多个性(例如基于文件的路由),但它也有责任。尽管React自身(比方应用Vite)放弃绝对稳固,但你必定会看到Next.js生态系统的变动,因为他们正带头将React带到服务器上。 Next的长处带有内置库的框架SSR和许多其余渲染技术 性能晋升(留神:如果解决正确的话)与CSR相比,SEO失去改善Vercel是领有大量资金的大公司 与React外围团队严密单干有许多React外围团队的成员被雇佣在前沿畛域耕耘Next的毛病在前沿畛域耕耘与应用Vite的React相比,开销/稳定性/可维护性较差与应用Vite的React相比,学习曲线更平缓 更多关注框架的细节,更少关注React自身框架(和基础设施,例如在Vercel上部署)捆绑 后者可能由OpenNext解决为什么可能是React文档中的默认值最成熟的框架,合乎React的框架议程SSR是一等公民,合乎React的SSR议程应用React的所有原始值 例如,React服务端组件(RSC)不优先思考"过期的"SPA/CSR与React及其外围团队关系密切与React的外围团队单干,在Next中实现新的性能 并最终被Meta/Facebook应用应用AstroAstro容许开发人员创立以内容为重点的网站。因为它的群岛架构以及选择性混合,它默认给每个网站提供高效的性能。因而,SEO相干的网站从应用Astro中获益。 从实现的角度来看,它偏向于多页面应用程序(MPA)的概念,而不是单页面应用程序(SPA)。因而,它完结了历史循环:从MPA是网站的次要类型(2010年之前)到SPA被取代(2010-2020年),再次回到MPA(从而使MPA首先成为一个术语)。 Astro是一个与框架(这里是指React)无关的解决方案。因而,你能够应用Astro的内置组件语法或你抉择的框架(如React)。尽管框架只是用于服务端的渲染,并没有裸露给客户端。只有当一个人决定将一个交互式群岛混合到客户端时,它才会获取所有必要的JavaScript代码到浏览器上。 对于以内容为重点的网站,Astro被视为Gatsby的竞争对手。在过来的几年里,Gatsby失去了与Next的间接竞争。在这场竞争中,人们可能过多地关注与Next的性能对等(如SSR),因而对以内容为重点的网站真正重要的DX和性能的关注较少。这给了Astro一个机会,来作为可行的代替计划染指。 总之,只管Next(有SSR/SSG/ISR)或Gatsby也适宜以内容为重点的网站。不过Astro作为新的竞争对手,仿佛合乎以内容为重点的网站更具体的要求(比方性能、专一于内容制作)。 相比之下,Next混合了渲染技术。因而,一个性能优化的营销页面能够在应用程序中实现,而理论的应用程序则暗藏在登录后。但依据Astro的基准,它的性能依然较差(不思考RSC,因为还不稳固),因而我宁愿在古代Monorepo设置中混合应用Next和Astro,以使应用程序和网站并存。 应用Astro的长处以内容为重点的网站性能SEO框架无关(比方React)应用Astro的毛病不为动静web应用程序做广告为什么可能不是React文档中的默认值框架无关 React不是Astro的重点与React的新性能不统一 例如,React服务器组件 应用群岛架构,而不是选择性混合每次点击链接都要从新加载整个页面 因而不是最好的导航用户体验这些问题最终会在RSC的Next中失去更好的解决相同,Gatsby被列入了举荐启动程序的名单中 一流的React解决方案在架构层面上与React的性能相整合与React外围团队有更严密的分割更多抉择应用Parcel取代ViteMonorepo Setup(如Turborepo),可选Vite、Next和/或Astro。用于tRPC的create-t3-app用于挪动端应用程序的React Native/Expo用于桌面端应用程序的Tauri/Electron用React以外的其余库启动SSR我的项目的抉择: SvelteKitSolidStartQwikCity如何开启React我的项目如果你开始学习React(从教育者的角度),我倡议应用Vite,因为它尽可能地靠近React的基本原理。如果你只想找一个轻量级的SPA/CSR解决方案,也是如此。如果你想在React的根底上寻找一个有主意的框架,并蕴含几种渲染技术(和基础设施),我会举荐应用Next,因为它是最成熟的解决方案,有所有的长处和毛病。 如果Next.js不合乎你的需要,但你依然在寻找一个蕴含所有个性的SSR框架,请应用Remix。如果你想领有一个以内容为重点的网站,请查看应用Astro大节。免责申明:在2023年写这篇博文与2024年写这篇博文可能齐全不同,届时Next的App Router和RSC会变得稳固,从而成为创立服务端React应用程序的现状。在我集体看来,这是一个转折点,它可能会推动Next成为所有之前列出的案例的一体化解决方案。 最终想法尽管许多教育工作者可能会同意为React初学者提供一个更容易的终点(直到RSC/Next有更多的稳定性和更精简/整合的学习教训),但React文档中新的"开始一个新的React我的项目 "局部反而使很多React初学者处于一个两难的地步。 产生了什么:过来征询React的初学者被指向旧的文档;但被告知应用带钩子的函数组件。可能会产生什么:征询React的初学者被指向新的文档;但会被告知应用Vite而不是Next。总之,我为React团队提供新的文档感到高兴。然而,它随同着许多探讨,特地是围绕React启动我的项目的抉择。 只管每个人都隐约晓得SSR和框架正在成为古代React的高优先级,但对于许多人来说,没有看到Vite是从头开始创立一个React我的项目的最简略的办法,依然是一个惊喜(至多在2023年)。在2024年可能会有不同的状况,届时所有的基本要素(为初学者提供的React/Next交互式教程、Next13/RSX的稳定性、对RSC优先利用的关注)都会存在,但当初"如何创立一个新的React利用"的转变,以及新的文档仿佛都很仓促。 从一个独自的开发者的角度来看,我很期待这次服务端的冒险会带给咱们什么。然而,我感觉当初初学者开始学习React,就像他们在React Hooks公布时一样,因而这篇博文是为了提供更多样化的抉择来开启一个新的React我的项目。

June 6, 2023 · 1 min · jiezi

关于react.js:高级前端进阶必修自主打造高扩展的业务组件库

download:高级前端进阶必修:自主打造高扩大的业务组件库在前端开发中,脚手架是一种弱小的工具,它能够疾速创立我的项目模板和配置,进步开发效率。市面上有很多优良的脚手架,但自主搭建一个适宜本人团队应用的脚手架也是十分有必要的。上面介绍5个精品脚手架,让你更好地了解如何自主搭建一个高质量的脚手架。 React 脚手架React 是古代 Web 开发中最热门的框架之一,所以一个好的 React 脚手架十分重要。自主搭建一个基于 React 的脚手架须要思考以下三个方面:我的项目构造集成第三方库路由治理你能够参考 create-react-app 这个脚手架的代码,这是 React 官网出品的脚手架。 Vue 脚手架Vue 也是另一个十分风行的前端框架,它绝对于 React 更加易学易用,因而越来越多的团队抉择了 Vue。自主搭建一个基于 Vue 的脚手架须要思考以下几个方面:我的项目构造集成第三方库路由治理状态治理你能够参考 vue-cli 这个脚手架的代码,它是 Vue 官网举荐的脚手架。 Node.js 脚手架Node.js 是一个十分风行的后端语言,自主搭建一个基于 Node.js 的脚手架能够大幅提高后端开发效率。须要思考以下几个方面:我的项目构造集成数据库日志解决测试环境配置你能够参考 express-generator 这个脚手架的代码,它是 Express 官网出品的脚手架。 Electron 脚手架Electron 是一个跨平台的桌面利用程序开发框架,能够应用 HTML、CSS 和 JavaScript 来构建桌面应用程序。自主搭建一个基于 Electron 的脚手架须要思考以下几个方面:我的项目构造界面开发主过程和渲染过程交互打包公布你能够参考 electron-forge 这个脚手架的代码,它是 Electron 官网举荐的脚手架。 小程序脚手架小程序是一种新兴的挪动应用程序,脚手架能够帮忙开发人员疾速创立小程序我的项目。自主搭建一个基于小程序的脚手架须要思考以下几个方面:我的项目构造根底组件封装异步申请解决路由治理你能够参考 mpvue 这个脚手架的代码,它是一款基于 Vue 的小程序开发框架。 以上就是自主搭建5个精品脚手架的具体介绍,当然在理论利用中依据团队的需要还须要进行一些定制化的开发。

May 31, 2023 · 1 min · jiezi

关于react.js:reactantdupload-使用一

1.电脑系统 windows11专业版2.开发环境 react16+antd43.在我的项目开发的时候,咱们会须要在上传的时候做一些限度,上面我来分享一下。4.template: <Upload listType="picture-card" className="avatar-uploader" fileList={hotImgFileList} showUploadList={{ showPreviewIcon: true, showDownloadIcon: false, showRemoveIcon: true, }} customRequest={(options) => { UploadCustomRequest(options, { type: 'bgImg', FileSize: 1, fileType: ['png', 'jpg', 'jpeg'], fileTypeValue: '.png、.jpg、.jpeg', }); }} beforeUpload={(file) => { beforeUpload(file, { type: 'bgImg', FileWidth: 750, FileHeight: 0, fileWidthValue: '750*0', }); }} >5.mathods: const beforeUpload = (file, data) => { const width = data.FileWidth; const height = file.FileHeight; return new Promise((resolve, reject) => { let reader = new FileReader(); reader.addEventListener( 'load', () => { let img = new Image(); img.src = reader.result; img.onload = () => { if (img.width < width || img.height < height) { data.FileHeight == 0 ? message.error(`请上传严惩于等于 ${data.FileWidth} 的封面图!`) : message.error(`请上传宽高大于等于 ${data.fileWidthValue} 的封面图!`); reject(`请上传宽高大于等于 ${data.fileWidthValue} 的封面图!`); } else { resolve(); } }; }, false, ); reader.readAsDataURL(file); }); };const UploadCustomRequest = (options, data) => { // console.log(options); console.log(options.file); console.log(data); const fileType = options.file.name.split('.'); const fileDate = fileType.slice(-1); const isFileSize = options.file.size / 1024 / 1024 < data.FileSize; let IsFileType = false; if (data.fileType.indexOf(fileDate[0]) < 0) { IsFileType = false; message.error(`仅反对图片格式:${data.fileTypeValue}格局图片!`); return Upload.LIST_IGNORE; } else { IsFileType = true; } !isFileSize && message.error(`上传图片大小不能超过${data.FileSize}M!`) && Upload.LIST_IGNORE; };6.本期的分享到这里就完结啦,心愿对你有所帮忙,让咱们一起致力走向巅峰。 ...

May 30, 2023 · 1 min · jiezi

关于react.js:如何下载react16版本

create-react-app创立的我的项目,如何下载指定react版本咱们平时可能会遇到面试官问你16,17,18有什么区别,那么如何降级呢? 1、删除我的项目的node_modules文件夹和yarn-lock.json(如果你用的npm,那就是package-lock.json)文件 2、批改package.json文件办法一,版本你能够本人看哪个胜利用哪个,不肯定跟我一样 "react": "^16.8.2","react-dom": "^16.8.2","react-scripts": "2.1.5",办法二,略微麻烦点 yarn add react@16.8.2 react-dom@16.8.2 --legacy-peer-deps --S// 留神:react18里没有react-scripts,用yarn或者npm,pnpm随便哈,都是一通百通的货色yarn add react-scripts -S3、在以后我的项目所在文件夹下,执行yarn install --legacy-peer-deps我以后是react18,所以我把leass-loader从8.xxx改成了7,启动起来无问题 4、批改src/index.js import React from 'react';import ReactDOM from 'react-dom'import Demo from './views/Demo7';ReactDOM.render( <Demo />,document.getElementById('root'));而后运行就功败垂成

May 24, 2023 · 1 min · jiezi

关于react.js:React18TSNestJSGraphQL-全栈开发在线教育平台无密

NestJS 是一个基于 TypeScript 构建的 Node.js 框架,旨在提供高效、可扩大和易于保护的解决方案。本文将介绍 NestJS 的特点、劣势和应用场景等方面。download:https://www.666xit.com/4006/ 特点基于 TypeScript:NestJS 基于 TypeScript 构建,能够应用强类型语言编写代码。它提供了更好的代码构造和可读性,使得开发人员能够更加轻松地治理和保护我的项目。模块化架构:NestJS 采纳模块化架构,使得开发人员能够更加便捷地管理应用程序中的各个局部。每个模块都有本人的性能和职责,能够轻松地增加或移除模块,以适应不同的业务需要。反对多种协定和数据库:NestJS 反对多种协定和数据库,包含 HTTP、WebSocket、gRPC 等协定,以及 MySQL、PostgreSQL、MongoDB 等数据库。这使得开发人员能够轻松地与不同的客户端和数据源进行交互。内置依赖注入:NestJS 内置依赖注入机制,使得开发人员能够轻松地治理和组合不同的服务和组件。这大大减少了代码耦合和反复,进步了代码的可维护性和可测试性。劣势可扩展性:NestJS 的模块化架构使其非常适合构建大型、简单的应用程序。开发人员能够依据不同的业务需要增加或移除模块,以适应应用程序的变动。易于保护:NestJS 的依赖注入机制和模块化架构使其易于保护。它提供了更好的代码构造和可读性,使得开发人员能够更加轻松地治理和保护我的项目。进步生产力:NestJS 提供了很多内置的性能和工具,如 CLI 工具、ORM 等,使得开发人员能够更快地构建和部署应用程序,进步生产力。社区沉闷:NestJS 的社区十分沉闷,有许多贡献者和用户。这意味着开发人员能够轻松地取得帮忙和反对,同时也能够分享本人的教训和常识。应用场景NestJS 能够用于构建各种类型的应用程序,包含 Web 应用程序、后端服务、RESTful API 等。它特地适宜构建大型、简单的应用程序,例如企业级应用程序、电子商务平台等。 NestJS 也能够与其余技术和框架集成,如 Angular、React、Vue.js 等前端框架,以及 Express、Fastify 等后端框架。这使得开发人员能够依据本人的需要抉择最适宜本人的技术栈。 总之,NestJS 是一个基于 TypeScript 构建的 Node.js 框架,具备模块化架构、多种协定和数据库反对、内置依赖注入等特点。它适宜构建大型、简单的应用程序,并提供了更好的代码构造、可读性和可维护性。

May 22, 2023 · 1 min · jiezi

关于react.js:React18TSNestJSGraphQL-全栈开发在线教育平台

download:React18+TS+NestJS+GraphQL 全栈开发在线教育平台如何用原生JavaScript开发高级利用 H2:模块化编程、函数式编程、面向对象编程、DOM操作、异步编程 原生JavaScript是Web开发中最根底的技术之一,它能够实现各种性能和成果。然而,要想用原生JavaScript写出高级的Web应用程序并不容易。在本文中,咱们将介绍一些有用的技巧和办法,使你可能更加无效地应用原生JavaScript来开发高级Web利用。 模块化编程 在大型Web应用程序中,代码很容易变得凌乱和难以保护。因而,模块化编程被宽泛采纳来解决这个问题。通过将代码分成小而独立的模块,能够进步代码的可读性和可维护性,并且能够缩小谬误和反复代码。在JavaScript中,能够应用ES6模块或CommonJS等模块零碎来实现模块化编程。 函数式编程 函数式编程是一种编程范式,它强调函数的纯正性和不可变性。采纳函数式编程能够让代码更加简洁、可读性更强、测试更容易。在JavaScript中,函数式编程能够通过应用高阶函数、闭包和纯函数等个性来实现。 面向对象编程 面向对象编程是一种基于对象的编程办法。JavaScript是一种面向对象的语言,能够应用类、继承和多态等个性来实现面向对象编程。面向对象编程能够进步代码的可重用性和可维护性,并且能够使代码更加易于了解。 DOM操作 DOM(文档对象模型)是一种将HTML文档示意为树状构造的API。在JavaScript中,能够应用DOM API来操作HTML元素。能够应用DOM API来增加、删除、批改HTML元素,以及响应用户的操作。DOM操作是Web开发中最罕用的技术之一。 异步编程 异步编程是一种在不阻塞主线程的状况下执行长时间运行的工作的办法。在JavaScript中,能够应用回调函数、Promise或async/await等技术来实现异步编程。异步编程能够进步Web利用的性能和用户体验,并且能够缩小服务器负载。 总结 本文介绍了如何应用原生JavaScript来开发高级Web应用程序。模块化编程、函数式编程、面向对象编程、DOM操作和异步编程是实现高级Web应用程序的五个关键技术。这些技术能够帮忙你编写更高效、更易于保护的代码,并且能够进步Web应用程序的性能和用户体验。

May 22, 2023 · 1 min · jiezi

关于react.js:React-18-的新更新和使用之新-API

React 18 的新更新和应用之新 APIReact 是一个由 Facebook 推出的 JavaScript 库,被广泛应用于构建 Web 应用程序和用户界面。随着工夫的推移,React 一直地进行更新和改良,以更好地反对最新的技术和开发模式。React 18 是 React 的最新版本,它引入了一些新的性能和 API,使得开发者能够更加轻松、高效地构建可保护和高性能的应用程序。本文将深入探讨 React 18 的新更新和应用之新 API。 React 18 的新更新React 18 引入了一些新的更新,这些更新波及到 React 外围库的改良和优化,以及一些全新的性能和工具的增加。以下是一些重要的更新: Suspense for Data FetchingReact 18 引入了一个名为"数据获取暂停(Suspense for Data Fetching)"的新个性,它容许咱们在组件外部应用异步数据获取,并在期待数据返回时显示一个自定义的加载指示器。这能够大幅提高应用程序的响应速度和用户体验。例如: import { Suspense } from 'react';import { fetchData } from './api';function App() { return ( <div> <Suspense fallback={<div>Loading...</div>}> <MyComponent data={fetchData()} /> </Suspense> </div> );}在下面的例子中,咱们应用 Suspense 组件来包装 MyComponent,并传递一个自定义的加载指示器作为 fallback 属性。MyComponent 通过 fetchData 函数来获取数据,在数据返回前将显示 Loading...。 ...

May 21, 2023 · 2 min · jiezi

关于react.js:React18TSNestJSGraphQL-全栈开发在线教育平台

download:React18+TS+NestJS+GraphQL 全栈开发在线教育平台深刻了解高层架构设计软件开发是一个简单的过程,须要思考到许多因素,例如性能需要、性能、可扩展性、可维护性和安全性等。高层架构设计是软件开发中最重要的一环,它能够帮忙咱们实现零碎的可扩展性、可维护性和可测试性,并且能够使整个零碎更加灵便和易于治理。本文将深入探讨高层架构设计的相干概念和技术。 什么是高层架构?高层架构(High-Level Architecture)是指软件系统的整体构造,包含各个组件之间的关系、数据流动和交互方式等。高层架构通常由几个次要的局部组成,例如用户界面、利用程序逻辑、数据存储和内部服务等。 高层架构因为其形象性质,对于业务逻辑和用户需要等具备较强的容错性和灵活性,因而在软件系统的设计过程中十分重要。 高层架构的长处高层架构的设计能够为软件系统带来很多劣势: 可扩展性通过高层架构设计,咱们能够依据业务需要增加新的组件或服务,而不用放心整个零碎的稳定性和性能问题。 可维护性高层架构能够使代码更加模块化和可重用,从而升高保护老本,并且能够使开发人员更容易地了解和批改代码。 可测试性高层架构能够使咱们更轻松地创立自动化测试,以确保零碎的稳定性和正确性。 可靠性高层架构能够将谬误隔离到独自的组件中,从而防止它们扩散到整个零碎中。 高层架构设计的根本准则在进行高层架构设计时,咱们须要思考以下根本准则: 开闭准则开闭准则(Open-Closed Principle,OCP)是指一个软件实体应该对扩大凋谢,对批改敞开。这意味着咱们应该通过增加新的组件或服务来扩大零碎的性能,而不是间接批改现有的代码。 繁多职责准则繁多职责准则(Single Responsibility Principle,SRP)是指一个类或组件应该只有一个职责。这意味着每个组件应该专一于实现一项工作,并且不应该蕴含与其职责无关的性能。 依赖倒置准则依赖倒置准则(Dependency Inversion Principle,DIP)是指高层模块不应该间接依赖于底层模块,而是应该依赖于形象。这意味着咱们应该应用接口或抽象类来定义组件之间的交互方式,而不是间接援用具体实现。 接口隔离准则接口隔离准则(Interface Segregation Principle,ISP)是指一个类不应该强制实现它不须要的接口。这意味着咱们应该将一个大接口拆分为多个小接口,以便客户端只须要晓得它们须要应用的接口,而不须要晓得全副的接口。 里氏替换准则里氏替换准则(Liskov Substitution Principle,LSP)是指任何能够应用基类对象的中央都应该可能应用子类对象。这意味着咱们应该在继承时放弃父类和子类之间的一致性,以防止不必要的复杂性和谬误。 高层架构设计的技术实现高层架构设计须要抉择适当的技术和工具。以下是一些常见的高层架构设计技术: 模块化模块化是将软件系统划分为互相独立的、可重用的组件的过程。每个模块都应该有清晰的职责,并且应该尽可能遵循上述根本准则。 微服务微服务是一种面向服务架构(Service-Oriented Architecture,SOA)的设计办法,它将软件系统划分为小的、自治的服务,每个服务都能够独立开发、部署和扩大。微服务架构通常应用轻量级通信协议(如REST)来实现服务之间的通信。 畛域驱动设计畛域驱动设计(Domain-Driven Design,DDD)是一种设计办法,它将软件系统建模为一个由业务实体和关系组成的畛域模型。DDD强调将业务需要和代码实现相结合,并通过一直迭代和改良来逐步完善模型。 事件驱动架构事件驱动架构(Event-Driven Architecture,EDA)是一种设计办法,它将软件系统建模为由事件和事件处理程序组成的体系结构。事件驱动架构通常应用音讯队列或公布/订阅模式来实现事件的传递和解决。 论断高层架构设计是软件开发中最重要的一环,它能够帮忙咱们实现零碎的可扩展性、可维护性和可测试性,并且能够使整个零碎更加灵便和易于治理。在进行高层架构设计时,咱们应该遵循根本准则,并抉择适当的技术和工具来实现设计。通过一直迭代和改良,咱们能够创立一个高效、强壮和牢靠的软件系统。

May 21, 2023 · 1 min · jiezi

关于react.js:R语言用贝叶斯线性回归贝叶斯模型平均-BMA来预测工人工资附代码数据

全文链接:http://tecdat.cn/?p=24141最近咱们被客户要求撰写对于贝叶斯的钻研报告,包含一些图形和统计输入。 在本文中,贝叶斯模型提供了变量抉择技术,确保变量抉择的可靠性。对社会经济因素如何影响支出和工资的钻研为利用这些技术提供了充沛的机会,同时也为从性别歧视到高等教育的益处等主题提供了洞察力 背景上面,贝叶斯信息准则(BIC)和贝叶斯模型平均法被利用于构建一个扼要的支出预测模型。 这些数据是从 935 名受访者的随机样本中收集的。该数据集是\_计量经济学数据集\_系列的一部分 。 加载包数据将首先应用该dplyr 包进行摸索 ,并应用该ggplot2 包进行可视化 。稍后,实现逐渐贝叶斯线性回归和贝叶斯模型均匀 (BMA)。 数据数据集网页提供了以下变量形容表: 变量形容wage每周支出(元)hours每周均匀工作工夫IQ智商分数kww对世界工作的理解得分educ受教育年数exper多年工作教训tenure在现任雇主工作的年数age年龄married=1 如果已婚black=1 如果是黑人south=1 如果住在北方urban=1 如果寓居在都市sibs兄弟姐妹的数量brthord出世程序meduc母亲的教育(年)feduc父亲的教育(年)lwage工资自然对数 wage\`\` 摸索数据与任何新数据集一样,一个好的终点是规范的探索性数据分析。汇总表是简略的第一步。 # 数据集中所有变量的汇总表--包含连续变量和分类变量summary(wage) 因变量(工资)的直方图给出了正当预测应该是什么样子的。 #工资数据的简略柱状图hst(wge$wae, breks = 30) 直方图还可用于大抵理解哪些地方不太可能呈现后果。 # 查看图表 "尾部 "的点的数量sm(wage$ge < 300)<!----> ## [1] 6<!----> sm(wae$wge > 2000)<!----> ## [1] 20简略线性回归因为周工资('wage')是该剖析中的因变量,咱们想摸索其余变量作为预测变量的关系。咱们在数据中看到的工资变动的一种可能的、简略的解释是更聪慧的人赚更多的钱。下图显示了每周工资和 IQ 分数之间的散点图。 gplot(wae, es(iq, wge)) + gom_oint() +gom_smoth() 点击题目查阅往期内容 R语言和STAN,JAGS:用RSTAN,RJAG建设贝叶斯多元线性回归预测选举数据 左右滑动查看更多 01 02 03 04 IQ 分数和工资之间仿佛存在轻微的正线性关系,但仅靠 IQ 并不能牢靠地预测工资。尽管如此,这种关系能够通过拟合一个简略的线性回归来量化,它给出: 工资 i = + ⋅iqi + iwagei = + ⋅iqi + i m_wg_iq = lm(wge ~ iq, dta = age)coefients 工资 i = 116.99 + 8.3 ⋅iqi + iwagei = 116.99 + 8.3 ⋅iqi + i ...

May 19, 2023 · 1 min · jiezi

关于react.js:完结无密最新React-技术栈实战复杂低代码项目仿问卷星

React 技术栈是一套用于构建用户界面的工具汇合,它以 React 框架为外围,并联合了其余技术和库来进步开发效率和优化利用性能。在本文中,咱们将介绍 React 技术栈的几个次要组成部分,并探讨各自的作用和长处。download:https://www.97yrbl.com/t-1630.html React 框架React 是一个由 Facebook 开发的 JavaScript 库,用于构建可重用的 UI 组件。React 的长处之一是其可能以申明式编程形式解决简单的 UI 逻辑,这意味着开发人员只须要关注要渲染的内容,而不用放心底层的 DOM 操作。此外,React 还提供了一些高级性能,如虚构 DOM 和 JSX 语法,以帮忙开发人员疾速构建高效的应用程序。 Redux 状态治理Redux 是一个风行的 JavaScript 库,用于管理应用程序状态。它提供了一个繁多的数据存储区域,称为“store”,开发人员能够应用该存储区域来存储和更新应用程序的状态。Redux 还提供了一个弱小的“中间件”机制,容许开发人员轻松地增加额定的逻辑,例如日志记录、错误处理或异步操作反对。 React Router 路由治理React Router 是一个 React 应用程序中罕用的路由治理库。它提供了一种简略但弱小的形式来解决应用程序中的导航和 URL 门路。React Router 反对嵌套路由,动静路由和代码宰割等性能,使得开发人员能够轻松地构建简单的单页应用程序。 Axios 数据申请Axios 是一个风行的 JavaScript 库,用于在客户端中发送 HTTP 申请。它提供了一种简略而优雅的形式来与服务器进行通信,并反对许多常见的 HTTP 性能,例如拦截器、超时、勾销申请和错误处理。Axios 还与 Promise 和 async/await 等古代 JavaScript 技术集成,使得异步数据申请变得更加容易。 Ant Design UI 组件库Ant Design 是一个风行的 UI 组件库,提供了许多可重用的组件来帮忙开发人员疾速构建好看且高效的用户界面。Ant Design 的组件格调基于谷歌的 Material Design 和苹果的 iOS 设计语言,因而它们具备现代感和易于应用性。Ant Design 还提供了一些高级组件,如表格、表单和图表,以帮忙开发人员更轻松地解决常见的 UI 工作。 ...

May 14, 2023 · 1 min · jiezi

关于react.js:React18Nextjs13TSB端C端完整业务技术双闭环完结无密

React 18 和 Next.js 13 是两个最新版本的前端开发工具,它们提供了许多新性能和改良,使得构建古代 Web 应用程序更加容易。以下是对于 React 18 和 Next.js 13 的一些介绍和个性。download:https://www.666xit.com/3933/ React 18React 18 是 React 框架的最新版本,它提供了一些新的性能和改良,能够帮忙开发人员更加高效地构建用户界面。以下是一些 React 18 的新个性: 自适应渲染模式React 18 引入了自适应渲染模式,它能够依据网络速度和设施性能等因素来决定何时进行渲染。这意味着应用程序能够更快地响应用户操作,并且能够在不同的设施上提供更好的用户体验。加强的服务器渲染React 18 还加强了服务器渲染的性能,使得将 React 应用程序部署到服务器上变得更加容易。此外,React 18 还提供了一些新的 API,如 useTransition、useDeferredValue 等等,能够帮忙开发人员更好地治理状态和组件之间的交互。改良的动画反对 React 18 还改良了对动画的反对,能够帮忙开发人员更加容易地创立晦涩的用户界面。新的 API,如 useTransition 和 useSpring 等等,能够帮忙开发人员更好地治理动画成果,同时进步应用程序的性能。Next.js 13Next.js 13 是 Next.js 框架的最新版本,它也提供了一些新的性能和改良,能够帮忙开发人员更加高效地构建 Web 应用程序。以下是一些 Next.js 13 的新个性: 加强的动态网站生成器Next.js 13 引入了加强的动态网站生成器,能够帮忙开发人员更好地解决动态内容。这意味着开发人员能够更容易地构建动态网站,并将其部署到各种服务器上。自动化性能优化Next.js 13 还提供了自动化性能优化性能,能够帮忙开发人员更好地管理应用程序的性能。Next.js 13 应用了一些新的工具和技术,如 SWR、Optimized Images 等等,能够进步应用程序的性能并缩小加载工夫。改良的开发体验 Next.js 13 还改良了开发体验,使得开发人员能够更加高效地编写代码。例如,Next.js 13 提供了一个新的“Live Preview”性能,能够帮忙开发人员实时预览批改成果。此外,Next.js 13 还提供了更好的 TypeScript 反对和更好的 IDE 集成。总结React 18 和 Next.js 13 是两个最新版本的前端开发工具,它们提供了许多新性能和改良,能够帮忙开发人员更加高效地构建古代 Web 应用程序。如果你是一个前端开发人员,那么倡议学习并把握这些新技术和工具,以便更好地满足用户需要并进步应用程序的性能。 ...

May 12, 2023 · 1 min · jiezi

关于react.js:最新React技术栈实战复杂低代码项目仿问卷星完结江山也要伟人扶

download:最新React技术栈,实战简单低代码我的项目-仿问卷星完结ChatGPT:开启人机交互新时代的AI语言模型 在现代科技疾速倒退的明天,人工智能曾经成为了一个备受关注的话题,而ChatGPT作为一种基于自然语言解决技术的AI语言模型,在人机交互方面扮演着越来越重要的角色。本文将介绍ChatGPT的基础知识、利用场景和将来瞻望等内容。 什么是ChatGPT?ChatGPT是由OpenAI研发的一种基于Transformer架构的大型AI语言模型,它能够实现自然语言生成和了解的工作,从而与人进行高度晦涩的对话。ChatGPT采纳了海量的训练数据和深度学习算法,从而能够一直地优化本身的预测和回复能力,让对话更加天然、灵便和人性化。 ChatGPT的利用场景ChatGPT在人机交互方面有着宽泛的利用场景,例如: 客服机器人:企业能够利用ChatGPT开发客服机器人,帮忙用户解答常见问题、提供服务反对等。智能助手:ChatGPT能够作为智能助手的核心技术,通过自然语言交互来实现日常事务、提供娱乐和学习等服务。语音辨认:ChatGPT能够与语音辨认技术联合,实现语音对话的性能,让人与机器之间的交互更加方便快捷。ChatGPT的将来瞻望随着人工智能技术的一直倒退,ChatGPT的利用前景也越来越广大。将来,咱们能够期待以下几个方面的倒退: 多语种反对:ChatGPT能够拓展到多种语言,让人们在寰球范畴内都可能应用它来进行自然语言交互。跨畛域利用:除了客服和娱乐畛域外,ChatGPT还能够拓展到医疗、金融、教育等各个领域,为人们提供更加全面的服务和反对。更加智能化:将来的ChatGPT将会领有更加智能的预测和回复能力,能够更好地了解人类的情感、语境和需要,让对话更加晦涩和天然。论断ChatGPT作为一种基于自然语言解决技术的AI语言模型,正在逐渐扭转人机交互的形式和状态。通过海量的训练数据和深度学习算法,ChatGPT能够实现高度晦涩、灵便和人性化的对话,为人们提供更加便当和高效的服务和反对。将来,咱们能够期待ChatGPT在多语种反对、跨畛域利用和智能化等方面的一直拓展和翻新。

May 12, 2023 · 1 min · jiezi

关于react.js:使用dumi搭建UI组件库

什么是dumidumi,中文发音嘟米,是一款为组件开发场景而生的文档工具,与 father 一起为开发者提供一站式的组件开发体验,father 负责构建,而 dumi 负责组件开发及组件文档生成。 个性 开箱即用,将注意力集中在组件开发和文档编写上 丰盛的 Markdown 扩大,不止于渲染组件 demo 基于 TypeScript 类型定义,主动生成组件 API 主题轻松自定义,还可创立本人的 Markdown 组件 反对挪动端组件库研发,内置挪动端高清渲染计划 一行命令将组件资产数据化,与上游生产力工具串联环境筹备首先得有node,并确保 node 版本是 10.13 或以上。 $ node -vv10.13.0初始化脚手架创立空文件夹mkdir dumi-ui-site-template 初始化一个站点模式的组价库开发脚手架 $ yarn create @umijs/dumi-lib --site 运行执行 npm run dev 或 npx dumi dev 即可开始调试组件或编写文档。 执行成果如下: 开发一个button组件在src上面创立文件Button文件。 外围代码index.tsx import React, { useState } from 'react';import styled from 'styled-components';import clsx from 'clsx';import * as vars from '../styles/vars';import { isMobile } from '../utils/dom';import { getThemeColorCss } from '../styles/themeHelper';type Props = { /** default 线框,primary 实色框 */ type?: 'default' | 'primary'; /** 线框应用主题色 */ active?: boolean; /** 禁用 */ disabled?: boolean; /** 自定义style */ style?: React.CSSProperties; /** 按钮类型 */ htmlType?: 'submit' | 'reset' | 'button' | undefined; /** 块级按钮 */ block?: boolean; children?: React.ReactNode; /** 自定义className */ className?: string; /** 圆形按钮 */ circle?: boolean; /** 虚线边 */ dashed?: boolean; /** 设置危险按钮 */ danger?: boolean; /** 设置为展现的标签,比方div,a,button */ as?: any; /** 设置按钮的图标组件 */ icon?: React.ReactNode; /** 设置按钮加载状态 */ loading?: boolean; /** 是否幽灵按钮 */ ghost?: boolean; /** 点击回调 */ onClick?: (e: React.SyntheticEvent) => void; /** 点击后,下次能点击的工夫距离,避免反复点击, 如果是true, 距离默认是1s */ wait?: number | boolean;};const StyledButton = styled.button` color: inherit; cursor: pointer; margin: 0; display: inline-flex; box-sizing: border-box; outline: 0; position: relative; align-items: center; user-select: none; vertical-align: middle; justify-content: center; text-decoration: none; background-color: transparent; appearance: none; -webkit-tap-highlight-color: transparent; font-weight: 400; white-space: nowrap; background-image: none; transition: all 0.3s ease; user-select: none; touch-action: manipulation; padding: 4px 16px; font-size: 14px; border-radius: 2px; border: 1px solid transparent; height: 32px; &.default { background-color: #fff; border-color: ${vars.border}; ${isMobile ? '&:active' : '&:hover'} { opacity: 0.8; } &.pc:hover, &.active { ${getThemeColorCss('border-color')} ${getThemeColorCss('color')} } &.mobile:active { background-color: ${vars.activeBg}; } &.danger, &.danger:hover, &.danger:active { color: ${vars.danger}; border-color: ${vars.danger}; } } &.primary { ${getThemeColorCss('background-color')} ${getThemeColorCss('border-color')} color: #fff; ${isMobile ? '&:active' : '&:hover'} { opacity: 0.8; } &.danger, &.danger:hover, &.danger:active { background-color: ${vars.danger}; border-color: ${vars.danger}; } } &.disabled, &.disabled:hover, &.disabled:active { cursor: not-allowed; opacity: 0.6; pointer-events: none; } &.block { width: 100%; } &.circle { min-width: 32px; padding: 0; border-radius: 50%; } &.dashed { border-style: dashed; } &.ghost, &.ghost:hover { color: ${vars.border}; background-color: transparent; border-color: ${vars.border}; } &.anchor { margin: unset; padding: unset; background: unset; border: none; ${getThemeColorCss('color')} height: unset; }`;const Button = React.forwardRef<HTMLButtonElement, Props>((props, ref) => { const { children, type = 'default', disabled, block, active, danger, circle, dashed, loading, ghost, className, htmlType, onClick, wait, ...rest } = props; return ( <StyledButton {...rest} ref={ref} disabled={disabled} type={htmlType} className={clsx( 'uc-btn', type, { disabled: disabled || loading, block: block, danger: danger, circle: circle, dashed: dashed, ghost: ghost, pc: !isMobile, anchor: rest.as === 'a', active, }, className, )} > {children} </StyledButton> );});Button.displayName = 'UC-Button';export default Button;index.md ...

May 8, 2023 · 3 min · jiezi

关于react.js:React列表组件通知列表私信列表虚拟列表

引言最近在做社交网站开发,过程中须要用到三种组件:告诉列表组件、聊天列表组件和虚构列表组件。这三种组件都是社交网站必备的,当初把我在开发中遇到的问题以及代码全副分享给大家,心愿对大家有所帮忙。 告诉列表咱们在应用社交网站的过程中会发现他们通常会应用下拉告诉展示告诉列表数据,这种就是当初要介绍的告诉列表,如图所示: 首先咱们先来介绍下告诉下拉列表的工作原理:1、点击告诉按钮2、查问列表数据并展示3、向下拉滚动条过程中分页加载数据,并把数据合并到列表中,直到数据全副加载完 当初看看咱们如何制作吧。首先,咱们须要应用一个React插件:InfiniteScroll,废话不多说间接上代码: <div id="scrollableDiv" className={styles.noticeBody}> { loading&&page.pageNum === 1? <Loading />:<InfiniteScroll //留神:dataLength={remindList.length}要写remindList.length不能写成remindListTotal,切记! dataLength={remindList.length} next={loadMoreData} height={413} hasMore={remindList.length < remindListTotal} loader={<Loading/>} scrollableTarget="scrollableDiv"> <List split={false} itemLayout="horizontal" dataSource={remindList} renderItem={item => (your list item in here)} /> </InfiniteScroll> } </div>咱们看一下下面的代码,首先咱们要定义一个id=scrollableDiv的div,接着判断如果以后页码是1的话,则显示loading加载组件。 留神: 因为InfiniteScroll组件,默认如果没有数据是不被动触发next对应的loadMoreData获取下一页数据的办法,所以最好咱们关上下拉框的时候就被动去获取列表第一页的数据,在获取过程中咱们能够先用loading成果展现给用户,目标是为了晋升更好的体验,当然你也能够不必加!loading&&page.pageNum === 1? <Loading />当初,来看看这段代码: <InfiniteScroll //留神:dataLength={remindList.length}要写remindList.length不能写成remindListTotal,切记! dataLength={remindList.length} next={loadMoreData} height={413} hasMore={remindList.length < remindListTotal} loader={<Loading/>} scrollableTarget="scrollableDiv"> <List split={false} itemLayout="horizontal" dataSource={remindList} renderItem={item => (your list item in here)} /> </InfiniteScroll>不晓得大家有没有看InfiniteScroll文档下面的代码,如果没有的话,我这里就简略介绍一下,并且把开发过程中遇到的问题给大家点明一下避免入坑。dataLength={remindList.length}示意以后数据长度next={loadMoreData}示意获取下一页数据的办法,它会随着滚动条的滚动主动触发的hasMore={remindList.length < remindListTotal}示意什么时候显示loading成果loader={<Loading/>}示意loading成果组件scrollableTarget示意它是依赖于id=scrollableTarget的div的 留神:1、这里须要留神的是dataLength应该是以后列表的长度,否则滚动条滚动到列表底部的时候不会触发获取下一页数据的办法loadMoreData2、因为下拉列表滚动加载过程中,列表数据源remindList是始终减少的,它是把每页的数据源merge在一起的。私信列表私信列表就比拟非凡了,大家都用过微信,QQ的,它的聊天记录是向上滚动加载,跟咱们的告诉下拉列表刚好相同,庆幸的是InfiniteScroll组件也提供该性能,间接上代码: <div className={styles.chatList} id="scrollableDiv" ref={dom}> <InfiniteScroll //留神:dataLength={remindList.length}要写remindList.length不能写成remindListTotal,切记! dataLength={chatList.length} next={getCurrentData} hasMore={showChatListLoading} loader={<Loading/>} style={{ display: "flex", flexDirection: "column-reverse" }} scrollableTarget="scrollableDiv" inverse={true}> your list item in here </InfiniteScroll> </div>跟之前一样,咱们来剖析下这段代码,因为是滚动条向上滚动加载,所以咱们要把loading搁置在顶部,所以要加上inverse={true},同时还要设置两个款式:款式一、 ...

May 3, 2023 · 2 min · jiezi

关于react.js:ES6-常用语法介绍

咱们先来理解一些ES6语法。好多小伙伴就是不重视根底,感觉这有什么难的,多写点我的项目,记住写法就行了,前面天然就会了。其实这种想法是谬误的,要想代码写法标准,bug少及排错能力强,必须把根底把握牢固。 1、let 与 constES2015(ES6) 新增2个JavaScript 关键字: let 和 const**let 申明的变量只在所在的代码块中失效。举例说明如下: function getShopList() { let shopCount = 10; console.log('shopCount1', shopCount); // 正确打印出10 } getShopList(); console.log('shopCount2', shopCount); // 报错,即 shopCount not defined在控制台打印得:所以,let 申明的变量只在所在的代码块中失效。 const 申明一个只读的常量,一旦申明,常量的值就不能扭转。举例说明如下: function getShopList() { const shopCount = 10; shopCount = 20; // 从新赋值,就会报错 console.log('shopCount', shopCount); } getShopList();在控制台打印得: 反思点:爱动脑筋的小伙伴可能会问,如果用 const 申明初始化一个数组或者对象时,为何能扭转它的值? function getShopList() { const shopCount = [10]; shopCount.push(30); console.log('shopCount', shopCount); } getShopList();在控制台打印得:总结:const 其实保障的不是变量的值不变,而是保障变量指向的内存地址所保留的数据不容许扭转。然而,简略类型和复合类型保留值的形式是不一样的。对于简略类型(数值 number、字符串 string 、布尔值 boolean),它的值就保留在变量指向的那个内存地址,因而 const 申明的简略类型变量等同于常量;而简单类型(对象 object,数组 array,函数 function),变量指向的内存地址其实是保留了一个指向理论数据的指针,指针是能够挪动的,所以变量的值也是能够扭转的。其实下面原理不太了解的小伙伴,也不必太过纠结,咱们只须要记住,罕用的数值和字符串用const申明初始化后,是不能够从新赋值的;而数组和对象用const申明初始化后,容许扭转其值就ok了! ...

May 3, 2023 · 2 min · jiezi

关于react.js:Ant-Design-Pro-环境安装

一、Node下载地址:http://nodejs.cn/download/ 二、验证环境是否装置胜利命令:1、node –v2、npm -v正确输出版本号,表明环境曾经装置胜利。 三、全局装置yarn及配置淘宝镜像:1、npm i -g yarn2、配置淘宝镜像:npm config set registry https://registry.npm.taobao.orgyarn config set registry https://registry.npm.taobao.org3、验证是否胜利:npm config get registryyarn config get registry如果输入 "https://registry.npm.taobao.org",表明淘宝镜像配置胜利。 四、拉我的项目代码命令:1、yarn create umi (留神:必须在一个空文件夹里)2、顺次抉择:ant-design-pro、Pro V4、JavaScript、simple、antd@43、装置依赖包命令:yarn4、yarn start

May 3, 2023 · 1 min · jiezi

关于react.js:Ant-Design-Pro配置

不论是前端框架,还是后端框架,大多数状况下,咱们只想批改一些根本配置后,就能疾速依据本人的业务需要进行开发我的项目。这也是咱们违心应用一些优良框架的起因。 在 Ant Design Pro 中,调整配置的中央不止一处,都有哪些呢?一起来看看吧。 1、defaultSetting.js 配置地位:/config/defaultSetting.js const proSettings = { navTheme: 'dark', // 黎明蓝 primaryColor: '#1890ff', layout: 'side', contentWidth: 'Fluid', fixedHeader: false, fixSiderbar: true, colorWeak: false, menu: { locale: true, }, title: 'Ant Design Pro', pwa: false, iconfontUrl: '',};export default proSettings;navTheme导航的主题,可选值为:'light' | 'dark',其成果别离为: primaryColor主题色,默认为:黎明蓝(#1890ff),咱们能够更换主题色,比方:(#722ED1),其效果图如下:如果咱们想更换其它色彩,请参考 Ant Design 色调。传送门 layoutlayout 的菜单模式,side:右侧导航,top:顶部导航,mix:混合导航,其效果图别离为: contentWidthlayout 的内容模式,Fluid:自适应,Fixed:定宽 1200px,其效果图别离为:留神:contentWidth 只有在 layout:"top" 或者 layout:"mix" 状况下失效 fixedHeader是否固定 header 到顶部,默认为:false fixSiderbar是否固定导航,默认为:false colorWeak是否开启色弱模式,默认为:false。开启后,其效果图如下: menumenu 的配置项,默认 { locale:true } title零碎的左上角 的 零碎名称 ...

May 1, 2023 · 1 min · jiezi

关于react.js:最新React技术栈实战复杂低代码项目仿问卷星

download:最新React技术栈,实战简单低代码我的项目-仿问卷星仿问卷星是指在问卷星的根底上进行二次开发,以满足用户更多的需要和定制化要求。在仿问卷星的实现过程中,须要留神以下几个关键点。 首先,须要对问卷星的组成部分进行剖析。问卷星次要包含问卷设计、问卷公布、问卷填写、问卷统计等模块。在仿问卷星时,须要认真钻研这些模块的交互方式和数据流动逻辑,并依据理论需要进行调整和优化。 其次,须要思考问卷题型的反对。问卷星反对多种不同类型的题目,例如单选、多选、填空、矩阵等。在仿问卷星时,须要确保所抉择的框架和技术可能很好地反对这些题型,并且可能满足用户的需要。 除此之外,还须要思考问卷设计的灵活性和好看度。问卷星提供了很多款式和模板,使得问卷设计能够轻松地实现各种视觉效果。在仿问卷星时,须要针对实际利用场景,提供相应的设计工具和款式库,以满足用户不同的设计需要。 最初,问卷统计是问卷星的一个重要性能。它能够帮忙用户理解问卷答复的状况,例如每个问题的答复比例、均匀分数等。在仿问卷星时,须要思考如何对这些数据进行剖析和展现,并提供相应的可视化统计工具。 总的来说,仿问卷星须要思考的方面十分粗疏和全面,包含问卷设计、题型反对、灵活性和好看度、统计分析等等。只有在这些方面都做到优良,才可能吸引更多的用户,并且满足他们的需要。

April 23, 2023 · 1 min · jiezi

关于react.js:React的渲染原理

React的渲染原理能够用Virtual DOM和Reconciliation两个概念来解释: 1. Virtual DOMVirtual DOM是React用来形容实在DOM树的一个JS对象树,其构造和实在的DOM树是一一对应的,通过Virtual DOM能够不便地操作和治理DOM树,进步了组件的渲染效率。 它的基本原理是在组件状态(state)发生变化时,React不间接操作实在的DOM树,而是先在内存中创立一个新的Virtual DOM树,而后通过比拟新旧Virtual DOM树的差别,只对更新的局部进行对应的DOM操作,这种更新形式也叫做Diff算法,是React在渲染过程中的外围算法。 2. Reconciliation当组件状态发生变化时,React须要调用Reconciliation算法,来决定哪些DOM节点须要更新以及如何更新。它的根本流程是: 比拟新旧Virtual DOM的根节点,判断是否能够复用如果根节点不能复用,则判断它们是否是不同类型的节点如果是不同类型节点,则间接替换如果是雷同类型节点,则依据节点的属性和子节点的内容进行复用或更新在比拟新旧Virtual DOM时,React采纳了一种递归遍历的形式,这也是为什么更新操作不适宜过于频繁的起因,因为递归遍历是一个高耗费的操作。 总的来说,React的渲染原理利用了Virtual DOM和Reconciliation两个外围概念,进步了组件的渲染效率,同时也能保障DOM操作的可靠性和稳定性。

April 22, 2023 · 1 min · jiezi

关于react.js:componentWillUpdate可以直接修改state的值吗

不应该在 componentWillUpdate 生命周期办法中间接批改 state 的值,因为这样做可能导致谬误。 在 componentWillUpdate 生命周期办法中,依然能够拜访以后组件的 state 和 props,然而更改它们的值可能会导致不可预感的后果。这是因为该生命周期办法触发时,组件的状态正在被更新,如果在此时更改状态会导致组件进入有限循环的状态。 如果须要更改状态,倡议应用 setState() 办法,它应该在 componentWillUpdate() 办法调用完结当前,通过 componentDidUpdate() 生命周期办法进行操作,保障不会在以后更新周期中产生副作用。 在 componentDidUpdate 生命周期办法中,能够依据新的 state 和 props 做出响应,并调用 setState() 触发新的更新周期。

April 22, 2023 · 1 min · jiezi

关于react.js:React-setStateuseState同步异步

React setState、useState到底是同步的,还是异步的?setState语法用法1: this.setState({ // 数据更新})用法2: this.setState((state, props) => { // 以后组件的state // 父级的state}, () => { // 数据更新之后})useState语法用法1: const [num, setNum] = useState(0);...setNum(1);用法2: const [num, setNum] = useState(0);...setNum(() => { // 数据操作});setState是同步还是异步?看一下上面的代码: import React from 'react';import { Button } from 'antd-mobile';export default class App extends React.Component { constructor(props) { super(props); this.state = { count: 0 } } onButtonClick() { setTimeout(() => { this.setState({ count: 1 }) console.log('count00000', this.state.count); }) console.log('count111111', this.state.count); setTimeout(() => { console.log('count222222', this.state.count); }) } render() { return ( <div> <Button onClick={this.onButtonClick.bind(this)}>点击</Button> <div> 这个数字就是啊哈哈哈:{this.state.count} </div> </div> ) }}打印后果: ...

April 21, 2023 · 1 min · jiezi

关于react.js:翻译翻译什么叫JSX

前言什么叫JSX?,咱们能够先从 React 官网 的定义窥见一二。其中讲到JSX 能够很好地形容 UI 应该呈现出它应有交互的实质模式,即能够让咱们写 React 组件像在写 HTML 一样。除了相似原生的HTML标签外,咱们还能够自定义本人的组件,进而一步步形成简单的页面。那么在这一过程中React是如何解决JSX的,咱们将在接下来一一拆解,透过景象来开掘背地的实质。 本文源码 feature/jsx ,在scripts中提供了三个命令: ## 须要import React,index.jsyarn dev or npm run dev## 不须要import React,index-jsx-runtime.jsyarn runtime or npm run runtime## 自定义jsx-runtime, index-feact-jsx-runtime.jsyarn feact or npm run feactimport React from 'react'在React17 以前,如果咱们不显式调用import React from 'react' 那么在页面上必定会报如下谬误 当然在咱们刚开始用React的时候,前辈、书里都说过必须在顶部显示import React from 'react',长此以往,咱们都会条件反射式地写上这么一句。可是你有没有想过,为何必须这样做页面才不会报错正告呢?明明我上面都没用到React相干的啊! 而且你还发现,每次你写上import React from 'react',即便发现代码里都没有用到React相干的,然而vscode外面的import React就会高亮,而比照上面的import eslint就是暗色的,并且提醒申明了但没应用 诶,下面提到的两个问题为何那么诡异?上面,让咱们化身福尔摩斯来一一揭秘吧~ React.createElementReact 官网 JSX 示意对象 有一句话:Babel 会把 JSX 转译成一个名为  React.createElement()  函数调用。翻译翻译,就是说咱们写的组件中用到了JSX,那么转译的过程中Babel就会去找React.createElement,将JSX转译为相应的对象。 ...

April 13, 2023 · 4 min · jiezi

关于react.js:翻译翻译什么叫ReactDOMcreateRoot

前言本文源码版本是React 17.0,源码分支为feature/createRoot,剖析的模式是Concurrent(并发)模式,且对一些不太重要的源码进行了删除要想搞清楚React源码,debugger是必不可少的,否则看再多的源码解析,还是只能停留于感性认识,无奈真正倒退到理性认识 入口咱们个别会在我的项目的src/index.ts文件中初始化我的项目,即创立根节点后将App组件渲染到根节点上  import React from 'react'; import ReactDOM from 'react-dom'; function App() { return <div>app</div> }  const root = document.getElementById('root')  // Concurrent mode ReactDOM.createRoot(root).render(<App />);那ReactDOM.createRoot在这一过程到底做了什么呢?怀着好奇心,咱们从ReactDOM.createRoot入口开始debugger,来一探到底 createRoot export function createRoot(container: Container): RootType {   return new ReactDOMRoot(container); }首先天然是来到 createRoot 函数,createRoot接管一个container,即div#root,而其实际上返回的是一个ReactDOMRoot实例 ReactDOMRoot function ReactDOMRoot(container: Container) {   // 这里采纳的是并发模式   this._internalRoot = createRootImpl(container, ConcurrentRoot); }而创立 ReactDOMRoot 实例仅仅是通过createRootImpl创立一个rootContainer,赋值给_internalRoot属性上 这里咱们还留神到下面传入了一个ConcurrentRoot,这里简略介绍一些。 React中的模式有三种模式:  // 传统模式 export const LegacyRoot = 0; // 渐进模式 export const BlockingRoot = 1; // 并发模式 export const ConcurrentRoot = 2;传统模式咱们的写法是: ReactDOM.render(<App />, document.getElementById('root'))本文的模式是Concurrent Mode,其写法是: ReactDOM.createRoot(document.getElementById('root')).render(<App />);BlockingRoot则是一个介于LegacyRoot和ConcurrentRoot之间的过渡模式,这里咱们略过 ...

April 13, 2023 · 3 min · jiezi

关于react.js:Remix-后台桌面electronremixantdadmin

Remix Antd Admin Electron 基于 Electron/Remix/Antd/Echarts/Styled-components 的管理系统,可能疾速初始化我的项目。 我的项目地址electron repo: https://github.com/yyong008/remix-antd-admin-electron Web websit: https://remix-antd-admin.vercel.app/ 以后 Remix 版本1.51.0设计动机Remix 的设计范式简略不便,整个利用就是一个路由器,并且是前后端买通的路由器。表单设计使得 Remix 的表单能力更加简略不便。在后盾管理系统中,数据展现与数据录入,以及页面切换占据重要地位,Remix 设计仿佛特贴的简略贴切。集成 Antd UI 我的项目能力,能疾速实现具备丑陋 UI 简略的后盾管理系统。 Core Packageselectron packagedescremix-electronElectron 集成到 Remix ⚛electron外围包@remix-run/server-runtimeremix 运行时nodemon监听文件自动更新文件减少右面主文件desktop/main.jsconst { initRemix } = require("remix-electron");const { app, BrowserWindow, dialog } = require("electron");const { join } = require("node:path");/** @type {BrowserWindow | undefined} */let win;/** @param {string} url */async function createWindow(url) { win = new BrowserWindow({ show: false }); await win.loadURL(url); win.show(); if (process.env.NODE_ENV === "development") { win.webContents.openDevTools(); }}app.on("ready", async () => { try { if (process.env.NODE_ENV === "development") { const { default: installExtension, REACT_DEVELOPER_TOOLS, } = require("electron-devtools-installer"); await installExtension(REACT_DEVELOPER_TOOLS); } const url = await initRemix({ serverBuild: join(__dirname, "build") }); await createWindow(url); } catch (error) { dialog.showErrorBox("Error", getErrorStack(error)); console.error(error); }});/** @param {unknown} error */function getErrorStack(error) { return error instanceof Error ? error.stack || error.message : String(error);}减少 Remix 配置文件// remix.config.js/** * @type {import('@remix-run/dev/config').AppConfig} */module.exports = { serverBuildPath: "desktop/build/index.js", // ...};减少 nodemon.json{ "$schema": "https://json.schemastore.org/nodemon.json", "exec": "electron", "watch": ["desktop"], "ignore": ["desktop/build"], "execMap": { "ts": "ts-node" }}外围包包阐明remix1.51.0(外围包)antd5.3.1(外围 UI 包)styled-componentscss-in-js 解决方案(外围 css 解决方案)remix-utilsRemix 的 常用工具,例如:仅仅在服务端然组件 <ClientOnly> 组件(外围工具)国际化国际化包阐明remix-i18next很容的形式翻译你的 remix 利用图表库选图表留神反对 ssr ...

April 13, 2023 · 2 min · jiezi

关于react.js:如何在2023年学习React

在2023年学习React并不是一件容易的事件。自2019年React Hooks公布以来,咱们曾经领有了很多稳定性,但当初局势正在再次变动。而这次变动可能比应用React Hooks时更加不稳固。在本文中,我想比拟两种学习React的形式:以库的形式和以框架的形式。 为了让事件更加清晰:React公布了新的文档,并倡议将React用于齐全集成的框架中。文档主张应用一个(元)框架(例如Next.js),而不是将React作为库(或框架 )在像Vite或Parcel这样的打包工具中应用。我对此的认识是,在框架最终成为默认选项之前,依然倡议应用其余React启动工具,而不仅仅是齐全集成的React框架,以使转变更加容易。 技术是个圈谁不晓得这个技术短语是来自讥笑行将到来的不可避免变动的高级开发?没错,咱们发明,学习,适应。始终以来都是这样,这是反馈循环的实质。 开发者也对Web开发的以后状态发表了相似的认识:在大概2000年到2010年,咱们在PHP、Java、C#中,将Web应用程序实现为服务器端应用程序(SSR - 服务端渲染/服务端路由),接着是Ruby on Rails。他们将越来越多的JavaScript(例如jQuery、MooTools、Dojo)混合在一起,以改善客户端的用户体验。 在2010年,局势转向了以客户端为主的应用程序(CSR - 客户端渲染/客户端路由),这是在单页应用程序(SPA)这个总称下的残缺JavaScript解决方案。 第一代:Backbone,Knockout,Ember,Angular第二代:React,Vue二点五代:Svelte第三代:Solid,Qwik现在,许多人将SPA称为Web开发历史上的谬误。 然而,SPA有其存在的意义,而且SPA成为JavaScript(以及起初的TypeScript)作为Web利用框架腾飞的条件,并得出将JavaScript/TypeScript用于SSR的论断,因为底层技术的缺失(例如短少HTTP流)使咱们以前(到目前为止)无奈实现它。 服务端的React总之,这种作为SPA的web应用程序的状态大概继续了10年… 当初圆圈曾经闭合了,因为咱们正在回到应用React和许多其余框架的SSR;每个框架(Vue、Svelte、Solid、Qwik、Angular)都相互影响着。 尽管许多非原生JavaScript开发人员讥笑这种转变是“回到了过来”(参见2000-2010年),或者是“JavaScript在模拟PHP”,然而他们疏忽了与上一个周期相比的所有改良(例如局部/选择性水合、服务端组件作为架构模式、可恢复性)。 JavaScript(更好的说法是TypeScript)是SSR Web应用程序的一等公民。 它将是下一个十年咱们实现Web应用程序的形式... ...在人工智能接管之前(开个玩笑)。 扯远了,咱们来谈谈React以及如何在这些动荡的水域中学习它。 学习作为库的React从公布以来,React曾经作为一个库应用了将近十年。React开发人员始终在应用React与丰盛的生态系统中的许多其余互补库一起应用。React Router就是其中一个受欢迎的库,因为它为React在SPA世界中启用了客户端路由。 大部分React的学习材料都将其作为一个库来传授。新的React文档这样做,最风行的React书籍《The Road to React》也是如此,还有许多其余在线教程、视频和课程。 学习React作为一个库时,你不会被框架分心。你能够齐全专一于学习React的基础知识:元素 vs 组件,React Hooks,自定义Hooks,函数组件,事件处理器,表单,Refs,条件渲染,Props,而后再集成诸如React 测试库或款式组件(或任何其余React款式解决方案)等互补的第三方库。 通常你会应用相似Vite的打包工具来学习React。当打包工具在背地隐没时,你将学习如何应用React创立客户端路由/渲染的SPA。 现在,许多React初学者对学习React作为一个库感到不确定,因为以后的说法通知咱们应该学习框架。尽管我批准将来的趋势是齐全集成的框架,然而专一于学习React的基础知识并不会使你学到谬误的货色。 初学者也不会错过SSR,因为依然有许多应用程序在没有框架的状况下运行。只管SSR将在将来成为支流,但当初还没有达到那一步,你将很幸运地把握如何应用近程REST / GraphQL / tRPC API,来创立客户端应用程序的历史常识。这将是你技术栈中的一项基本技能(特地是与API一起工作)。 学习作为框架的React将来,React将作为一个提供框架所需根本构建块的库而展示。尽管开发人员过来始终可能本人应用React的性能,但随着React作为一个框架走向将来,这种状况将不再存在。 例如,React服务端组件会与路由和数据获取亲密集成。尽管框架将依据React自身提供的明确定义的标准实现这个架构构建块,但日常的React开发人员只会将它们作为框架提供的性能来应用,因为他们不须要本人依据标准来实现它们。 这样做有充沛的理由,因为咱们心愿框架解决细节,而React开发人员能够专一于实现其业务逻辑。 在学习React作为框架时,最好的抉择是学习Next.js。它具备基于文件的路由,许多渲染技术(CSR、SSG、ISR、SSR),其中SSR是一等公民,内置图像、SEO和字体反对。它也尽可能靠近于在框架中应用React,因为它与React在诸如React服务端组件等性能上密切合作。此外,许多React外围开发人员当初正在为Vercel工作,Vercel是Next.js背地的公司。 倡议学习React作为库或框架不用是一个排他性的决定。以下是我给React初学者的倡议: 在学习React作为框架的同时,不要疏忽它作为库的基础知识。例如,你能够从框架开始学习React。最有可能的是,你会首先应用像Next这样的框架实现页面之间的路由转换。这个个性齐全由框架提供,而不是React自身。然而,一旦你接触到React的基础知识,比方Hooks,回到React作为库的基础知识总是一个好的能源。 2023年学习React的一种办法:在实现一个你感兴趣的畛域的应用程序(例如体育、动漫、游戏、电子商务、生产力、音乐)时,同时应用React和Next的文档。 你能够从Next的文档开始。然而每当你接触到React的基础知识时,回到React的文档中。重点关注两个实体(框架和库)的交汇处以及它们提供给你的工具。 如果你想通过补充学习资源来学习React的基础知识,请查看课程、视频或书籍。这些资源可能会为React作为库及其基础知识提供不同的视角。 以上就是本文的全部内容,如果对你有所帮忙,欢送点赞、珍藏、转发~

April 12, 2023 · 1 min · jiezi

关于react.js:Remix-后台remixantdadmin

Remix Antd Admin 一款基于 Remix / Antd / Echarts / Styled-components 的管理系统,可疾速进行我的项目初始化。(本我的项目偏前端) Project experience URLhttps://remix-antd-admin.vercel.app/ 我的项目仓库地址:https://github.com/yyong008/remix-antd-admin Current Remix Version1.51.0设计动机Remix 的设计范式简略不便,整个利用就是一个路由器,并且是前后端买通的路由器。表单设计使得 Remix 的表单能力更加简略不便。在后盾管理系统中,数据展现与数据录入,以及页面切换占据重要地位,Remix 设计仿佛特贴的简略贴切。集成 Antd UI 我的项目能力,能疾速实现具备丑陋 UI 简略的后盾管理系统。 外围包包阐明remix1.51.0(外围包)antd5.3.1(外围 UI 包)styled-componentscss-in-js 解决方案(外围 css 解决方案)remix-utilsRemix 的 常用工具,例如:仅仅在服务端然组件 <ClientOnly> 组件(外围工具)国际化国际化包阐明remix-i18next很容的形式翻译你的 remix 利用i18next-react-i18next-i18next-browser-languagedetector-图表库选图表留神反对 ssr 图表库阐明echarts5.3.9 次要图表(思考 Remix 须要服务端渲染等问题)echarts-for-react基于 React 封装 echarts 组件react-mindReact 脑图react-mindmapReact 脑图react-wordcloudReact 云词图 反对 ssrreactflow流程图echarts-liquidfill-ssr水滴图裁剪工具react-advanced-cropperpnpm install react-advanced-cropperRemix 长处简单明了的路由书写范式,简略的数据获取和表单能力 弱小的文件路由范式loader 获取数据action 解决表单数据用法应用 pnpm # 服务器pnpm run dev # pnpm dev# 构建pnpm run build # pnpm build# 开发环境服务器pnpm run start # pnpm start格式化工具"scripts": { "prettier": "prettier --write app/ public/locales"},反对目前作者长期处于爱发电的状态,如果本我的项目可能帮忙到你无妨请作者喝一杯咖啡,有你的反对,开源我的项目将失去更好的保护,也崔进输入更加高质量的代码,当然也能够参加到此我的项目中成为我的项目的参与者,同时冀望提出宝贵意见以便我的项目能失去更好的保护和倒退。 ...

April 11, 2023 · 1 min · jiezi

关于react.js:Remix-写-API-接口

Remix 是一个全栈框架,能写 api 接口的能必定是具备的,而且 Remix 尽管定义为全栈框架,此文章次要摸索如何接口。 本文内容Remix 中 api 的书写形式Remix 中 RESTful api 的属性形式类 MVC 分层接口如何写 Remix解决上传示例接口品种一般 get/post api:即可满足根本RESTful API:有标准, 须要协同的graphql:可管制须要的字段的,良好的跨端其中如果是一些小我的项目,没有必要规则化的我的项目,应用 get/post 解决就曾经足够了,如果我的项目有了很多的人要保护,并且有了肯定的规模,为了方便管理,能够应用 RESTful API 的形式解决。graphql API 手动能力最强。 RESTful API 特点创立:POST /api/resources读取:GET /api/resources/:id更新:PUT /api/resources/:id删除:DELETE /api/resources/:id其中,:id 示意资源的惟一标识符。 Remix 中如何解决 api 特点loader 解决 get 申请action 解决非 get 申请Loader 函数解决 Get 申请export const loader = () => { return json({ get: 'loader get' })}action 解决非 GET 办法import { json } from "@remix-run/node";const handleNotGetRequest = function ({ request }) { const method = request.method; switch (method) { case "POST": return json({ code: 0, method: "POST", message: "增加胜利" }); case "PUT": return json({ ok: true, code: 1, method: "PUT", message: "批改胜利" }); case "DELETE": return json({ ok: true, code: 1, method: "PUT", message: "删除胜利" }); default: break; }};// 非 getexport const action = ({ request }) => { return handleNotGetRequest({ request });};// getexport const loader = ({ request }) => { return json({ a: 1, });};增加管制层和服务层为了代码更加好保护,有构造的代码时必要的,代码分层占据重要地位。 ...

April 11, 2023 · 2 min · jiezi

关于react.js:Remix-路由模块输出对象-loader

Remix loader 函数是一个获取以后页面页面数据的函数,常常与 useLoaderData 一起配合应用 以后 Remix 版本:1.15.0次要内容定义形式loader 与 useLoaderData 应用返回值类型以及应用办法参数/上下文重定向错误处理laoder 操作纯 api 输入数据应用loader 函数定义Remix Route 中定义 loader 函数export 对外裸露返回 json/defer/ new Response 实例等常常与 ORM/ODM 进行交互,从数据库获取数据。 loader 函数配合 useLoaderData 一起应用import { json } from "@remix-run/node"; // or cloudflare/denoexport const loader = async () => { return json({ ok: true });};export default function Users() { const data = useLoaderData(); return ( <>{JSON.stringly(data)}</> );}loader 函数返回值json 个别是同步数据,json 函数能够指定两个参数,第一个是 指标数据,第二个是 http 状态export const loader = () => { json({jsonKey: "jsonValue"})}export const loader = () => { json({jsonKey: "jsonValue"}, { status: 200, headers: { "Cache-Control": "no-store" } })}defer 容许返回一个 promise, 个别配合 Await 组件应用json 数据个别是返回一个同步 json 对象,然而 defer 容许咱们返回值能够是一个 promise ...

April 11, 2023 · 2 min · jiezi

关于react.js:Remix-路由模块输出对象-handle

Remix handle 函数是一个有用的对外输入的 Route 模块对象,用于裸露特定的数据 match 对象,它们常常在一起应用。 以后 Remix 版本:1.15.0在哪里能够定义 handle?root 根组件路由页面在根路由定义import { /.../ } from "@remix-run/react";// 根路由 handle 配合页面中 useMatches 获取到 app 数据export const handle = { app: 1}export default function App() { return ( <html lang="en"> // ... </html> );在页面 _index 路由中与 useMatch 一起handle 与 useMatch 一起应用, useMatch 返回路由匹配相干的对象: import type { V2_MetaFunction } from "@remix-run/node";// hooksimport { useMatches } from "@remix-run/react";export const meta: V2_MetaFunction = () => { return [{ title: "New Remix App" }];};// 输入定义 handle 对象export const handle = { test: 1,}export default function Index() { const match = useMatches() console.log(match[1].test) // 在 match 中拜访 match 函数 return ( <div> <h1>Welcome to Remix</h1> </div> );}match 数组match 是一个数组, 数组中的对象数据结构: ...

April 11, 2023 · 1 min · jiezi

关于react.js:Remix-1150-变化为-v2-预准备

Remix 自我介绍Build Better Websites. Create modern, resilient user experiences with web fundamentals.Remix 1.15.0 公布日期2023-04-01更新目录更新文章: 为 v2 预筹备文件系统路由约定元路由发生变化谬误边界发生变化钩子函数: usetransition、useFetcher 属性变量展平formMethod 的办法大小写更改route 模块的 link/links 产生了变动构建目录命名发生变化服务端构建产生了变动同时在开发服务器中开始UI调用 css 相干库开始反对 css modules, 提取, tailwind 反对, postcss 反对。remix 开发版分支开发版文档分支Github dev 分支创立 Remix 配置文件变动/** @type {import('@remix-run/dev').AppConfig} */module.exports = { ignoredRouteFiles: ["**/.*"], // appDirectory: "app", // assetsBuildDirectory: "public/build", // serverBuildPath: "build/index.js", // publicPath: "/build/", future: { v2_errorBoundary: true, v2_meta: true, v2_normalizeFormMethod: true, v2_routeConvention: true, },};future 中更: 配置阐明errorBoundary新的谬误边界meta新的 meta 解决形式normalizeFormMethod一般的 Form 办法routeConvention路由转换(新的路由转换)路由约定新版的路由约定,应用 点路由宰割符号 的形式,不在反对文件夹嵌套的模式。index 文件路由改为 _index 路由,布局路由应用 _ 开始的前缀代替__双下划线开始的前缀路由布局路由。 ...

April 11, 2023 · 1 min · jiezi

关于react.js:ReactNative-项目工作总结

图片 Image官网文档图片引入 // 本地图片<Image source={require('./assets/xxx.png')}/>// 网络图片<Image source={{uri: 'https://xxx.png'}}/>图片的尺寸 // 本地图片const {height, width} = Image.resolveAssetSource(require('./assets/xxx.png'));// 网络图片Image.getSize('https://xxx.png',(width, height)=>{ });

April 11, 2023 · 1 min · jiezi

关于react.js:Vue3-React18-TS4-入门到实战蛟龙生气尽不若鼠横行

download:Vue3 + React18 + TS4 入门到实战PHP是一种风行的开源脚本语言,次要用于Web开发。它的特点是简略易学、功能强大、灵活性高,同时也具备宽泛的利用和社区反对。在本文中,咱们将深入探讨PHP语言的一些基本知识和利用。 1.根本语法 PHP语言的根本语法相似于C语言,具备一些非凡的关键字和语法结构。例如,以下是一个简略的PHP程序: phpCopy code<?php echo "Hello, World!"; ?>在这个例子中,<?php和?>是PHP的标记,用于将PHP代码嵌入到HTML页面中。echo语句用于将一条音讯输入到浏览器窗口。 2.面向对象编程 PHP语言在语言级别提供了面向对象编程的反对,它具备类、对象、继承、多态等个性。例如,以下是一个简略的PHP类: phpCopy code<?php class Person { private $name; private $age; public function __construct($name, $age) { $this->name = $name; $this->age = $age; } public function getName() { return $this->name; } public function getAge() { return $this->age; } } ?>在这个例子中,Person类示意一个人,它具备$name和$age两个公有属性,以及构造函数和两个公共办法getName和getAge。 3.数据库编程 PHP语言在数据库编程方面具备丰盛的反对,它能够连贯各种数据库,并提供了一些罕用的API和扩大库。例如,以下是一个简略的应用MySQL数据库的程序: phpCopy code<?php $servername = "localhost"; $username = "username"; $password = "password"; $dbname = "myDB"; // 创立连贯 $conn = new mysqli($servername, $username, $password, $dbname); // 检测连贯 if ($conn->connect_error) { die("Connection failed: " . $conn->connect_error); } // 查问数据 $sql = "SELECT id, firstname, lastname FROM MyGuests"; $result = $conn->query($sql); if ($result->num_rows > 0) { // 输入每行数据 while($row = $result->fetch_assoc()) { echo "id: " . $row["id"]. " - Name: " . $row["firstname"]. " " . $row["lastname"]. "<br>"; } } else { echo "0 results"; } // 敞开连贯 $conn->close(); ?>在这个例子中,mysqli类用于连贯MySQL数据库,$sql变量用于执行查问语句,并通过$result对象获取后果集。通过循环遍历后果集中的每行数据,并将其输入到浏览器窗口。 ...

April 10, 2023 · 1 min · jiezi

关于react.js:Remix是个啥混音不是一个很新的全栈式前端框架上

想不到吧,我还会前端框架,还是类比next.js的框架。这个也算机缘巧合,为了晋升工作效率,保护了一个共事基于remix开发的小工具。感觉还挺好玩的,就想着联合官网文档写个初入门文章(重点是共事交接给我后,不给我文档,只能去看官网文档)。 重点还是和之前的mermaid一样,次要跟大家讲下有这个货色,如果讲得不正确以官网为主。 什么是RemixRemix is a full stack web framework that lets you focus on the user interface and work back through web standards to deliver a fast, slick, and resilient user experience. People are gonna love using your stuff.老套路,一句话总结,就是全栈式的前台框架,而后再提前剧透下,因为在援用里是没有写的,remix还应用了Prisma,一个号称下一代Node.js和TypeScript的ORM数据库。 官网举荐的环境前提: Node.js version (^14.17.0, or >=16.0.0)npm 7 or greaterA code editor (VSCode is a nice one)好,先疾速搭建一个helloworld工程 npx create-remix@latest --template remix-run/indie-stack blog-tutorial之后按需抉择,比方工程的目录名需不需要自定义,整体语言应用js还是ts,最初一步需不需要帮你运行npm install。最初这个我选的是否,因为我想用pnpm。 最初在运行前记得吧工程目录下.env.example 文件改名为.env ,否则会始终报短少环境变量的错,就算应用npx prisma migrate deploy 也不行。最初关上localhost:3000 ,呈现一下界面即为胜利 ...

April 7, 2023 · 3 min · jiezi

关于react.js:React18Nextjs13TSB端C端完整业务技术双闭环羊求结伴意欣然

download:React18+Next.js13+TS,B端+C端残缺业务+技术双闭环摘要CDN的全称是(Content Delivery Network),即内容散发网络。其目标是通过在现有的Internet中减少一层新的CACHE(缓存)层,将网站的内容公布到最靠近用户的网络”边缘“的节点,运用户可能就近取得所需的内容,提高用户拜访网站的响应速度。从技术上全面解决因为网络带宽小、用户访问量大、网点分布不均等原因,提高用户拜访网站的响应速度。简略的说,CDN的工作原理就是将您源站的资源缓存到位于寰球各地的CDN节点上,用户请求资源时,就近返回节点上缓存的资源,而不需要每个用户的请求都回您的源站获取,防止网络拥塞、缓解源站压力,保障用户拜访资源的速度和体验。 一、CDN减速原理 的解析记录,DNS调度零碎将为其调配最佳节点IP地址。Local DNS获取DNS调度零碎返回的最佳节点IP地址。Local DNS将最佳节点IP地址返回给用户,用户获取到最佳节点IP地址。用户向最佳节点IP地址发动对该资源的拜访请求。如果该最佳节点已缓存该资源,则会将请求的资源间接返回给用户(步骤8),此时请求结束。如果该最佳节点未缓存该资源或者缓存的资源已经生效,则节点将会向源站发动对该资源的请求。获取源站资源后拆散用户自定义配置的缓存策略,将资源缓存到CDN节点并返回给用户(步骤8),此时请求结束。二、CDN的利用场景和作用CDN的利用场景如下表所示。可使用CDN减速的站点次要包含媒体站点、网页站点和下载站点,下表列出了每个站点实用的场景。 实用于网站或利用中小文件的减速散发,例如各种门户网站、电子商务类网站、新闻资讯类网站或利用、娱乐游戏类网站等。 大文件 实用于各类大文件的下载和散发减速,例如游戏安装包、利用更新、手机ROM升级、利用程序包下载等,平均单个文件大小在20 MB以上。 频音点播 实用于各类视音频网站,例如影视类视频网站、在线教育类视频网站、新闻类视频网站、短视频社交类网站以及音频类相干网站和利用,反对MP4、FLV等支流视频格式。 图片小文件 图片小文件实用于网站或利用中小文件的减速散发,例如各种门户网站、电子商务类网站、新闻资讯类网站、娱乐游戏类网站等。您需要将源站内容进行动动态分离,动态内容使用CDN减速,例如图片、CSS、JS小文件等; CDN减速图片小文件业务可能帮您解决以下问题: 终端用户拜访慢:网站小文件内容多、打开速度太慢。跨区域拜访品质差:终端用户分布在不同区域,不同区域的访问速度和品质高低不一。高并发压力大:经营推广期间,源站服务器压力大,服务器容易崩溃,造成服务不可用。图片格式分辨率处理简单:无奈根据适合的终端情况进行图片压缩和优化。大文件下载 大文件下载实用于各类大文件的下载和散发减速,例如游戏安装包、利用更新、手机ROM升级、利用程序包下载等,平均单个文件大小在20 MB以上。 CDN减速大文件下载业务可能帮您解决以下问题: 终端用户无奈下载或者下载太慢。网络环境不稳固时,下载容易中断,从新下载会耗费额定的资源。网站内容不安全,容易被劫持或者盗链,对业务造成额定的损失。高并发下载或者下载突增场景下对源站性能申请非常高,且源站的带宽成本也较高。视音频点播 视音频点播实用于各类视音频网站,例如影视类视频网站、在线教育类视频网站、新闻类视频网站、短视频社交类网站以及音频类相干网站和利用,您可能使用CDN产品实现对音视频内容的文件散发和拜访减速。 CDN减速视音频点播业务可能帮您解决以下问题: 终端用户拜访视频时打不开视频或容易卡顿,观看不流畅。视频资源容易被劫持或盗用,版权得不到无效保护。高并发拜访或者拜访突增场景下对源站性能申请非常高,且源站的带宽成本也较高。使用CDN可能帮您实现动态资源的减速和散发,提高资源访问速度: 丰富的资源节点:为用户提供就近接入的同运营商CDN节点,解决长距离接入和跨运营商拜访带来的提早高和速度慢的问题。资源可弹性扩大:基于寰球2800+节点,资源可弹性扩大,实现业务高可用。精准的调度零碎:实时获取CDN节点的健康状况,并根据用户所在位置和运营商来调配最佳接入节点,以便获得最佳接入成果。智能的传输链路:通过协定优化、连接优化等措施来升高总体时延、提高传输速度,特地是提高弱网环境下的传输速度。高效的缓存策略:能够带来更高的缓存命中率,命中就近节点上的近程资源,提供高效地访问速度。升高您的IT成本:可将您的业务算力、带宽、连接数转移到CDN边缘节点,升高您的IT成本。弱小的带宽输入能力:全网带宽输入能力达150 Tbps。提供行业通用标准API:提高易用性和适用性。三、CDN的零碎架构CDN的产品架构图,由调度零碎、链路品质零碎、缓存零碎和撑持零碎这四大零碎组成。 CDN的产品架构图说明 调度零碎:反对策略核心、DNS、HTTPDNS和302调度模式。当终端用户发动拜访请求时,用户的拜访请求会先进行域名DNS解析,而后通过CDN的调度零碎处理用户的解析请求。链路品质零碎:链路品质探测系统会实时监测缓存零碎中的所有节点和链路的实时负载以及健康状况,并将后果反馈给调度零碎,调度零碎根据用户请求中携带的IP地址解析用户的运营商和区域归属,而后综合链路品质信息为用户调配一个最佳接入节点。缓存零碎:用户通过收到的最佳接入节点拜访对应的缓存节点,如果节点已经缓存了用户请求的资源,会间接将资源返回给用户;如果L1(边缘节点)和L2(汇聚节点)节点都没有缓存用户请求的资源,此时会返回源站去获取资源并缓存到缓存零碎,供后续用户拜访,避免重复回源。分级缓存的部署架构可提高内容散发效率、升高回源带宽以及晋升用户体验。撑持服务零碎撑持服务零碎包含天眼、数据智能和配置管理系统,别离具备了资源监测、数据分析和配置管理能力。资源监测:天眼可能对缓存零碎上用户业务运行的状态进行监测。例如对CDN减速域名的QPS、带宽、HTTP状态码等常见指标的监控。数据分析:用户可能分析CDN减速域名的TOP URL、PV、UV等数据。配置管理:通过配置管理系统,用户可能配置缓存文件类型、缓存时去参数缓存等缓存规定,以晋升缓存零碎的运作效率。3.2 CDN网络的基础概念源站,指您运行业务的网站服务器,是减速散发数据的起源。源站可用来处理和响应用户请求,当边缘节点没有缓存用户请求的内容时,节点会返回源站获取资源数据并返回给用户。CDN的源站可能是对象存储OSS、函数计算、自有源站(IP、源站域名)。 边缘节点是CDN用于缓存源站资源,以便疾速响应不同地区用户请求的网络节点。在CDN的帮助文档中,边缘节点、CDN节点、Cache节点、缓存节点、减速节点、节点等都指CDN的边缘节点。 减速域名,是您接入CDN用于减速、终端用户实际拜访的域名。例如,您将域名aliyundoc.com接入DN,aliyundoc.com即为减速域名。 CDN通过减速域名,将源站资源缓存到CDN减速节点,实现资源拜访减速。在DN的帮助文档中,减速域名通常被简写为域名。域名(Domain Name)又称网域,是由一串用点分隔的名字组成的Internet上某一台计算机或计算机组的名称,用于在数据传输时标识计算机的电子方位(有时也指地理地位)。 CNAME(Canonical Name)记录,指域名解析中的别名记录,用来把一个域名解析到另一个域名(CNAME域名),再由CNAME域名来解析到需要拜访的服务器IP地址。 CNAME域名,是CDN生成的,当您在CDN控制台增加减速域名后,零碎会为减速域名调配一个.kunlun*.com形式的CNAME域名。说明 CDN产品通过分布广泛的CDN边缘节点来为最终用户提供减速服务,不同区域或者不同运营商的用户拜访到的CDN节点IP地址是不同的,因此减速域名就无奈通过DNS的A记录解析的形式唯一解析到某个IP地址,这个时候就引入了CNAME域名。增加减速域名后,您需要在您的DNS解析服务商处,增加一条CNAME记录,将减速域名唯一解析到CNAME域名,记录失效后域名解析就正式转向CDN服务,该域名所有的请求都将转向CDN的边缘节点,达到减速成果。CNAME域名将会解析到具体哪个CDN节点IP地址,将由CDN的调度零碎来综合区域、运营商、节点资源水位等多个条件来决定。 动态内容是指用户多次请求某一资源,响应返回的数据都是雷同的内容。例如图片、视频、网站中的文件(HTML、CSS、JS)、软件安装包、APK文件、压缩包文件等。CDN通过减速域名将源站的动态资源缓存到CDN遍布寰球的减速节点上,供用户就近拜访,实现资源拜访减速。 动静内容是指用户多次请求某一资源,响应返回的数据可能是不同的内容。例如网站中的文件(ASP、JSP、PHP、PERL、CGI)、API接口、数据库交互请求等。 DNS(Domain Name System)即域名解析服务,次要功能是将域名解析为网络可能识别的IP地址,即域名解析。人们习惯记忆域名,但机器间互相只识别IP地址。域名解析需要由顺便的DNS服务器来实现,整个过程主动进行。例如,您上网时输出域名aliyundoc.com会主动转换成10.10.10.10(举例说明,具体IP以实际为准)。 SSL(Secure Sockets Layer)即安全套接字协定,SSL协定位于TCP/IP协定与各种应用层协定之间,可能无效辅助Internet上的应用软件晋升通信时的资料完好性及安全性。IETF将SSL规范化后名称被改为TLS(Transport Layer Security),即传输层安全协定,因此通常将两者并称为SSL/TLS。 当用户通过阅读器发送请求时,如果CDN节点未缓存请求的资源或缓存资源已到期,此时会回源站获取资源并返回给用户,该过程被称为回源。 回源HOST,即CDN节点回源时实际请求的域名。当源站服务器上提供多个域名服务时,您可根据业务需要指定CDN节点回源时在拜访的具体域名。例如,您期望CDN回源时实际请求的地址为aliyundoc.com,与减速域名www.aliyundoc.com不同,那么您需要配置回源HOST为aliyundoc.com。 回源协定,指CDN节点回源时使用的协定,有可能与客户端拜访资源时使用的协定雷同,也有可能不雷同。例如,当客户端使用HTTPS形式请求未缓存在CDN节点上的资源时,可能配置CDN节点使用HTTPS协定回源站获取资源,也可能配置使用HTTP协定回源(源站不反对HTTPS协定的情况下)。 SNI(Server Name Indication)是对SSL/TLS协定的扩大,可用来解决一个HTTPS服务器(同一个IP地址)具备多个域名,然而无奈必定客户端到底请求的是哪一个域名的服务的问题。 当您的源站IP绑定了多个域名,且CDN回源协定为HTTPS时,可通过配置回源SNI,来指明客户端从哪个域名获取资源,服务器会根据配置的SNI信息返回正确的证书给客户端。 Range回源,指CDN节点在回源的HTTP请求外面携带了Range信息,源站在收到CDN节点的回源请求时,根据HTTP请求头中的Range信息返回指定范畴的内容数据给CDN节点,例如只返回某个文件的0-100Byte范畴内的数据。 在视频点播、软件下载等大文件内容散发场景下,Range回源可无效提高文件散发效率,可能提高缓存命中率,缩小回源流量消耗和源站压力,并且晋升资源响应速度。说明 Range是HTTP请求头之一,可用来指定需获取的内容的范畴。 回源302追随,指CDN节点代替客户端间接处理源站响应的302状态码的内容,可缩小处理流程,放慢获取资源的速度。 Referer防盗链,是基于HTTP请求头中Referer字段(例如,Referer黑白名单)来设置访问控制规定,实现对访客的身份识别和过滤,防止网站资源被非法盗用。配置Referer黑白名单后,CDN会根据名单识别请求身份,容许或拒绝拜访请求。说明 Referer是HTTP请求头的一部分,携带了HTTP请求的起源地址信息(协定+域名+查问参数),可用于识别请求的起源。 带宽封顶,指通过设置带宽下限,来管制带宽用量,缩小因突发流量导致的损失。当指定减速域名在统计周期(1分钟)内产生的平均带宽超出预设下限,CDN将停止为该域名提供减速服务,且该域名会主动下线,并被解析到有效地址offline.*.com,无奈被持续拜访。 缓存过期工夫,指资源在CDN节点上缓存的时长。资源过期后会主动从CDN节点删除,用户向CDN节点发动的拜访请求会被判定为未命中缓存,CDN节点会主动回源站获取最新资源返回给用户,并缓存到CDN节点。 跨域资源共享(CORS),是一种基于HTTP头的访问控制机制,容许Web服务器申明哪些源站(指定的域名、协定、端口)有权限通过阅读器拜访指定资源。 边缘脚本(EdgeScript,简称ES)是一个可供您疾速实现CDN/DCDN定制配置的工具箱,当CDN/DCDN管制台上的标准配置无奈满足您的业务需要时,可能使用边缘脚本通过简略地编程实现定制化业务需要。 边缘程序(EdgeRoutine,简称ER)是一个运行在寰球边缘节点上的JavaScript代码运行环境,反对ES6语法和标准的Web Service Worker API。您可能将自行开发的JavaScript代码公布至寰球边缘程序运行,在寰球边缘节点上就近地处理客户端的请求。 ...

April 4, 2023 · 1 min · jiezi

关于react.js:React18Nextjs13TSB端C端完整业务技术双闭环无mi愁云低锁衡阳路

React 18与Next.js 13以及TypeScript的联合,能够带来很多长处和益处。上面咱们将对这些技术进行介绍和探讨。 download : https://www.sisuoit.com/3828.html React 18React 18是React库的最新版本,其引入了很多新个性和改良,其中最重要的是新的渲染器(React Server Components)。这个新的渲染器能够让React利用在服务器端进行渲染,从而进步了利用的性能和SEO。 此外,React 18还引入了一些新的API,比方useTransition和useDeferredValue,这些API能够帮忙开发者更好地解决异步渲染和交互。React 18还反对在开发者工具中进行的性能跟踪和调试,让开发者能够更好地优化利用性能。 Next.js 13Next.js是一款React框架,它提供了很多有用的性能,比方服务器端渲染、动态网站生成、自动化代码宰割、按需加载等等。Next.js 13是Next.js的最新版本,它带来了很多新个性和改良,其中最重要的是自动化预取和缓存(Automatic Prefetching and Caching)。 自动化预取和缓存是一种技术,能够依据用户的行为和拜访模式来预测用户可能要拜访的页面,并在用户拜访之前提前加载和缓存这些页面,从而进步用户体验和网站性能。Next.js 13还引入了一些新的API,比方useRouter和useSession,这些API能够帮忙开发者更好地解决路由和用户会话。 TypeScriptTypeScript是一种由微软开发的动态类型查看器,它能够在编译期间查看代码中的类型谬误和其余常见谬误,从而进步代码的可靠性和可维护性。在React和Next.js中应用TypeScript能够让开发者更好地治理利用的状态和组件,防止很多常见的谬误和Bug。 此外,TypeScript还能够提供更好的代码提醒和文档,让开发者能够更快地编写和了解代码。在React和Next.js中应用TypeScript也能够帮忙开发者更好地合作,因为能够分明地定义和束缚接口和API。 论断React 18与Next.js 13以及TypeScript的联合能够带来很多长处和益处,比方更好的性能、更好的用户体验、更好的可维护性和更好的协作性。如果你正在开发React利用或Next.js利用,并且心愿进步利用的品质和效率,那么你应该思考应用React 18、Next.js 13和TypeScript。

March 31, 2023 · 1 min · jiezi

关于react.js:ReactPureComponent深入了解机制及其原理

起因用React.PureComponent时,更新state外面的count用的形式是++this.state.count,然而意外的导致组件没有从新render(自己用Hook组件较多,所以感到很纳闷) import React from 'react';import { Button } from 'antd-mobile';class DemoChildClass extends React.PureComponent { constructor(props) { super(props); this.state = { num: 1 } } addNum = () => { this.setState({ num: ++this.state.num }, () => { console.log('fffgggghhhh1111', this.state.num) }) console.log('fffgggghhhh222', this.state.num) } render() { const { num } = this.state; return ( <div className='demo-child'> 这是儿子,这个数字就是{num},hhhh< br /> <Button onClick={this.addNum}>子++++</Button> </div> ) }}export default DemoChildClass;打印后果如下: 一开始是没有加两个console.log的,所以依照惯识,认为代码没问题,逻辑没问题,然而预期是谬误的。 于是,更改一下setstate形式,如下: addNum = () => { let { num } = this.state; this.setState({ num: ++num }) }发现他喵的render了?WHF???为什么? ...

March 31, 2023 · 2 min · jiezi

关于react.js:Bread-面包屑

定义面包屑list,每次push以后页面,push前校验是否为第一层级,第一层级革除list单页面路由需监听页面刷新,缓存listimport React, { useContext, useEffect, useState } from 'react';import classNames from 'classnames';import { withRouter } from 'react-router-dom';import { useLastLocation } from 'react-router-last-location';import { findIndex } from 'lodash';import { Breadcrumb } from '@huohua/luca';import NativePageJump from '@utils/nativePageJump';import RouterContext from '@components/Context/RouterContext';import './style.less';// 历史记录let PRE_LIST = [];// 通过name找到记录const getBreadcrumbName = ({ routes, location }) => { return routes.filter(f => { // 存在动静参数 if ( f?.action?.indexOf(':') !== -1 && f?.action?.split('/')?.length === location?.pathname?.split('/')?.length && location?.pathname?.startsWith(f?.action?.split(':')?.[0]) ) { return f; } return f?.action === location?.pathname; })?.[0];};// 获取面包屑记录function getBreadcrumb({ routes, location, cache, rootPages }) { if (location) { const cacheUrl = `${location?.pathname}${location?.search}`; const route = getBreadcrumbName({ routes, location }); // 如果以后是二级目录,须要将一级目录手动导入 if (rootPages?.find(item => item?.id === route?.id)) { const parent = routes?.find(item => item.id === route?.pid); parent && cache.push({ path: parent?.action, name: parent?.title, }); } cache.push({ path: cacheUrl, name: route?.title, }); return cache; } return [];}interface BreadRoutes { name: string; path: string;}/** * 面包屑 * @constructor * 面包屑list 历史路由 + 以后路由 * 需鉴定页面刷新,存储历史路由 * 根目录判断依靠于星云菜单配置 二级菜单为页面跳转 * todo 一级目录 未对应间接页面,点击不可跳转 pid为0 * 二级目录 为第一层页面 */const Bread = ({ routes, location }) => { // 获取最初一个地址 - 上个页面地址 const lastLocation: any = useLastLocation(); const router: any = useContext(RouterContext); // 二级目录 const [rootPages, setRootPages] = useState<any[]>([]); // 面包屑记录 const [breadRoutes, setBreadRouts] = useState<BreadRoutes[]>([]); useEffect(() => { if (!routes?.length) return; // 二级目录 const packageRoute = routes?.filter(item => item?.pid === 0 && item?.display); // 根目录 -- 星云返回的二级目录 let _rootPages = []; packageRoute?.map(item => { const list = routes?.filter(it => it?.pid === item?.id); _rootPages = _rootPages.concat(list); }); setRootPages(_rootPages); }, [routes]); // 监听事件处理 const listenReload = () => { // 设置刷新字段 window.sessionStorage.setItem('BREAD_PAGE_LOAD', '1'); // 存储历史记录(不蕴含以后页面) if (PRE_LIST?.length) { window.sessionStorage.setItem('BREAD_PRE_LIST', JSON.stringify(PRE_LIST)); } }; // 监听页面刷新 useEffect(() => { const isReload = window.sessionStorage.getItem('BREAD_PAGE_LOAD'); if (!isReload) window.sessionStorage.setItem('BREAD_PAGE_LOAD', '0'); window.addEventListener('beforeunload', listenReload); return () => { window.removeEventListener('beforeunload', listenReload); }; }, []); // 跳转地址 useEffect(() => { if (!routes?.length || !rootPages?.length || !location) return; // 以后页面是否刷新 const isReload = window.sessionStorage.getItem('BREAD_PAGE_LOAD'); if (!PRE_LIST?.length && isReload === '1') { // 历史页面 PRE_LIST = JSON.parse(window.sessionStorage.getItem('BREAD_PRE_LIST') || '[]'); window.sessionStorage.setItem('BREAD_PAGE_LOAD', '0'); } else { // 不刷新 --> PRE_LIST 为上个页面之前的历史,须要通过 lastLocation 合成为历史数据 PRE_LIST = getBreadcrumb({ routes, location: lastLocation, cache: PRE_LIST, rootPages }); } // 以后页面 let current = []; // 二级导航清空数据, 并导入一级导航 if (rootPages?.find(item => item?.action === location?.pathname)) { PRE_LIST = []; } // 以后路由 current = getBreadcrumb({ routes, location, cache: current, rootPages }); // 面包屑 const result = [...PRE_LIST, ...current]; // 查找与以后门路雷同的第一个路由 并将其从面包屑中去除 const index = findIndex(result || [], { name: getBreadcrumbName({ routes, location })?.title, }); index !== result.length - 1 && result.splice(index + 1, result.length); setBreadRouts(() => result); }, [location, routes, lastLocation, rootPages]); if (breadRoutes.length === 0) return null; const handleJumpPage = url => { NativePageJump( { url, router, }, { isReplace: true, }, ); }; return ( <Breadcrumb className="bread-crumb" separator=">"> {breadRoutes.map((c, index) => { return ( <Breadcrumb.Item className={classNames('crumb', { 'last-crumb': index === breadRoutes?.length - 1 })} key={`breadcrumb-${index}`} // 一级目录、当前页皆不可点击跳转 onClick={() => index !== breadRoutes?.length - 1 && index !== 0 && handleJumpPage(c.path)}> {c?.name} </Breadcrumb.Item> ); })} </Breadcrumb> );};// 导出export default withRouter(Bread);

March 29, 2023 · 3 min · jiezi

关于react.js:Remix-集成-antd-和-procomponents

读者如果尝试过 Remix 那么感觉 Remix 页面与路由用的真的很难受(简略易用构造清晰),然而有一个问题,目前 Remix 我的项目集成了 antd/pro-components 等 国内UI 组件库好模板示例很少,于是想创立一个集成 Remix 与 antd 生态的组件库模板,能更快的体验并创立具备 antd 生态的 remix 我的项目。 浏览本文须要 React/Remix 基础知识和服务端渲染的相干常识要留神的问题外围要留神的问题就是: 问题阐明模块(包)兼容性和 peer 依等问题ssrRemix 服务端渲染反对问题兼容性兼容性次要体现在 React18 和其余的包的兼容性 应用脚手架创立的我的项目默认应用 React 18,由此带来兼容性问题?React 18 api 产生了变动,渲染 api 调用是否手动批改为 React18 的形式?npm 的 peer 依赖装置与否?其余的依赖的兼容 React 18 的问题?Remix 服务端渲染的反对状况咱们晓得 Remix 其实基于 esbuild 很多代码都跑在服务端,所以服务端的渲染的留神点是咱们要提前晓得: antd 反对服务端渲染pro-components 不反对服务端渲染,个别用于客户渲染,因为间接应用了 window/document 等客户端才有的全局对象remix-utils 工具包反对 <ClientOnly>{() => <>You Content</>}</ClientOnly> 应用组件仅仅在客户端进行渲染。初始化我的项目装置必要的包pnpm dlx create-umi@latest [your_package_name]# remix 抉择默认的选项即可pnpm install remix-utils antd @ant-design/pro-components @ant-design/cssinjs @ant-design/icons应用新个性 v2 版本的文件路由模式remix.config.js/** @type {import('@remix-run/dev').AppConfig} */module.exports = { future: { v2_routeConvention: true, }, ignoredRouteFiles: ["**/.*"],};增加 pro-components SettingDrawer 组件上下文import { createContext } from "react";const SettingContext = createContext({ theme: {}, setTheme: (theme: any) => {}});export default SettingContext;全局配置放在 SettingContext 上下文中,须要批改和应用都基于此上下文。 ...

March 24, 2023 · 6 min · jiezi

关于react.js:react16antd4-RangePicker-时间禁选

1.开发环境 react16+antd42.电脑系统 windows11专业版3.分享一下 react+antd RangePicker组件的工夫禁选;废话不多说,间接上代码: const [dateType, setdataType] = useState([ { value: '按日', key: 1 }, { value: '按月', key: 2 }]);const [dateTime, setDateTime] = useState([ moment().add(-1, 'years').add(0, "months").format("YYYY-MM"), moment().format("YYYY-MM"),]);const [timeValue, setTimeValue] = useState([ moment(moment().add(-1, 'years').add(0, "months"), 'YYYY-MM'), moment(moment(), 'YYYY-MM')]);const [timeFormat, setTimeFormat] = useState('YYYY-MM');const [pickerValue, setPickerValue] = useState('month');const getDay = () => { setDateTime([ moment().add(-1, "months").format("YYYY-MM-DD"), moment().format("YYYY-MM-DD"), ]); setTimeValue([ moment(moment().add(-1, "months"), 'YYYY-MM-DD'), moment(moment(), 'YYYY-MM-DD') ]); setTimeFormat('YYYY-MM-DD'); setPickerValue('date'); }; const getMonth = () => { setDateTime([ moment().add(-1, 'years').add(0, "months").format("YYYY-MM"), moment().format("YYYY-MM"), ]); setTimeValue([ moment().add(-1, 'years').add(0, "months"), moment(moment(), 'YYYY-MM') ]); setTimeFormat('YYYY-MM'); setPickerValue('month'); } // 工夫类型 变动 const TimeTypeChange = (value, option) => { setdateTypeValue(value); switch (+value) { case 1://按日 getDay(); break; case 2://按月 getMonth(); break; } } const timeDisabled = (current) => { switch (+dateTypeValue) { case 1:// 按日 return day_disabledDate(current); break; case 2:// 按月 return month_disabledDate(current); break; } } const month_disabledDate = (current) => { if (!timeValue) { return false; } const tooLate = timeValue[0] && current.diff(timeValue[0], 'months') > 11; const tooEarly = timeValue[1] && timeValue[1].diff(current, 'months') > 11; return !!tooEarly || !!tooLate; }; const day_disabledDate = (current) => { if (!timeValue) { return false; } const tooLate = timeValue[0] && current.diff(timeValue[0], 'months') > 0; const tooEarly = timeValue[1] && timeValue[1].diff(current, 'months') > 0; const disable_day = current && current < moment().endOf('day'); return !!tooEarly || !!tooLate || !disable_day; } const onOpenChange = (open) => { if (open) { setTimeValue([null, null]); } }; const _onRangePickerChange = (date, dateString) => { // setTimeValue(dateString); setTimeValue(date); setDateTime(dateString); } const onCalendarChange = (value) => { setTimeValue(value); }<Select placeholder='请抉择工夫类型' value={dateTypeValue == 1 ? '按日' : '按月'} onChange={TimeTypeChange} getPopupContainer={triggerNode => triggerNode.parentElement}> {dateType && dateType.map((item) => { return ( <Option key={item.key} value={item.key}>{item.value}</Option> ) })}</Select><RangePicker style={{ width: 330, marginLeft: 5 }} value={timeValue} format={timeFormat} allowClear={false} disabledDate={timeDisabled} picker={pickerValue} onChange={_onRangePickerChange} onOpenChange={onOpenChange} onCalendarChange={onCalendarChange}/>4.成果如下: ...

March 23, 2023 · 2 min · jiezi

关于react.js:前端生成pdf

最近要实现一个签合同的需要 须要前端实现合同展现、减少签名及公章、生成合同诉求: 不容许用户随便更改复制文案 网上搜到的办法canvas生产pdf 但会呈现页面被截断状况,所以钻研了一下 react-pdf 和 @react-pdf/renderer,很好用~ @react-pdf/renderer 它会提供自带的元素,能够自定义款式,生成你想要的pdfpdf内容 import { Document, Page, Text, StyleSheet, View, Image } from '@react-pdf/renderer';// 自定义字体 Font.register({ family: 'Oswald', src: 'https://64a478.ttf' });const styles = StyleSheet.create({ body: { paddingTop: 60, paddingLeft: 40, paddingRight: 40, paddingBottom: 30, fontFamily: 'Oswald' }, title: { fontSize: 14, textAlign: 'center', marginBottom: 30, }, subtitle: { fontSize: 14, textAlign: 'center', marginTop: 20, marginBottom: 20, }, introduce: { fontSize: 12, lineHeight: 1.6, }, graph: { fontSize: 12, lineHeight: 1.6, wrap: true, fontWeight: 'thin', color: 'rgba(0,0,0,.8)', }, graphText: { fontWeight: 'bold', textDecoration: 'underline', color: '#000', }, signImg: { width: '80px', height: '80px', position: 'absolute', left: 0, top: 0, zIndex: 2 }, pageNumber: { position: 'absolute', fontSize: 12, bottom: 30, left: 0, right: 0, textAlign: 'center', color: 'grey', },});const Content = (name?: string) => { return <Document> <Page size="A4" style={styles.body} > <Text style={styles.title}>BBBBB</Text> <Text style={styles.introduce}>This Agreement.</Text> <Text style={styles.subtitle}>AAAAAAa</Text> <Text style={styles.graph}> <Text style={styles.graphText}>加粗文案 </Text><Text>以后文案在一行内</Text> </Text> <Image style={styles.signImg} src="https:xxxxx.jpg" /> {name ? <Text>{name}</Text> : <></>} <Text style={styles.pageNumber} render={({ pageNumber, totalPages }) => ( `${pageNumber} / ${totalPages}` )} fixed /> </Page> </Document>}export default Contentpdf展现 ...

March 22, 2023 · 2 min · jiezi

关于react.js:解读-ahooks-源码系列DOM篇三

前言本文是 ahooks 源码系列的第四篇,往期文章: 【解读 ahooks 源码系列】(开篇)如何获取和监听 DOM 元素:useEffectWithTarget【解读 ahooks 源码系列】DOM篇(一):useEventListener、useClickAway、useDocumentVisibility、useDrop、useDrag【解读 ahooks 源码系列】DOM篇(二):useEventTarget、useExternal、useTitle、useFavicon、useFullscreen、useHover本文次要解读 useMutationObserver、useInViewport、useKeyPress、useLongPress 源码实现 useMutationObserver一个监听指定的 DOM 树发生变化的 Hook 官网文档 MutationObserver APIMutationObserver 接口提供了监督对 DOM 树所做更改的能力。利用 MutationObserver API 咱们能够监督 DOM 的变动,比方节点的减少、缩小、属性的变动、文本内容的变动等等。 可参考学习: MutationObserver你不晓得的 MutationObserver根本用法官网在线 Demo 点击按钮,扭转 width,触发 div 的 width 属性变更,打印的 mutationsList 如下: import { useMutationObserver } from 'ahooks';import React, { useRef, useState } from 'react';const App: React.FC = () => { const [width, setWidth] = useState(200); const [count, setCount] = useState(0); const ref = useRef<HTMLDivElement>(null); useMutationObserver( (mutationsList) => { mutationsList.forEach(() => setCount((c) => c + 1)); }, ref, { attributes: true }, ); return ( <div> <div ref={ref} style={{ width, padding: 12, border: '1px solid #000', marginBottom: 8 }}> current width:{width} </div> <button onClick={() => setWidth((w) => w + 10)}>widening</button> <p>Mutation count {count}</p> </div> );};外围实现这个实现比较简单,次要还是了解 MutationObserver API: ...

March 21, 2023 · 8 min · jiezi

关于react.js:把React新文档投喂给-GPT4-后

大家好,我卡颂。 最近,React新文档终于上线了。从内容上看,新文档包含: 理论知识、学习指引API介绍从模式上看,新文档除了传统的文字内容,还包含: 在线Demo示意图小测验能够说是浏览体验拉满。 然而,因为文档中实践局部内容太具体(比方与useEffect相干就有5节内容),浏览起来太费时间。且以后官网仅有英文版本,所以对国内开发者不太敌对。 凑巧最近GPT-4公布,将React新文档投喂给他后,完满解决了上述问题。并且,因为React新文档讲的切实是太分明了,以至于学习了文档的GPT齐全可能胜任编程助理的角色。 本文来聊聊GPT-4与React文档联合后产生的微妙体验。 欢送退出人类高质量前端交换群,带飞 GPT如何学习文档内容因为GPT-4的训练数据截止到21年9月,所以他无奈提供那之后公布的内容相干的信息。所以,首先咱们要给他手动投喂React文档。 实现起来很简略,只需2步: 在须要投喂的文档页关上控制台,执行下述代码:// 革除所有代码示例,只保留文字内容document.querySelectorAll('main code').forEach(item => {item.remove()})// 复制文档文本内容copy(document.querySelector('main').innerText)将文本内容复制给GPT: 如果文档内容太长,能够分段投喂: 至此,咱们就失去了熟读React文档的GPT。那么,熟读文档的GPT相比未学习之前都有哪些能力晋升呢? 文档大神炼成得益于Dan(React新文档作者)编写的逻辑清晰、由浅入深的文档内容,学习过文档的GPT比学习文档前对React有了更深的了解。 比方,对于如下代码,在useEffect的应用上有什么问题么(读者能够先本人试着找找问题): function List({ items }) { const [isReverse, setIsReverse] = useState(false); const [selection, setSelection] = useState(null); useEffect(() => { setSelection(null); }, [items]); // ...}这段代码没有逻辑或语法上的问题。所以,对于未学过新文档的GPT,尽管他能齐全了解这段代码的作用,但并不能发现问题: React Hooks公布于19年2月的v16.8,所以GPT晓得Hooks如何应用: 在学过新文档后,GPT能够明确指出例子中应用useEffect的形式可能会导致的问题: 同时,他还提出了解决办法 —— 在事件回调中间接设置selection为null,而不是应用useEffect。 实际上,这个Demo出自You Might Not Need an Effect一节,该节解说了一些常见的useEffect应用误区。GPT提供的解决思路正是该节提到的 —— 将useEffect局部逻辑抽离到事件回调中。 优良的编程助手让GPT学习文档后,还能解锁一个弱小能力 —— 私人编程助手。 得益于优良的文档,GPT曾经把握React最佳实际。当初,你能够将业务代码间接投喂给GPT,让他剖析代码有没有不合乎最佳实际的中央,并给出修改意见。 比方,对于上述代码,GPT给出了批改后的代码: 总结文档体验始终是各大开源我的项目都在重点发力的中央。以往大家的思路是 —— 提供各种不便开发者了解的工具(比方repl、在线Demo、视频文档...)。 ...

March 20, 2023 · 1 min · jiezi

关于react.js:20230320-技术周刊第-21-期

记录一周所见所闻 关注公踪号 进二开物,更多 JS/TS/CSS/Rust 技术文章和科技资讯...浏览语句"The only way to do great work is to love what you do." - Steve Jobs资讯本周科技圈又被 ACIG 相干内容点燃,Chat-GPT 公布第四个版本。四个版本开始反对更长的文字的辨认,减少多模态,输入图片等性能。百度也公布了本人的 ACIG 大模型 文心一言 文心一言目前还在内测中,须要邀请码能力体验其性能。 GPT-4 GPT-4 是一个多模态大型语言模型(反对承受图像和文本输出,以文本模式输入),也是 OpenAI 致力扩大深度学习的最新里程碑。文心一言 文心一言正式公布,目前须要排队或者邀请码能力应用。React 新的官网 本周React 公布了其新的官网,不同程度的 React 开发者都能够在学到本人所须要的货色。zed 编辑器进入公测阶段,目前仅反对 MacOS。[TypeScript 5.0]() 2023 年 3 月 17 日,TypeScript 5.0 正式公布!反对全新的装璜器模式等诸多新德行。文章举荐文章简介李开复:AI进入2.0时代,所有利用都会被重写一遍AI2.0 是相对不能错过的一次反动,它会是一个平台级别的趋势,超过挪动互联网十倍。别只盯着GPT-4!谷歌正在量子计算畛域获得更要害的冲破当市场都在围着ChatGPT转、纷纷议论谷歌正在输给微软之际,谷歌在科技界的“圣杯”量子计算畛域获得了重要的停顿。Vue.js 测试端到端指南单元测试将软件分解成更小的单元,因而更容易关注更小的局部及其细节,调试也变得容易得多。实用工具库用处阐明prisma-kysely 间接从您的Prisma模式生成Kysely类型!tailwindcss-animate一个 TailWind CSS 插件能创立丑陋的动画gradient-string一个丑陋的终端输入突变色彩exercises一些根本的JavaScript编码挑战和面试问题mesh-gradient.js一个应用 vanilla js 构建 微型基于 4 种 RGB 色彩生成网格突变。changelogen 应用惯例提交的丑陋更改日志cmake-jsCMake.js - 一个 Node.js 原生插件构建工具react-dev-inspector只需单击即可间接从 browser React 组件跳转到本地 IDE 代码svelte-codemirror-editor基于 CodeMirror6 的 Svelte 组件库开源与库库用处阐明mfng下一代微前端生成器llama-rs用 Rust 在 cpu 中运行 LLaMA 接口jsdom用于 Node.js,各种 Web 规范的 JavaScript 实现saaskit一个古代的应用 Fresh 的 SaaS 模板jsmind由 JavaScript 构建的思维导图库resolve.exports一个小的、正确的、通用的、可配置的导出和导入解析器,不依赖于文件系统mdx-editor微信排版编辑器,应用 MDX,可自定义组件、款式、生成二维码、代码 diff 高亮,可导出 markdown 和 PDFrust-ctorRust 的模块初始化/全局构造函数xplr一个可破解的,最小的,疾速的 TUI 文件浏览器bling 与框架无关的转译实用程序,用于客户端/服务器 RPC、环境隔离、孤岛、模块拆分等。elysia疾速、敌对的 Bun Web 框架jitiNode.js 的运行时 Typescript 和 ESM 反对往期举荐# 2023-03-13 技术周刊第 20 期# 2023-03-13 技术周刊第 19 期# 2023-02-27 技术周刊第 18 期更多微信搜寻并关注公踪号 进二开物,更多技术 JS/TS/CSS/Rust 文章... ...

March 19, 2023 · 1 min · jiezi

关于react.js:浅谈antd5使用心得

antd v5版本公布至今已有整整4个月了,在v5版本公布后我也是第一工夫把之前v4我的项目迁徙到了v5,对于此次降级还是有很大的变动跟改良的,故在此浅聊一下我的迁徙经验和倡议,前提是你曾经通读过官网的迁徙指南。 重大改良除了 ui 格调变动、更好的反对 Typescript、优化底层库的依赖等,我感觉此次大版本更新带来最大的变动是 CSS-in-JS 代替本来 less 的技术计划变更。升至v5后 antd 产物不再导出 css 文件,只有一个 reset.css ,况且这个重置款式文件也只是为了让开发者不再去依赖其余的诸如 Normalize.css 的第三方库。 为什么说这是一次重大改良?做过 antd 切换主题性能的开发者应该深有体会,我在之前的文章也有介绍过实现计划:[前端实现切换主题计划](https://segmentfault.com/a/1190000042573976) 。流程是先提前编译进去每种模式下的对应 less 文件,而后通过包裹 antd 提供的 ConfigProvider ,依据 mode 的变幻动静传值批改 prefixCls 的值以动静批改组件内的款式,这样做有以下几种弊病: 每加一种主题就要编译一套less,只管有很多反复的款式代码。使得我的项目打包后的体积变得越来越臃肿。保护起来十分吃力,因为每改一个 antd 组件的通用款式就要同时去批改每套主题下的 less 文件对应的雷同代码,只管他们只有 prefixCls 不同。批改款式要分外重视款式权重问题,减轻了开发者的心智累赘。批改主题可能会破费更多的工夫和写更多的代码,因为开发者须要去找到批改款式的元素的dom层级,而后在款式文件中为了权重问题须要写 full path。...(我没经验过的其余问题)而采纳 CSS-in-JS 这样的技术计划则会大大改善以上问题的呈现: 首先它是一种将 css 代码写成 JavaScript 对象或函数的办法,因而能够通过应用变量、函数等动静生成款式,不便响应式设计。并且相比 less 它作用域管制更容易,因而很好的解决了命名抵触和款式权重的问题。在肯定水平上他解决了一部分性能优化的问题,因为缩小了申请 css 款式文件的 http 申请。迁徙指南如果我的项目中没有除了黑夜\白天模式以外的其余主题,并且没有适配 IE 浏览器的需要,那么祝贺你,迁徙此我的项目的老本将是十分轻量级的,间接 yarn add antd 升级库版本,移除 v4 我的项目中援用到的 antd 内置的文件(antd/dist/antd.css),之前在 less 文件中通过 :global 去批改 antd 组件默认款式的行为同样会失效,如果之前做了主题切换性能的我的项目同样也能够把之前的主题款式文件删了,antd 内置了白天(default)、黑夜模式和紧凑模式的算法(algorithm)。这个 algorithm 在体现上来看能够了解为格调或者主题吧。那如果要批改单个组件的款式,比方antd 按钮默认高度为32,在某个业务场景下,这个按钮须要改成40,那么能够批改主题中的 token 去实现这一目标而不必去批改款式文件,这个 token 怎么了解?能够看成是组成一个组件的每个颗粒化的款式,也就是一些款式变量名而已。 ...

March 19, 2023 · 2 min · jiezi

关于react.js:Remix-表单

Remix 的三种表单原生表单Remix 提供的表单组件Remix fetcher 表单回顾表单根底提交行为:enter 按键(只有一个 input type="txt")/应用具备 type=sumbit 的按钮method 不指定时,form 默认应用 get 办法form 提交后默认行为是跳转到 action 对应的页面表单的提交形式是 content-type = x-www-form-unlencoded表单提交的模式应用 html 标签属性,主动提交手动提交:钩子函数 sumit 提交形式, fetcher.sumbit 提交形式阻止跳转通常咱们不心愿提交表单后产生跳转行为:应用事件阻止函数进行阻止。 const handleClick = (e) => { e.preventDefault()}Remix 提供的表单组件import { Form } from "@remix-run/react";一个简略的 demoimport { json } from "@remix-run/node";import { Form } from "@remix-run/react";export async function action () { let data = { a: 'this is data' } return json({ ...data })}export default function Index() { return ( <div> <div>Remix Form</div> <Form method="post"> <input type="text" name="a-name-remix"/> <button type="submit">submit-remix</button> </Form> </div> );}留神:Form 组件没有定义 method 的时候,点击提交按钮没有任何成果。个别增加 method='post'。增加之后就能够失常提交 post 申请表单。 ...

March 18, 2023 · 3 min · jiezi

关于react.js:Nextjs-实践从-SSR-到-CSR-的优雅降级

Next.js 是一个十分风行的 React 框架,它提供了开箱即用的服务端渲染(Server-Side Rendering, SSR)能力,咱们能够很轻松地借助 Next.js 实现 SSR,并部署到 Vercel 上。然而,Vercel 在国内没有服务节点,SSR 时通过 Vercel 服务器申请国内的服务接口存在肯定比例的申请失败,影响到了页面的渲染。因而,咱们须要减少客户端渲染(Client-Side Rendering, CSR)的逻辑作为兜底,以晋升渲染成功率。 在 Next.js 中咱们通过给页面组件减少 getServerSideProps 办法,即可触发 SSR。例如,咱们依据页面 URL 上的门路参数 id 调用接口获取详细信息,并将数据提供给页面组件办法渲染。代码如下: interface Props { detail: Detail;}async function getServerSideProps(context: GetServerSidePropsContext): Promise<{ props: Props }> { const { id } = context.params; const detail = await getDetail(id); return { props: { detail, }, };}Next.js 会传递 context 给 getServerSideProps 办法,其中包含了路由及申请参数信息;咱们通过返回一个蕴含 props 的对象,将获取到的数据通过 props 提供给页面组件在服务端渲染。 const Page: React.FC<Props> = props => { return <div>detail 的渲染逻辑 {props.detail}</div>;};由此可见,页面组件强依赖了服务端传递 props 的数据,如果申请失败势必导致页面无奈失常渲染。 ...

March 17, 2023 · 2 min · jiezi

关于react.js:NutUIReact-京东移动端组件库-2月份上新欢迎使用

作者:京东批发 佟恩 NutUI 是一款京东格调的挪动端组件库。NutUI 目前反对 Vue 和 React技术栈,反对Taro多端适配。 本次,是2月的一个示例输入,心愿对你有帮忙!2月,咱们对组件交互、issue修复、减少示例上做了急行军,共合并70+PR,修复近40个issue。这里咱们选取一些组件的新增示例,供您参考! 期待您早日成为咱们共建大军中的一员! 微信群:hanyuxinting(暗号:NutUI-React) 官网GitHub:点击进入 欢送共建、应用! Badge:款式自定义 外围代码: const customTheme = { nutuiBadgeBorderRadius: '12px 12px 12px 0',}<ConfigProvider theme={customTheme}> <Badge value="NEW"> <Avatar icon="my" shape="square" /> </Badge></ConfigProvider>查看Badge更多示例 Calendar:日期顶部和底部可配置内容 外围代码: const onTopInfo = () => { return ( t )}const onBottomInfo = () => { return ( b )}<Calendar visible={isVisible3} defaultValue={date3} type="range" confirmText="submit" startText="enter" endText="leave" onTopInfo={onTopInfo } onBottomInfo={onBottomInfo }/>查看更多示例 Cascader:可配置色彩、分割线、check icon 外围代码: const customTheme = { nutuiCascaderItemHeight: '48px', nutuiCascaderItemMargin: '0 10px', nutuiCascaderItemPadding: '10px', nutuiCascaderItemBorderBottom: '1px solid #F0F0F0',}<ConfigProvider theme={customTheme}> <Cascader color="#3768FA" tabsColor="#3768FA" /></ConfigProvider>查看更多示例 ...

March 16, 2023 · 2 min · jiezi

关于react.js:compressionwebpackplugin项目加载优化

1.开发环境 react18+webpack42.电脑系统 windows11专业版3.在我的项目打包的过程中,咱们发现打进去的包比拟大,而且我的项目加载比较慢[比方首页],解决办法是应用compression-webpack-plugin进行打包压缩gzip。4.所有古代浏览器都反对gzip压缩,启用gzip压缩可扩大和扩大传输资源大小,从而缩短资源下载工夫,缩小首次白屏工夫,晋升用户体验。gzip对基于文本格式文件的压缩成果最好(如:CSS,JavaScript和HTML),在压缩压缩文件时往往可实现高达70-90%的压缩率,对曾经压缩过的资源(如:图片)进行gzip压缩解决,成果很不好。 npm i compression-webpack-plugin@5 --save留神,这里不能间接下载,须要下载低版本的。间接下载就是最新版的了,我的项目可能临时不反对最新版的,所以就会报错:TypeError: Cannot read property 'tapPromise' of undefined。const CompressionPlugin = require('compression-webpack-plugin');plugins: [ new CompressionPlugin({ // gzip压缩配置 algorithm: 'gzip', test: /\.(js|css)$/, // 匹配文件名 threshold: 10240, // 对超过10kb的数据进行压缩 deleteOriginalAssets: true, // 是否删除原文件 }), ]这里配置完当前,临时还不能应用,还须要后端做一下配置,这里后端以nginx为例5.次要配置如下图: #user nobody;worker_processes 1;#error_log logs/error.log;#error_log logs/error.log notice;#error_log logs/error.log info;#pid logs/nginx.pid;events { worker_connections 1024;}http { include mime.types; default_type application/octet-stream; #log_format main '$remote_addr - $remote_user [$time_local] "$request" ' # '$status $body_bytes_sent "$http_referer" ' # '"$http_user_agent" "$http_x_forwarded_for"'; #access_log logs/access.log main; sendfile on; #tcp_nopush on; #keepalive_timeout 0; keepalive_timeout 65; #gzip on; server { listen 9000; server_name localhost; #charset koi8-r; #access_log logs/host.access.log main; location / { root D:/dist; index index.html index.htm; } location /api { proxy_pass http://localhost:3000; } # 次要是下方的gizp配置哦,间接复制粘贴就能够应用啦,亲测无效哦 gzip on; # 开启gzip压缩 gzip_min_length 4k; # 小于4k的文件不会被压缩,大于4k的文件才会去压缩 gzip_buffers 16 8k; # 解决申请压缩的缓冲区数量和大小,比方8k为单位申请16倍内存空间;应用默认即可,不必批改 gzip_http_version 1.1; # 晚期版本http不反对,指定默认兼容,不必批改 gzip_comp_level 2; # gzip 压缩级别,1-9,实践上数字越大压缩的越好,也越占用CPU工夫。实际上超过2的再压缩,只能压缩一点点了,然而cpu确是有点节约。因为2就够用了 # 压缩的文件类型 MIME类型,百度一下,一大把 # css # xml # 辨认php # 图片 gzip_types text/plain application/x-javascript application/javascript text/javascript text/css application/xml application/x-httpd-php image/jpeg image/gif image/png application/vnd.ms-fontobject font/x-woff font/ttf; # text # 晚期js # js # js的另一种写法 # .eot字体 # woff字体 # ttf字体 gzip_vary on; # 是否在http header中增加Vary: Accept-Encoding,个别状况下倡议开启 gzip_static on; #error_page 404 /404.html; # redirect server error pages to the static page /50x.html # error_page 500 502 503 504 /50x.html; location = /50x.html { root html; } # proxy the PHP scripts to Apache listening on 127.0.0.1:80 # #location ~ \.php$ { # proxy_pass http://127.0.0.1; #} # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000 # #location ~ \.php$ { # root html; # fastcgi_pass 127.0.0.1:9000; # fastcgi_index index.php; # fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name; # include fastcgi_params; #} # deny access to .htaccess files, if Apache's document root # concurs with nginx's one # #location ~ /\.ht { # deny all; #} } # another virtual host using mix of IP-, name-, and port-based configuration # #server { # listen 8000; # listen somename:8080; # server_name somename alias another.alias; # location / { # root html; # index index.html index.htm; # } #} # HTTPS server # #server { # listen 443 ssl; # server_name localhost; # ssl_certificate cert.pem; # ssl_certificate_key cert.key; # ssl_session_cache shared:SSL:1m; # ssl_session_timeout 5m; # ssl_ciphers HIGH:!aNULL:!MD5; # ssl_prefer_server_ciphers on; # location / { # root html; # index index.html index.htm; # } #}}// 要害 配置# 次要是下方的gizp配置哦,间接复制粘贴就能够应用啦,亲测无效哦 gzip on; # 开启gzip压缩 gzip_min_length 4k; # 小于4k的文件不会被压缩,大于4k的文件才会去压缩 gzip_buffers 16 8k; # 解决申请压缩的缓冲区数量和大小,比方8k为单位申请16倍内存空间;应用默认即可,不必批改 gzip_http_version 1.1; # 晚期版本http不反对,指定默认兼容,不必批改 gzip_comp_level 2; # gzip 压缩级别,1-9,实践上数字越大压缩的越好,也越占用CPU工夫。实际上超过2的再压缩,只能压缩一点点了,然而cpu确是有点节约。因为2就够用了 # 压缩的文件类型 MIME类型,百度一下,一大把 # css # xml # 辨认php # 图片 gzip_types text/plain application/x-javascript application/javascript text/javascript text/css application/xml application/x-httpd-php image/jpeg image/gif image/png application/vnd.ms-fontobject font/x-woff font/ttf; # text # 晚期js # js # js的另一种写法 # .eot字体 # woff字体 # ttf字体 gzip_vary on; # 是否在http header中增加Vary: Accept-Encoding,个别状况下倡议开启 gzip_static on; ...

March 15, 2023 · 3 min · jiezi

关于react.js:reactantd4-menu刷新之后保持之前默认选中

1.开发环境 react+antd2.电脑系统 windows11专业版3.咱们在我的项目的开发过程中,会遇到刷新页面之前选中的menu会失落,怎么刷新之后还放弃之前的选中的菜单呢?上面我来分享一下。4.须要用到withRouter来解决,一般组件的props是没有location,match,和history这三个属性的,只有路由组件才有。所以withRouter的作用就是将一般组件包装成路由组件,这样就会给一般组件的props加上location,match,和history这三个属性: import React, { useEffect, useState } from "react";import { Menu, Layout } from 'antd';import { withRouter } from "react-router-dom";const { Sider } = Layout;function SideMenu(props) { const [selectdValue,setSelectdValue] = useState(['result']); function _handleMenuClick({ item, key, keyPath}) { // console.log(item); // console.log(key); // console.log(keyPath); setSelectdValue(keyPath); props.history.push('/${key}`); } // 选中 菜单存储 //要害代码 const getMenuOptions=()=>{ const {pathname} = props.location; const menuKey = pathname.split('/')[1] || 'result'; setSelectdValue([menuKey]); } useEffect(()=>{ getMenuOptions(); },[]) return <Sider width={190} className="site-layout-background"> <Menu onClick={_handleMenuClick} selectedKeys={selectdValue} mode="inline" style={{ height: '100%', borderRight: 0 }} theme="dark" > <Menu.Item key="chenSouthList">南治理</Menu.Item> <Menu.Item key="chenNorthList">北治理</Menu.Item> </Menu> </Sider>}export default withRouter(SideMenu);5.本期的分享到了这里就完结啦,心愿对你有所帮忙,让咱们一起致力走向巅峰。 ...

March 15, 2023 · 1 min · jiezi

关于react.js:react源码解析16concurrent模式

concurrent modereact17反对concurrent mode,这种模式的基本目标是为了让利用放弃cpu和io的疾速响应,它是一组新性能,包含Fiber、Scheduler、Lane,能够依据用户硬件性能和网络情况调整利用的响应速度,外围就是为了实现异步可中断的更新。concurrent mode也是将来react次要迭代的方向。 cup:让耗时的reconcile的过程能让出js的执行权给更高优先级的工作,例如用户的输出,io:依附SuspenseFiberFiber咱们之前介绍过,这里咱们来看下在concurrent mode下Fiber的意义,react15之前的reconcile是同步执行的,当组件数量很多,reconcile时的计算量很大时,就会呈现页面的卡顿,为了解决这个问题就须要一套异步可中断的更新来让耗时的计算让出js的执行权给高优先级的工作,在浏览器有闲暇的时候再执行这些计算。所以咱们须要一种数据结构来形容实在dom和更新的信息,在适当的时候能够在内存中中断reconcile的过程,这种数据结构就是Fiber。 SchedulerScheduler独立于react自身,相当于一个独自的package,Scheduler的意义在于,当cup的计算量很大时,咱们依据设施的fps算出一帧的工夫,在这个工夫内执行cup的操作,当工作执行的工夫快超过一帧的工夫时,会暂停工作的执行,让浏览器有工夫进行重排和重绘。在适当的时候持续工作。 在js中咱们晓得generator也能够暂停和持续工作,然而咱们还须要用优先级来排列工作,这个是generator无奈实现的。在Scheduler中应用MessageChannel实现了工夫切片,而后用小顶堆排列工作优先级的高下,达到了异步可中断的更新。 Scheduler能够用过期工夫来代表优先级的高下。 优先级越高,过期工夫越短,离以后工夫越近,也就是说过一会就要执行它了。 优先级越低,过期工夫越长,离以后工夫越长,也就是过很久了能力轮到它执行。 laneLane用二进制位示意工作的优先级,不便优先级的计算,不同优先级占用不同地位的‘赛道’,而且存在批的概念,优先级越低,‘赛道’越多。高优先级打断低优先级,新建的工作须要赋予什么优先级等问题都是Lane所要解决的问题。 batchedUpdates简略来说,在一个上下文中同时触发屡次更新,这些更新会合并成一次更新,例如 onClick() { this.setState({ count: this.state.count + 1 }); this.setState({ count: this.state.count + 1 });} 在之前的react版本中如果脱离以后的上下文就不会被合并,例如把屡次更新放在setTimeout中,起因是处于同一个context的屡次setState的executionContext都会蕴含BatchedContext,蕴含BatchedContext的setState会合并,当executionContext等于NoContext,就会同步执行SyncCallbackQueue中的工作,所以setTimeout中的屡次setState不会合并,而且会同步执行。 onClick() { setTimeout(() => { this.setState({ count: this.state.count + 1 }); this.setState({ count: this.state.count + 1 }); });}export function batchedUpdates<A, R>(fn: A => R, a: A): R { const prevExecutionContext = executionContext; executionContext |= BatchedContext; try { return fn(a); } finally { executionContext = prevExecutionContext; if (executionContext === NoContext) { resetRenderTimer(); //executionContext为NoContext就同步执行SyncCallbackQueue中的工作 flushSyncCallbackQueue(); } }} 在Concurrent mode下,下面的例子也会合并为一次更新,根本原因在如下一段简化的源码,如果屡次setState,会比拟这几次setState回调的优先级,如果优先级统一,则先return掉,不会进行前面的render阶段 ...

March 15, 2023 · 1 min · jiezi

关于react.js:react源码解析15schedulerLane

当咱们在相似上面的搜寻框组件进行搜寻时会发现,组件分为搜寻局部和搜寻后果展现列表,咱们冀望输入框能立即响应,后果列表能够有期待的工夫,如果后果列表数据量很大,在进行渲染的时候,咱们又输出了一些文字,因为用户输出事件的优先级是很高的,所以就要进行后果列表的渲染,这就引出了不同工作之间的优先级和调度 Scheduler咱们晓得如果咱们的利用占用较长的js执行工夫,比方超过了设施一帧的工夫,那么设施的绘制就会出不的景象。 Scheduler次要的性能是工夫切片和调度优先级,react在比照差别的时候会占用肯定的js执行工夫,Scheduler外部借助MessageChannel实现了在浏览器绘制之前指定一个工夫片,如果react在指定工夫内没比照完,Scheduler就会强制交出执行权给浏览器 工夫切片 在浏览器的一帧中js的执行工夫如下 requestIdleCallback是在浏览器重绘重排之后,如果还有闲暇就能够执行的机会,所以为了不影响重绘重排,能够在浏览器在requestIdleCallback中执行耗性能的计算,然而因为requestIdleCallback存在兼容和触发机会不稳固的问题,scheduler中采纳MessageChannel来实现requestIdleCallback,以后环境不反对MessageChannel就采纳setTimeout。 在之前的介绍中咱们晓得在performUnitOfWork之后会执行render阶段和commit阶段,如果在浏览器的一帧中,cup的计算还没实现,就会让出js执行权给浏览器,这个判断在workLoopConcurrent函数中,shouldYield就是用来判断残余的工夫有没有用尽。在源码中每个工夫片时5ms,这个值会依据设施的fps调整。 function workLoopConcurrent() { while (workInProgress !== null && !shouldYield()) { performUnitOfWork(workInProgress); }}function forceFrameRate(fps) {//计算工夫片 if (fps < 0 || fps > 125) { console['error']( 'forceFrameRate takes a positive int between 0 and 125, ' + 'forcing frame rates higher than 125 fps is not supported', ); return; } if (fps > 0) { yieldInterval = Math.floor(1000 / fps); } else { yieldInterval = 5;//工夫片默认5ms }}工作的暂停在shouldYield函数中有一段,所以能够晓得,如果以后工夫大于工作开始的工夫+yieldInterval,就打断了工作的进行。 ...

March 15, 2023 · 4 min · jiezi

关于react.js:Remix-设计哲学

Remix 版本: v1.14.1Remix 中的丰盛教训Remix philosophy 浏览过程中感触最深的一个词 经验丰富,应用一个 map 数据结构来示意: let remixPhilosophy = Map({ 1: '开发经验丰富', 2: '培训经验丰富', 3:'开源经验丰富'})遵循 web 主观倒退主观倒退点用一个 map 数据结构示意: let rich_experience = Map({ 1: '遵循 S/C 模型', 2: '遵循 Web 规范', 3: '遵循渐进式加强', 4: '不过渡形象',})遵循 S/C 模型Remix 将前端对立到一个 Route Module 外面,然而仍然遵循 S/C 模型: loader 前端端数据形容:let sc_remix_router = { fe: 'useLoaderData_hook', be: 'export_loader_async_fn'}action 前后端数据形容:let sc_remix_router = { fe: 'useActionData_hook', be: 'export_action_async_fn'}遵循 Web 规范遵循 web 规范倒退形容: let web = { 'support': ['web_standard', 'http', 'html'], 'examples': ['fetch_api', 'link_tag', 'meta_tag', 'form']}渐进式在原有的 html 根底上,做 css/javascript/from/异步数据等性能加强 ...

March 14, 2023 · 1 min · jiezi

关于react.js:React-Tips-更优雅的处理多个值之间的切换

背景:此时,一个组件外部的state取值为"response" | 'header', 然而在组件外部,咱们须要依据state的值来切换不同的组件,这时候就须要用到type切换了。 实现思路:第一种实现 function App() { const [type, setType] = useState<"respones" | "header">('response'); return ( <div> <button onClick={() => setType('response')}>response</button> <button onClick={() => setType('header')}>header</button> {type === 'response' ? <Response /> : <Header />} </div> )}第二种实现 function App() { const [type, setType] = useState<"respones" | "header">('response'); const handleTypeChange = (e) => { setType(e.currentTarget.dataset.key); } return ( <div> {[{ name: 'response', }, { name: 'header', }].map((item) => { return <button key={item.name} data-key={item.name} onClick={handleTypeChange}>{item.name}</button> })} {type === 'response' ? <Response /> : <Header />} </div> )}总结:下面的两种形式都能够实现咱们的目标。然而第二种形式的实现更加的灵便,因为咱们能够通过循环的形式来实现,而不是写死的两个button。第一种形式的实现,如果咱们须要增加一个新的type,那么咱们就须要在组件外部增加一个新的button,这样就会导致组件的可维护性升高。此外,第一种形式的函数组件的渲染次数会比第二种形式的函数组件的渲染次数多,因为第一种形式的函数组件在每次渲染时,都会从新创立一个新的函数,而第二种形式的函数组件在每次渲染时,都会应用同一个函数。

March 12, 2023 · 1 min · jiezi

关于react.js:3个容易混淆的前端框架概念

大家好,我卡颂。 有3个容易混同的前端框架概念: 响应式更新单向数据流双向数据绑定在持续浏览本文前,读者能够思考下是否明确晓得三者的含意。 这三者之所以容易混同,是因为他们尽管同属前端框架领域内的概念,但又不是同一形象层级的概念,不好间接比拟。 本文会从3个形象层级动手解说这三者的区别。 欢送退出人类高质量前端交换群,带飞 响应式更新响应式更新也叫细粒度更新。同时,最近前端圈比拟火的Signal这一概念形容的也是响应式更新。 抽象的讲,响应式更新形容的是状态与UI之间的关系,即状态变动如何映射到UI变动。 思考如下例子(例子来自what are signals一文): function TodoApp() { const [todos, setTodos] = useState( [{ text: 'sleep', completed: false }] ) const [showCompleted, setShowCompleted] = useState(false) const filteredTodos = useMemo(() => { return todos.filter((todo) => !todo.completed || showCompleted) }, [todos, showCompleted]) return ( <TodoList todos={filteredTodos} /> )}在TodoApp组件中,定义了两个状态: 待办事项todos是否展现实现的事项showCompleted以及根据上述状态派生出的状态filteredTodos。最终,返回<TodoList/>组件。 如果todos状态变动,UI该如何变动?即咱们该如何晓得状态变动的影响范畴?这时,有两个思路: 推(push)拉(pull)推的原理咱们能够从变动的状态(例子中为todos)登程,依据状态的派生关系,一路推下去。 在例子中: todos变动filteredTodos由todos派生而来,变动传导到他这里<TodoList/>组件依赖了filteredTodos,变动传导到他这里确定了todos变动的最终影响范畴后,更新对应UI这就建设了状态与UI之间的关系。 除了推之外,还有一种被称为拉的形式。 拉的原理同样的例子,咱们也能建设状态与可能的UI变动的关系,再反过来推导UI变动的范畴。 在例子中: todos变动可能有UI变动(因为建设了状态与可能的UI变动的关系)UI与<TodoList/>组件相干,判断他是否变动<TodoList/>组件依赖filteredTodos,filteredTodos由todos派生而来,所以filteredTodos是变动的既然filteredTodos变动了,那么<TodoList/>组件可能变动计算变动的影响范畴,更新UI在支流框架中,React的更新以推为主,Vue、Preact、Solid.js等更多框架应用拉的形式。 本文聊的响应式更新就是拉这种形式的一种实现。 单向数据流咱们能够发现,不论是推还是拉,他们都须要计算变动的影响范畴,即一个状态变动后,到底有多少组件会受影响。 那么,从框架作者的角度登程,是心愿减少一些束缚,来缩小计算影响范畴这一过程的复杂度。 同样,从框架使用者的角度登程,也心愿减少一些束缚,当计算影响范畴出bug后,更容易排查问题。 这就有了单向数据流。 单向数据流是一条约定,他规定了当状态变动后,变动产生的影响只会从上往下传递。 ...

March 8, 2023 · 1 min · jiezi

关于react.js:解读-ahooks-源码系列-开篇如何获取和监听-DOM-元素

前言因为在工作中自定义 Hook 场景写的较多,当实现某个通用场景性能时,可能没想过有已实现好的 Hook 封装或者压根没想去从 Hooks 库外面找,然而社区好的实现应用起来是能够进步开发效率和缩小 bug 率的。 公司我的项目中有依赖库 ahooks,但我用的次数不多,于是有了想具体理解 ahooks 的打算,更次要是为了更加纯熟抽离与实现一些场景 Hook,学习如何更好的自定义 Hook,便有开始浏览 ahooks 源码的打算了。 学习 ahooks 源码的益处在我看来,学习 ahooks 常见 Hooks 封装有以下益处: 相熟如何依据需要去提炼相应的 Hooks,将通用逻辑进行封装解说源码实现思路,提炼外围实现,通过学习源码学习自定义 Hooks 最佳实际深刻学习特定的场景 Hooks,我的项目开发中一点通,应用时更得心应手对于源码系列本系列文章基于 ahooks 版本 v3.7.4,后续会相继输入 ahooks 源码解读的系列文章。 依照 ahooks 官网的分类,我目前先从 DOM 篇开始看起,DOM 篇包含的 Hooks 如下: useEventListener:优雅的应用 addEventListener。useClickAway:监听指标元素外的点击事件。useDocumentVisibility:优雅的应用 addEventListener。useDrop & useDrag:解决元素拖拽的 Hook。useEventTarget:常见表单控件(通过 e.target.value 获取表单值) 的 onChange 跟 value 逻辑封装,反对自定义值转换和重置性能。useExternal:动静注入 JS 或 CSS 资源,useExternal 能够保障资源全局惟一。useTitle:用于设置页面题目。useFavicon:设置页面的 favicon。useFullscreen:治理 DOM 全屏的 Hook。useHover:监听 DOM 元素是否有鼠标悬停。useMutationObserver:一个监听指定的 DOM 树发生变化的 Hook。useInViewport:察看元素是否在可见区域,以及元素可见比例。useKeyPress:监听键盘按键,反对组合键,反对按键别名。useLongPress:监听指标元素的长按事件。useMouse:监听鼠标地位。useResponsive:获取响应式信息。useScroll:监听元素的滚动地位。useSize:监听 DOM 节点尺寸变动的 Hook。useFocusWithin:监听以后焦点是否在某个区域之内,同 css 属性: focus-within。因为内容较多,DOM 篇会分成几篇文章输入,这样每篇读起来既不太耗时也能疾速过一遍。文章会在解读源码的根底上,也会把波及到的 JS 基础知识拎进去,在学源码的过程也能查漏补缺根底。 ...

March 2, 2023 · 3 min · jiezi

关于react.js:react源码解析14手写hooks

手写hooks最要害的是要了解hook队列和update队列的指针指向和updateQueue的更新计算 import React from "react";import ReactDOM from "react-dom";let workInProgressHook;//当前工作中的hooklet isMount = true;//是否时mount时const fiber = {//fiber节点 memoizedState: null,//hook链表 stateNode: App//dom};const Dispatcher = (() => {//Dispatcher对象 function mountWorkInProgressHook() {//mount时调用 const hook = {//构建hook queue: {//更新队列 pending: null//未执行的update队列 }, memoizedState: null,//以后state next: null//下一个hook }; if (!fiber.memoizedState) { fiber.memoizedState = hook;//第一个hook的话间接赋值给fiber.memoizedState } else { workInProgressHook.next = hook;//不是第一个的话就加在上一个hook的前面,造成链表 } workInProgressHook = hook;//记录当前工作的hook return workInProgressHook; } function updateWorkInProgressHook() {//update时调用 let curHook = workInProgressHook; workInProgressHook = workInProgressHook.next;//下一个hook return curHook; } function useState(initialState) { let hook; if (isMount) { hook = mountWorkInProgressHook(); hook.memoizedState = initialState;//初始状态 } else { hook = updateWorkInProgressHook(); } let baseState = hook.memoizedState;//初始状态 if (hook.queue.pending) { let firstUpdate = hook.queue.pending.next;//第一个update do { const action = firstUpdate.action; baseState = action(baseState); firstUpdate = firstUpdate.next;//循环update链表 } while (firstUpdate !== hook.queue.pending);//通过update的action计算state hook.queue.pending = null;//重置update链表 } hook.memoizedState = baseState;//赋值新的state return [baseState, dispatchAction.bind(null, hook.queue)];//useState的返回 } return { useState };})();function dispatchAction(queue, action) {//触发更新 const update = {//构建update action, next: null }; if (queue.pending === null) { update.next = update;//update的环状链表 } else { update.next = queue.pending.next;//新的update的next指向前一个update queue.pending.next = update;//前一个update的next指向新的update } queue.pending = update;//更新queue.pending isMount = false;//标记mount完结 workInProgressHook = fiber.memoizedState;//更新workInProgressHook schedule();//调度更新}function App() { let [count, setCount] = Dispatcher.useState(1); let [age, setAge] = Dispatcher.useState(10); return ( <> <p>Clicked {count} times</p> <button onClick={() => setCount(() => count + 1)}> Add count</button> <p>Age is {age}</p> <button onClick={() => setAge(() => age + 1)}> Add age</button> </> );}function schedule() { ReactDOM.render(<App />, document.querySelector("#root"));}schedule();相干参考视频解说:进入学习 ...

March 1, 2023 · 2 min · jiezi

关于react.js:react源码解析13hooks源码

hook调用入口 在hook源码中hook存在于Dispatcher中,Dispatcher就是一个对象,不同hook 调用的函数不一样,全局变量ReactCurrentDispatcher.current会依据是mount还是update赋值为HooksDispatcherOnMount或HooksDispatcherOnUpdate ReactCurrentDispatcher.current = current === null || current.memoizedState === null//mount or update ? HooksDispatcherOnMount : HooksDispatcherOnUpdate; const HooksDispatcherOnMount: Dispatcher = {//mount时 useCallback: mountCallback, useContext: readContext, useEffect: mountEffect, useImperativeHandle: mountImperativeHandle, useLayoutEffect: mountLayoutEffect, useMemo: mountMemo, useReducer: mountReducer, useRef: mountRef, useState: mountState, //...};const HooksDispatcherOnUpdate: Dispatcher = {//update时 useCallback: updateCallback, useContext: readContext, useEffect: updateEffect, useImperativeHandle: updateImperativeHandle, useLayoutEffect: updateLayoutEffect, useMemo: updateMemo, useReducer: updateReducer, useRef: updateRef, useState: updateState, //...};hook数据结构 在FunctionComponent中,多个hook会造成hook链表,保留在Fiber的memoizedState的上,而须要更新的Update保留在hook.queue.pending中 const hook: Hook = { memoizedState: null,//对于不同hook,有不同的值 baseState: null,//初始state baseQueue: null,//初始queue队列 queue: null,//须要更新的update next: null,//下一个hook};上面来看下memoizedState对应的值 ...

March 1, 2023 · 6 min · jiezi

关于react.js:react源码解析12状态更新流程

setState&forceUpdate在react中触发状态更新的几种形式: ReactDOM.renderthis.setStatethis.forceUpdateuseStateuseReducer咱们重点看下重点看下this.setState和this.forceUpdate,hook在第13章讲 this.setState内调用this.updater.enqueueSetState,次要是将update退出updateQueue中//ReactBaseClasses.jsComponent.prototype.setState = function (partialState, callback) { if (!(typeof partialState === 'object' || typeof partialState === 'function' || partialState == null)) { { throw Error( "setState(...): takes an object of state variables to update or a function which returns an object of state variables." ); } } this.updater.enqueueSetState(this, partialState, callback, 'setState');};//ReactFiberClassComponent.old.jsenqueueSetState(inst, payload, callback) { const fiber = getInstance(inst);//fiber实例 const eventTime = requestEventTime(); const suspenseConfig = requestCurrentSuspenseConfig(); const lane = requestUpdateLane(fiber, suspenseConfig);//优先级 const update = createUpdate(eventTime, lane, suspenseConfig);//创立update update.payload = payload; if (callback !== undefined && callback !== null) { //赋值回调 update.callback = callback; } enqueueUpdate(fiber, update);//update退出updateQueue scheduleUpdateOnFiber(fiber, lane, eventTime);//调度update}enqueueUpdate用来将update退出updateQueue队列 ...

February 28, 2023 · 4 min · jiezi

关于react.js:react源码解析11生命周期调用顺序

各阶段生命周期执行状况函数组件hooks的周期会在hooks章节解说,这一章的使命周期次要针对类组件,各阶段生命周期执行状况看下图: render阶段: mount时:组件首先会经验constructor、getDerivedStateFromProps、componnetWillMount、renderupdate时:组件首先会经验componentWillReceiveProps、getDerivedStateFromProps、shouldComponentUpdate、rendererror时:会调用getDerivedStateFromErrorcommit阶段 mount时:组件会经验componnetDidMountupdate时:组件会调用getSnapshotBeforeUpdate、componnetDidUpdateunMount时:调用componnetWillUnmounterror时:调用componnetDidCatch其中红色的局部不倡议应用,须要留神的是commit阶段生命周期在mutation各个子阶段的执行程序,能够温习上一章 接下来依据一个例子来解说在mount时和update时更新的具体程序: 相干参考视频解说:进入学习 mount时:首先会依照深度优先的形式,顺次构建wip Fiber节点而后切换成current Fiber,在render阶段会顺次执行各个节点的constructor、getDerivedStateFromProps/componnetWillMount、render,在commit阶段,也就是深度优先遍历向上冒泡的时候顺次执行节点的componnetDidMountupdate时:同样会深度优先构建wip Fiber树,在构建的过程中会diff子节点,在render阶段,如果返现有节点的变动,例如上图的c2,那就标记这个节点Update Flag,而后执行getDerivedStateFromProps和render,在commit阶段会顺次执行节点的getSnapshotBeforeUpdate、componnetDidUpdate

February 28, 2023 · 1 min · jiezi

关于react.js:一文带你梳理React面试题2023年版本

源码剖析 一、React18有哪些更新?setState主动批处理在react17中,只有react事件会进行批处理,原生js事件、promise,setTimeout、setInterval不会 react18,将所有事件都进行批处理,即屡次setState会被合并为1次执行,进步了性能,在数据层,将多个状态更新合并成一次解决(在视图层,将屡次渲染合并成一次渲染) 引入了新的root API,反对new concurrent renderer(并发模式的渲染)//React 17import React from "react"import ReactDOM from "react-dom"import App from "./App"const root = document.getElementById("root")ReactDOM.render(<App/>,root)// 卸载组件ReactDOM.unmountComponentAtNode(root) // React 18import React from "react"import ReactDOM from "react-dom/client"import App from "./App"const root = document.getElementById("root")ReactDOM.createRoot(root).render(<App/>)// 卸载组件root.unmount() 去掉了对IE浏览器的反对,react18引入的新个性全副基于古代浏览器,如需反对须要退回到react17版本flushSync批量更新是一个破坏性的更新,如果想退出批量更新,能够应用flushSync import React,{useState} from "react"import {flushSync} from "react-dom"const App=()=>{ const [count,setCount]=useState(0) const [count2,setCount2]=useState(0) return ( <div className="App"> <button onClick=(()=>{ // 第一次更新 flushSync(()=>{ setCount(count=>count+1) }) // 第二次更新 flushSync(()=>{ setCount2(count2=>count2+1) }) })>点击</button> <span>count:{count}</span> <span>count2:{count2}</span> </div> )}export default Appreact组件返回值更新在react17中,返回空组件只能返回null,显式返回undefined会报错在react18中,反对null和undefined返回strict mode更新当你应用严格模式时,React会对每个组件返回两次渲染,以便你察看一些意想不到的后果,在react17中去掉了一次渲染的控制台日志,以便让日志容易浏览。react18勾销了这个限度,第二次渲染会以浅灰色呈现在控制台日志 ...

February 27, 2023 · 4 min · jiezi

关于react.js:react源码解析10commit阶段

在render阶段的开端会调用commitRoot(root);进入commit阶段,这里的root指的就是fiberRoot,而后会遍历render阶段生成的effectList,effectList上的Fiber节点保留着对应的props变动。之后会遍历effectList进行对应的dom操作和生命周期、hooks回调或销毁函数,各个函数做的事件如下 在commitRoot函数中其实是调度了commitRootImpl函数 //ReactFiberWorkLoop.old.jsfunction commitRoot(root) { var renderPriorityLevel = getCurrentPriorityLevel(); runWithPriority$1(ImmediatePriority$1, commitRootImpl.bind(null, root, renderPriorityLevel)); return null;}在commitRootImpl的函数中次要分三个局部: commit阶段前置工作 调用flushPassiveEffects执行完所有effect的工作初始化相干变量赋值firstEffect给前面遍历effectList用//ReactFiberWorkLoop.old.jsdo { // 调用flushPassiveEffects执行完所有effect的工作 flushPassiveEffects(); } while (rootWithPendingPassiveEffects !== null); //... // 重置变量 finishedWork指rooFiber root.finishedWork = null; //重置优先级 root.finishedLanes = NoLanes; // Scheduler回调函数重置 root.callbackNode = null; root.callbackId = NoLanes; // 重置全局变量 if (root === workInProgressRoot) { workInProgressRoot = null; workInProgress = null; workInProgressRootRenderLanes = NoLanes; } else { } //rootFiber可能会有新的副作用 将它也退出到effectLis let firstEffect; if (finishedWork.effectTag > PerformedWork) { if (finishedWork.lastEffect !== null) { finishedWork.lastEffect.nextEffect = finishedWork; firstEffect = finishedWork.firstEffect; } else { firstEffect = finishedWork; } } else { firstEffect = finishedWork.firstEffect; }mutation阶段 ...

February 27, 2023 · 5 min · jiezi

关于react.js:react源码解析1开篇介绍和面试题

怎么学习react源码作为前端最罕用的js库之一,相熟react源码成了高级或资深前端工程师必备的能力,如果你不想停留在api的应用层面或者想在前端技能的深度上有所突破,那相熟react源码将是你提高的很好的形式。 react的纯正体现在它的api上,一切都是围绕setState状态更新进行的,然而外部的逻辑却经验了很大的重构和变动,而且代码量也不小,如果只是从源码文件和函数来浏览,那会很难以了解react的渲染流程。优良工程师几年工夫打造的库,必然有借鉴之处,那么咱们应该怎么学习react源码呢。 首先,咱们能够从函数调用栈动手,理清react的各个模块的性能和它们调用的程序,盖房子一样,先搭好架子,对源码有个整体的意识,而后再看每个模块的细节,第一遍的时候切忌纠结每个函数实现的细节,陷入各个函数的深度调用中。其次能够联合一些demo和本人画图了解,react源码中设计大量的链表操作,画图是一个很好的了解指针操作的形式。源码里也有一些英文正文,能够依据正文或者依据此react源码解析文章进行了解。 相熟react源码并不是久而久之的事,想精进本人的技术,必须花工夫才行。 教程特色本教程遵循react v17.0.1源码的核心思想,目标是打造一门通俗易懂的react源码解析系列文章。教程从源码的各个模块开始,联合大量demo、示例图解和视频教程,带着大家一步一步调试react源码,教程也会齐全遵循react17手写hook和精简版的react不便大家的了解,随着react大版本的更新,此教程也会始终更新。 教程构造 教程播种为什么要学习react源码呢,你是应用了api很久,停留在框架应用层面还是会被动去理解框架的逻辑和运行形式呢。跟着教程走,了解起来不费劲,你将播种: 面试加分:大厂前端岗都要求相熟框架底层原理,也是面试必问环节,相熟react源码会为你的面试加分,也会为你的谈薪流程减少不少筹码坚固基础知识:在源码的scheduler中应用了小顶堆 这种数据结构,调度的实现则应用了messageChannel,在render阶段的reconciler中则应用了fiber、update、链表 这些构造,lane模型应用了二进制掩码,咱们也会介绍diff算法怎么升高比照复杂度。学习本教程也顺便坚固了数据结构和算法、事件循环。日常开发晋升效率:相熟react源码之后,你对react的运行流程有了新的意识,在日常的开发中,置信你对组件的性能优化、react应用技巧和解决bug会更加得心应手。置信学完教程之后,你对react的了解肯定会回升一个品位,甚至会超过大多数面试官了 常见面试题(带上问题学习吧)以下这些问题可能你曾经有答案了,然而你能从源码角度答复进去吗。 jsx和Fiber有什么关系react17之前jsx文件为什么要申明import React from 'react',之后为什么不须要了Fiber是什么,它为什么能进步性能hooks 为什么hooks不能写在条件判断中状态/生命周期 setState是同步的还是异步的componentWillMount、componentWillMount、componentWillUpdate为什么标记UNSAFE组件 react元素$$typeof属性什么react怎么辨别Class组件和Function组件函数组件和类组件的相同点和不同点开放性问题 说说你对react的了解/请说一下react的渲染过程聊聊react生命周期简述diff算法react有哪些优化伎俩react为什么引入jsx说说virtual Dom的了解你对合成事件的了解 咱们写的事件是绑定在dom上么,如果不是绑定在哪里?为什么咱们的事件手动绑定this(不是箭头函数的状况)为什么不能用 return false 来阻止事件的默认行为?react怎么通过dom元素,找到与之对应的 fiber对象的?解释后果和景象 点击Father组件的div,Child会打印Child吗function Child() { console.log('Child'); return <div>Child</div>;}function Father(props) { const [num, setNum] = React.useState(0); return ( <div onClick={() => {setNum(num + 1)}}> {num} {props.children} </div> );}function App() { return ( <Father> <Child/> </Father> );}const rootEl = document.querySelector("#root");ReactDOM.render(<App/>, rootEl);相干参考视频解说:进入学习 打印程序是什么function Child() { useEffect(() => { console.log('Child'); }, []) return <h1>child</h1>;}function Father() { useEffect(() => { console.log('Father'); }, []) return <Child/>;}function App() { useEffect(() => { console.log('App'); }, []) return <Father/>;}useLayoutEffect/componentDidMount和useEffect的区别是什么class App extends React.Component { componentDidMount() { console.log('mount'); }}useEffect(() => { console.log('useEffect');}, [])如何解释demo_4、demo_8、demo_9呈现的景象

February 27, 2023 · 1 min · jiezi

关于react.js:面试官说说react的渲染过程

hello,这里是潇晨,大家在面试的过程中有没有遇到过一些和react相干的问题呢,比方面试官让你说说react渲染的过程,这到题目比拟凋谢,也比拟考验大家对react渲染原理以及源码的整体架构的了解。 整体流程: react的外围能够用ui=fn(state)来示意,更具体能够用 const state = reconcile(update);const UI = commit(state);下面的fn能够分为如下一个局部: Scheduler(调度器): 排序优先级,让优先级高的工作先进行reconcileReconciler(协调器): 找出哪些节点产生了扭转,并打上不同的Flags(旧版本react叫Tag)Renderer(渲染器): 将Reconciler中打好标签的节点渲染到视图上那这些模块是怎么配合工作的呢:首先jsx通过babel的ast词法解析之后编程React.createElement,React.createElement函数执行之后就是jsx对象,也被称为virtual-dom。不论是在首次渲染还是更新状态的时候,这些渲染的工作都会通过Scheduler的调度,Scheduler会依据工作的优先级来决定将哪些工作优先进入render阶段,比方用户触发的更新优先级十分高,如果以后正在进行一个比拟耗时的工作,则这个工作就会被用户触发的更新打断,在Scheduler中初始化工作的时候会计算一个过期工夫,不同类型的工作过期工夫不同,优先级越高的工作,过期工夫越短,优先级越低的工作,过期工夫越长。在最新的Lane模型中,则能够更加细粒度的依据二进制1的地位,来决定工作的优先级,通过二进制的交融和相交,判断工作的优先级是否足够在此次render的渲染。Scheduler会调配一个工夫片给须要渲染的工作,如果是一个十分耗时的工作,如果在一个工夫片之内没有执行实现,则会从以后渲染到的Fiber节点暂停计算,让出执行权给浏览器,在之后浏览器闲暇的时候从之前暂停的那个Fiber节点持续前面的计算,这个计算的过程就是计算Fiber的差别,并标记副作用。具体可浏览往期课件和视频解说,往期文章在底部。在render阶段:render阶段的配角是Reconciler,在mount阶段和update阶段,它会比拟jsx和以后Fiber节点的差别(diff算法指的就是这个比拟的过程),将带有副作用的Fiber节点标记进去,这些副作用有Placement(插入)、Update(更新)、Deletetion(删除)等,而这些带有副作用Fiber节点会退出一条EffectList中,在commit阶段就会遍历这条EffectList,解决相应的副作用,并且利用到实在节点上。而Scheduler和Reconciler都是在内存中工作的,所以他们不影响最初的出现。在commit阶段:会遍历EffectList,解决相应的生命周期,将这些副作用利用到实在节点,这个过程会对应不同的渲染器,在浏览器的环境中就是react-dom,在canvas或者svg中就是reac-art等。 另外咱们也能够从首次渲染和更新的时候看在render和commit这两个子阶段是如果工作的: mount时: 在render阶段会依据jsx对象构建新的workInProgressFiber树,不太理解Fiber双缓存的能够查看往期文章 Fiber架构,而后将相应的fiber节点标记为Placement,示意这个fiber节点须要被插入到dom树中,而后会这些带有副作用的fiber节点退出一条叫做Effect List的链表中。在commit阶段会遍历render阶段造成的Effect List,执行链表上相应fiber节点的副作用,比方Placement插入,或者执行Passive(useEffect的副作用)。将这些副作用利用到实在节点上相干参考视频解说:进入学习 update时: 在render阶段会依据最新状态的jsx对象比照current Fiber,再构建新的workInProgressFiber树,这个比照的过程就是diff算法,diff算法又分成单节点的比照和多节点的比照,不太分明的同学参见之前的文章 diff算法 ,比照的过程中同样会经验收集副作用的过程,也就是将比照进去的差别标记进去,退出Effect List中,这些比照进去的副作用例如:Placement(插入)、Update(更新)、Deletion(删除)等。在commit阶段同样会遍历Effect List,将这些fiber节点上的副作用利用到实在节点上

February 21, 2023 · 1 min · jiezi

关于react.js:面试官说说你对react生命周期的理解

hello,这里是潇晨,明天咱们来看下react生命周期在各个阶段是怎么执行的,在面试的过程中有没有遇到这个问题呢,大家也能够学习往期react源码体系文章哦,往期文章目录在文章结尾。 在之前的react源码介绍中,咱们能够将利用的渲染过程分为mount阶段(利用首次渲染)和update阶段(利用状态更新),无论在mount阶段还是update阶段,都会经验两个子阶段,一个是render阶段,一个是commit阶段。 mount时: 在render阶段会依据jsx对象构建新的workInProgressFiber树,不太理解Fiber双缓存的能够查看往期文章 Fiber架构,而后将相应的fiber节点标记为Placement,示意这个fiber节点须要被插入到dom树中,而后会这些带有副作用的fiber节点退出一条叫做Effect List的链表中。在commit阶段会遍历render阶段造成的Effect List,执行链表上相应fiber节点的副作用,比方Placement插入,或者执行Passive(useEffect的副作用)。将这些副作用利用到实在节点上update时: 在render阶段会依据最新状态的jsx对象比照current Fiber,再构建新的workInProgressFiber树,这个比照的过程就是diff算法,diff算法又分成单节点的比照和多节点的比照,不太分明的同学参见之前的文章 diff算法 ,比照的过程中同样会经验收集副作用的过程,也就是将比照进去的差别标记进去,退出Effect List中,这些比照进去的副作用例如:Placement(插入)、Update(更新)、Deletion(删除)等。在commit阶段同样会遍历Effect List,将这些fiber节点上的副作用利用到实在节点上为什么要先讲render在mount和update阶段的整体流程呢,这是因为react生命周期就是穿插在这些子阶段中执行的,来看一张图 render阶段: mount时:组件首先会经验constructor、getDerivedStateFromProps、componnetWillMount、renderupdate时:组件首先会经验componentWillReceiveProps、getDerivedStateFromProps、shouldComponentUpdate、rendererror时:会调用getDerivedStateFromErrorcommit阶段 mount时:组件会经验componnetDidMountupdate时:组件会调用getSnapshotBeforeUpdate、componnetDidUpdateunMount时:调用componnetWillUnmounterror时:调用componnetDidCatch其中红色的局部不倡议应用,须要留神的是commit阶段生命周期在mutation各个子阶段的执行程序,能够温习上一章 接下来依据一个例子来解说在mount时和update时更新的具体程序: mount时:首先会依照深度优先的形式,顺次构建wip Fiber节点而后切换成current Fiber,在render阶段会顺次执行各个节点的constructor、getDerivedStateFromProps/componnetWillMount、render,在commit阶段,也就是深度优先遍历向上冒泡的时候顺次执行节点的componnetDidMount相干参考视频解说:进入学习 update时:同样会深度优先构建wip Fiber树,在构建的过程中会diff子节点,在render阶段,如果返现有节点的变动,例如上图的c2,那就标记这个节点Update Flag,而后执行getDerivedStateFromProps和render,在commit阶段会顺次执行节点的getSnapshotBeforeUpdate、componnetDidUpdate

February 21, 2023 · 1 min · jiezi

关于react.js:ReactHooks怎样封装防抖和节流面试真题

Debouncedebounce 原意打消抖动,对于事件触发频繁的场景,只有最初由程序控制的事件是无效的。防抖函数,咱们须要做的是在一件事触发的时候设置一个定时器使事件提早产生,在定时器期间事件再次触发的话则革除重置定时器,直到定时器到时仍不被革除,事件才真正产生。 const debounce = (fun, delay) => { let timer; return (...params) => { if (timer) { clearTimeout(timer); } timer = setTimeout(() => { fun(...params); }, delay); };};如果事件产生使一个变量频繁变动,那么应用debounce能够升高批改次数。通过传入批改函数,取得一个新的批改函数来应用。 如果是class组件,新函数能够挂载到组件this上,然而函数式组件局部变量每次render都会创立,debounce失去作用,这时须要通过useRef来保留成员函数(下文throttle通过useRef保留函数),是不够便捷的,就有了将debounce做成一个hook的必要。 function useDebounceHook(value, delay) { const [debounceValue, setDebounceValue] = useState(value); useEffect(() => { let timer = setTimeout(() => setDebounceValue(value), delay); return () => clearTimeout(timer); }, [value, delay]); return debounceValue;}在函数式组件中,能够将指标变量通过useDebounceHook转化一次,只有在满足delay的提早之后,才会触发,在delay期间的触发都会重置计时。 配合useEffect,在debounce value扭转之后才会做出一些动作。上面的text这个state频繁变动,然而依赖的是debounceText,所以引发的useEffect回调函数却是在指定提早之后才会触发。 const [text,setText]=useState('');const debounceText = useDebounceHook(text, 2000);useEffect(() => { // ... console.info("change", debounceText);}, [debounceText]);function onChange(evt){ setText(evt.target.value)}下面一个搜寻框,输出实现1秒(指定提早)后才触发搜寻申请,曾经达到了防抖的目标。 ...

February 21, 2023 · 2 min · jiezi

关于react.js:社招前端常考react面试题总结

react 强制刷新component.forceUpdate() 一个不罕用的生命周期办法, 它的作用就是强制刷新 官网解释如下 默认状况下,当组件的 state 或 props 发生变化时,组件将从新渲染。如果 render() 办法依赖于其余数据,则能够调用 forceUpdate() 强制让组件从新渲染。 调用 forceUpdate() 将以致组件调用 render() 办法,此操作会跳过该组件的 shouldComponentUpdate()。但其子组件会触发失常的生命周期办法,包含 shouldComponentUpdate() 办法。如果标记发生变化,React 仍将只更新 DOM。 通常你应该防止应用 forceUpdate(),尽量在 render() 中应用 this.props 和 this.state。 shouldComponentUpdate 在初始化 和 forceUpdate 不会执行 react-router里的<Link>标签和<a>标签有什么区别比照<a>,Link组件防止了不必要的重渲染React 组件中怎么做事件代理?它的原理是什么?React基于Virtual DOM实现了一个SyntheticEvent层(合成事件层),定义的事件处理器会接管到一个合成事件对象的实例,它合乎W3C规范,且与原生的浏览器事件领有同样的接口,反对冒泡机制,所有的事件都主动绑定在最外层上。 在React底层,次要对合成事件做了两件事: 事件委派: React会把所有的事件绑定到构造的最外层,应用对立的事件监听器,这个事件监听器上维持了一个映射来保留所有组件外部事件监听和处理函数。主动绑定: React组件中,每个办法的上下文都会指向该组件的实例,即主动绑定this为以后组件。React-Router怎么设置重定向?应用<Redirect>组件实现路由的重定向: <Switch> <Redirect from='/users/:id' to='/users/profile/:id'/> <Route path='/users/profile/:id' component={Profile}/></Switch>当申请 /users/:id 被重定向去 '/users/profile/:id': 属性 from: string:须要匹配的将要被重定向门路。属性 to: string:重定向的 URL 字符串属性 to: object:重定向的 location 对象属性 push: bool:若为真,重定向操作将会把新地址退出到拜访历史记录外面,并且无奈回退到后面的页面。什么是上下文ContextContext 通过组件树提供了一个传递数据的办法,从而防止了在每一个层级手动的传递 props 属性。 用法:在父组件上定义getChildContext办法,返回一个对象,而后它的子组件就能够通过this.context属性来获取import React,{Component} from 'react';import ReactDOM from 'react-dom';import PropTypes from 'prop-types';class Header extends Component{ render() { return ( <div> <Title/> </div> ) }}class Title extends Component{ static contextTypes={ color:PropTypes.string } render() { return ( <div style={{color:this.context.color}}> Title </div> ) }}class Main extends Component{ render() { return ( <div> <Content> </Content> </div> ) }}class Content extends Component{ static contextTypes={ color: PropTypes.string, changeColor:PropTypes.func } render() { return ( <div style={{color:this.context.color}}> Content <button onClick={()=>this.context.changeColor('green')}>绿色</button> <button onClick={()=>this.context.changeColor('orange')}>橙色</button> </div> ) }}class Page extends Component{ constructor() { super(); this.state={color:'red'}; } static childContextTypes={ color: PropTypes.string, changeColor:PropTypes.func } getChildContext() { return { color: this.state.color, changeColor:(color)=>{ this.setState({color}) } } } render() { return ( <div> <Header/> <Main/> </div> ) }}ReactDOM.render(<Page/>,document.querySelector('#root'));在结构函数调用 super 并将 props 作为参数传入的作用在调用 super() 办法之前,子类构造函数无奈应用this援用,ES6 子类也是如此。 将 props 参数传递给 super() 调用的次要起因是在子构造函数中可能通过this.props来获取传入的 props ...

February 21, 2023 · 5 min · jiezi

关于react.js:Reacthooks面试考察知识点汇总

Hook 简介Hook入世之前React存在的问题在组件之间复用状态逻辑很难 React 没有提供将可复用性行为“附加”到组件的路径(例如,把组件连贯到 store)。有一些解决此类问题的计划,比方 render props 和 高阶组件。然而这类计划须要从新组织你的组件构造,这可能会很麻烦,使你的代码难以了解。 简单组件变得难以了解 组件经常在 componentDidMount 和 componentDidUpdate中获取数据。然而,同一个 componentDidMount 中可能也蕴含很多其它的逻辑,如设置事件监听,而之后需在 componentWillUnmount 中革除。互相关联且须要对照批改的代码被进行了拆分,而齐全不相干的代码却在同一个办法中组合在一起。如此很容易产生 bug,并且导致逻辑不统一。 难以了解的 class class 是学习 React 的一大屏障。你必须去了解 JavaScript 中 this 的工作形式,这与其余语言存在微小差别。还不能遗记绑定事件处理器。没有稳固的语法提案,这些代码十分冗余。大家能够很好地了解 props,state 和自顶向下的数据流,但对 class 却束手无策。 Hook带来的解决方案你能够应用 Hook 从组件中提取状态逻辑,使得这些逻辑能够独自测试并复用。Hook 使你在无需批改组件构造的状况下复用状态逻辑。Hook 将组件中互相关联的局部拆分成更小的函数(比方设置订阅或申请数据),而并非强制依照生命周期划分。你还能够应用 reducer 来治理组件的外部状态,使其更加可预测。Hook 使你在非 class 的状况下能够应用更多的 React 个性。 从概念上讲,React 组件始终更像是函数。而 Hook 则拥抱了函数,同时也没有就义 React 的精力准则。Hook 提供了问题的解决方案,无需学习简单的函数式或响应式编程技术。Hook APIuseStateuseState 是react自带的一个hook函数,它的作用就是用来申明状态变量。useState这个函数接管的参数是咱们的状态初始值(initial state),它返回了一个数组,这个数组的第[0]项是以后以后的状态值,第[1]项是能够扭转状态值的办法函数。 初始化//返回一个 state,以及更新 state 的函数 setState(接管一个新的 state 值并将组件的一次从新渲染退出队列)const [state, setState] = useState(initialState);函数式更新//如果新的 state 须要通过应用先前的 state 计算得出,那么能够将函数传递给 setState。该函数将接管先前的 state,并返回一个更新后的值。function Counter({initialCount}) { const [count, setCount] = useState(initialCount); return ( <> Count: {count} <button onClick={() => setCount(initialCount)}>Reset</button> <button onClick={() => setCount(prevCount => prevCount - 1)}>-</button> <button onClick={() => setCount(prevCount => prevCount + 1)}>+</button> </> );}惰性初始 state//如果初始 state 须要通过简单计算取得,则能够传入一个函数,在函数中计算并返回初始的 state,此函数只在初始渲染时被调用const [state, setState] = useState(() => { const initialState = someExpensiveComputation(props); return initialState;});跳过 state 更新调用 State Hook 的更新函数并传入以后的 state 时,React 将跳过子组件的渲染及 effect 的执行。(React 应用 Object.is 比拟算法 来比拟 state。) ...

February 21, 2023 · 4 min · jiezi

关于react.js:面试官useLayoutEffect和useEffect的区别

大家面试的过程中有没有遇到过这样的问题呢,useLayoutEffect和useEffect的区别是什么,大家可能会答复useEffect是异步的,useLayoutEffect是同步的,这样答复面试官真的会称心慢,咱们须要说分明他们在源码中的调用机会。 先来看个例子:点击触发更新之后,如果count之前的状态是0,咱们随机生成一个数字,在阻塞一段时间,在设置count位随机值,看看在useEffect和useLayoutEffect这两种状况下会有什么不同 import React, { useLayoutEffect, useState, useEffect } from "react";export default function App() { const [count, setCount] = useState(0); //用 useLayoutEffect 试试 useEffect(() => { if (count === 0) { const randomNum = Math.random() * 100;//随机生成一个数字 const now = performance.now(); while (performance.now() - now < 100) {//阻塞一段时间 console.log('blocking...'); } setCount(randomNum);//从新设置状态,设置成随机数 } }, [count]); return <div onClick={() => setCount(0)}>{count}</div>;}//在useEffect的状况下,一直点击触发更新,偶然会显示0//在useLayoutEffect的状况下,一直点击触发更新,不会偶现0在源码中不论首次渲染还是更新的时候都会经验一个阶段叫commit阶段,这个阶段次要的工作就是解决一些钩子函数、生命周期、遍历render阶段造成的EffectList链表,将带有副作用的Fiber节点利用到实在节点上,如果对render阶段不理解能够参阅往期文章 render阶段 ,上面这张图是commit阶段源码的结构图,咱们具体的解说一下。 在commitRootImpl的函数中次要分三个局部: commit阶段前置工作mutation阶段 调用commitBeforeMutationEffects,scheduleCallback调度执行flushPassiveEffects调用commitMutationEffects,解决相干的副作用,操作实在节点useLayoutEffect的销毁函数在这个函数中执行调用commitLayoutEffects,调用commitLayoutEffects的回调函数,这个时候副作用曾经利用到实在节点了,所以能拿到最新的节点。在commit阶段完结之后flushPassiveEffects执行useEffect的销毁函数和回调函数。commit阶段收尾工作所以useLayout/componentDidMount和useEffect的区别是什么? 答:他们在commit阶段不同机会执行,useEffect在commit阶段结尾异步调用,useLayout/componentDidMount同步调用 相干参考视频解说:进入学习

February 20, 2023 · 1 min · jiezi

关于react.js:面试官你是怎样理解Fiber的

hello,这里是潇晨,明天咱们来聊一聊Fiber。不晓得大家面试的时候有没有遇到过和react Fiber相干的问题呢,这一类问题比拟凋谢,但也是考查对react源码了解深度的问题,如果面试高级前端岗,凑巧你平时用的是react,那这道面试题是你必须要会的一道。 大型利用为什么会慢那之前的利用为什么会慢呢,传统的前端利用例如js原生或者jquery利用,在构建简单的大型利用的时候,各种页面之前的互相操作和更新很有可能会引起页面的重绘或重排列,而频繁操作这些dom其实是十分耗费性能的 在看下图,这是一个节点上的属性,能够看到一个节点上的属性是十分多的,在简单利用中,操作这些属性的时候可能一不小心就会引起节点大量的更新,那如何进步利用的性能呢? const div = document.createElement('div');let str = ''for(let k in div){ str+=','+k}console.log(str) 为什么会呈现Fiberreact从15版本开始,到当初的17,以及快进去的18,外部经验了十分大的变动,这一切都是围绕着一个指标进行的,这个指标是异步可中断的更新,而这个目标的最终后果是为了构建疾速响应的利用。 简单利用在更新的时候可能会更新大量的dom,所以react在应用层和dom层之间减少了一层Fiber,而Fiber是在内存中工作的,所以在更新的时候只须要在内存中进行dom更新的比拟,最初再利用到须要更新实在节点上 这就引出了一个比照新老节点的过程,而比照两棵树的计算其实是十分耗费性能的,react提出了diff算法来升高比照的复杂度,具体diff的过程能够参考往期文章 diff算法 然而面对越来越简单的利用,diff算法耗费的工夫片还是很长,在没做出优化的状况下,react在进行Fiber的比照和更新节点上的状态的时候仍然力不从心, 在react15之前,这个比照的过程被称之为stack reconcile,它的比照形式是‘一条路走到黑’,也就是说这个比照的过程是不能被中断的,这会呈现什么状况呢,比方在页面渲染一个比拟耗费性能操作,如果这个时候如果用户进行一些操作就会呈现卡顿,利用就会显得不晦涩。react16之后呈现了scheduler,以及react17的Lane模型,它们能够配合着工作,将比拟耗时的工作依照Fiber节点划分成工作单元,并且遍历Fiber树计算或者更新节点上的状态能够被中断、持续,以及能够被高优先级的工作打断,比方用户触发的更新就是一个高优先级的工作,高优先级的工作优先执行,利用就不会太卡顿。什么是Fiber这就是react所要做的事件了,react翻新的提出了jsx,申明式地形容页面出现的成果,jsx会被babel通过ast解析成React.createElement,而React.createElement函数执行之后就是jsx对象或者说是virtual-dom 在mount的时候,也就是首次渲染的时候,render阶段会依据jsx对象生成新的Fiber节点,而后这些Fiber节点会被标记成带有‘Placement’的副作用,阐明它们是新增的节点,须要被插入到实在节点中,在commit阶段就会操作实在节点,将它们插入到dom树中。在update的时候,也就是利用触发更新的时候,render阶段会依据最新的jsx和老的Fiber进行比照,生成新的Fiber,这些Fiber会带有各种副作用,比方‘Deletion’、‘Update’、‘Placement’等,这一个比照的过程就是diff算法 ,在commit阶段会操作实在节点,执行相应的副作用。如果对render阶段和commit阶段不理解的能够查看往期文章 8.render阶段 10.commit阶段 Fiber有比拟多的含意,他能够从以下几个角度了解: 工作单元 工作合成 :Fiber最重要的性能就是作为工作单元,保留原生节点或者组件节点对应信息(包含优先级),这些节点通过指针的形似造成Fiber树增量渲染:通过jsx对象和current Fiber的比照,生成最小的差别补丁,利用到实在节点上依据优先级暂停、持续、排列优先级:Fiber节点上保留了优先级,能通过不同节点优先级的比照,达到工作的暂停、持续、排列优先级等能力,也为下层实现批量更新、Suspense提供了根底保留状态:因为Fiber能保留状态和更新的信息,所以就能实现函数组件的状态更新,也就是hooksFiber的数据结构Fiber的自带的属性如下: //ReactFiber.old.jsfunction FiberNode( tag: WorkTag, pendingProps: mixed, key: null | string, mode: TypeOfMode,) { //作为动态的数据结构 保留节点的信息 this.tag = tag;//对应组件的类型 this.key = key;//key属性 this.elementType = null;//元素类型 this.type = null;//func或者class this.stateNode = null;//实在dom节点 //作为fiber数架构 连接成fiber树 this.return = null;//指向父节点 this.child = null;//指向child this.sibling = null;//指向兄弟节点 this.index = 0; this.ref = null; //用作为工作单元 来计算state this.pendingProps = pendingProps; this.memoizedProps = null; this.updateQueue = null; this.memoizedState = null; this.dependencies = null; this.mode = mode; //effect相干 this.effectTag = NoEffect; this.nextEffect = null; this.firstEffect = null; this.lastEffect = null; //优先级相干的属性 this.lanes = NoLanes; this.childLanes = NoLanes; //current和workInProgress的指针 this.alternate = null;}Fiber是怎么工作的当初咱们晓得了Fiber能够保留实在的dom,实在dom对应在内存中的Fiber节点会造成Fiber树,这颗Fiber树在react中叫current Fiber,也就是以后dom树对应的Fiber树,而正在构建Fiber树叫workInProgress Fiber,这两颗树的节点通过alternate相连. ...

February 20, 2023 · 2 min · jiezi

关于react.js:百度前端必会react面试题总结

对 React 和 Vue 的了解,它们的异同相似之处: 都将注意力集中放弃在外围库,而将其余性能如路由和全局状态治理交给相干的库都有本人的构建工具,能让你失去一个依据最佳实际设置的我的项目模板。都应用了Virtual DOM(虚构DOM)进步重绘性能都有props的概念,容许组件间的数据传递都激励组件化利用,将利用分拆成一个个性能明确的模块,进步复用性不同之处: 1)数据流 Vue默认反对数据双向绑定,而React始终提倡单向数据流 2)虚构DOM Vue2.x开始引入"Virtual DOM",打消了和React在这方面的差别,然而在具体的细节还是有各自的特点。 Vue声称能够更快地计算出Virtual DOM的差别,这是因为它在渲染过程中,会跟踪每一个组件的依赖关系,不须要从新渲染整个组件树。对于React而言,每当利用的状态被扭转时,全副子组件都会从新渲染。当然,这能够通过 PureComponent/shouldComponentUpdate这个生命周期办法来进行管制,但Vue将此视为默认的优化。3)组件化 React与Vue最大的不同是模板的编写。 Vue激励写近似惯例HTML的模板。写起来很靠近规范 HTML元素,只是多了一些属性。React举荐你所有的模板通用JavaScript的语法扩大——JSX书写。具体来讲:React中render函数是反对闭包个性的,所以咱们import的组件在render中能够间接调用。然而在Vue中,因为模板中应用的数据都必须挂在 this 上进行一次直达,所以 import 完组件之后,还须要在 components 中再申明下。 4)监听数据变动的实现原理不同 Vue 通过 getter/setter 以及一些函数的劫持,能准确晓得数据变动,不须要特地的优化就能达到很好的性能React 默认是通过比拟援用的形式进行的,如果不优化(PureComponent/shouldComponentUpdate)可能导致大量不必要的vDOM的从新渲染。这是因为 Vue 应用的是可变数据,而React更强调数据的不可变。5)高阶组件 react能够通过高阶组件(Higher Order Components-- HOC)来扩大,而vue须要通过mixins来扩大。 起因高阶组件就是高阶函数,而React的组件自身就是纯正的函数,所以高阶函数对React来说大海捞针。相同Vue.js应用HTML模板创立视图组件,这时模板无奈无效的编译,因而Vue不采纳HOC来实现。 6)构建工具 两者都有本人的构建工具 React ==> Create React APPVue ==> vue-cli7)跨平台 React ==> React NativeVue ==> Weex生命周期调用办法的程序是什么?React生命周期分为三大周期,11个阶段,生命周期办法调用程序别离如下。(1)在创立期的五大阶段,调用办法的程序如下。 getDetaultProps:定义默认属性数据。getInitialState:初始化默认状态数据。component WillMount:组件行将被构建。render:渲染组件。componentDidMount:组件构建实现(2)在存在期的五大阶段,调用办法的程序如下。 componentWillReceiveProps:组件行将接管新的属性数据。shouldComponentUpdate:判断组件是否应该更新。componnent WillUpdate:组件行将更新。render:渲染组件。componentDidUpdate:组件更新实现。(3)在销毁期的一个阶段,调用办法 componentWillUnmount,示意组件行将被销毀。 React 如何辨别 Class组件 和 Function组件个别的形式是借助 typeof 和 Function.prototype.toString 来判断以后是不是 class,如下: function isClass(func) { return typeof func === 'function' && /^class\s/.test(Function.prototype.toString.call(func));}然而这个形式有它的局限性,因为如果用了 babel 等转换工具,将 class 写法全副转为 function 写法,下面的判断就会生效。 ...

February 20, 2023 · 3 min · jiezi

关于react.js:面试官你是怎样进行react组件代码复用的

mixinMixin 设计模式Mixin(混入)是一种通过扩大收集性能的形式,它实质上是将一个对象的属性拷贝到另一个对象下面去,能够拷贝多个属性到一个对象上,为了解决代码复用问题。 罕用的办法:JQuery 的 extend 办法。 var LogMixin = { log: function() { console.log('log'); }, componentDidMount: function() { console.log('in'); }, componentWillUnmount: function() { console.log('out'); }};var User = React.createClass({ mixins: [LogMixin], render: function() { return (<div>...</div>) }});var Goods = React.createClass({ mixins: [LogMixin], render: function() { return (<div>...</div>) }});毛病Mixin 可能会相互依赖,互相耦合,不利于代码保护不同的 Mixin 中的办法可能会互相抵触当初大量应用 ES6 语法后,React.createClass 曾经勾销,这种形式也不再举荐高阶组件(HOC)高阶组件的定义: 高阶组件(HOC)是 React 中用于复用组件逻辑的一种高级技巧。HOC 本身不是 React API 的一部分,它是一种基于 React 的组合个性而造成的设计模式。 (高阶组件是参数为组件,返回值为新组件的函数。)具体的意思就是:高阶组件能够看作 React 对装璜模式的一种实现,高阶组件就是一个函数,且该函数承受一个组件作为参数,并返回一个新的组件。他会返回一个加强的 React 组件。高阶组件能够让咱们的代码更具备复用性,逻辑性与抽象性,能够对 render 办法进行劫持,也能够管制 props 与 state。 ...

February 20, 2023 · 3 min · jiezi

关于react.js:面试官说说ReactSSR的原理

前言所谓同构,简而言之就是,第一次拜访后盾服务时,后盾间接把前端要显示的界面全副返回,而不是像 SPA 我的项目只渲染一个 <div id="root"></div> 剩下的都是靠 JavaScript 脚本去加载。这样一来能够大大减少首屏等待时间。 同构概念并不简单,它也非我的项目必需品,然而摸索它的原理却是必须的。 浏览本文须要你具备以下技术根底: Node.js 、 React 、 React Router 、 Redux 、 webpack 。 本文将分以下两局部去讲述: 同构思路剖析,让你对同构有一个概念上的理解;手写同构框架,深刻了解同构原理。同构思路CSR 客户端渲染CSR 客户端渲染,这个就是很好了解了,应用 React , React Router 前端本人管制路由的 SPA 我的项目,就能够了解成客户端渲染。它有一个十分大的劣势就是,只是首次拜访会申请后盾服务加载相应文件,之后的拜访都是前端本人判断 URL 展现相干组件,因而除了首次访问速度慢些之外,之后的访问速度都很快。 执行命令: create-react-app react-csr 创立一个 React SPA 单页面利用我的项目 。执行命令: npm run start 启动我的项目。 查看网页源代码: 只有一个 <div id="root"></div> 和 一些 script 脚本。最终出现进去的界面却是这样的: 原理很简略,置信学习过 webpack 的同学都晓得,那就是 webpack 把所有代码都打包成相应脚本并插入到 HTML 界面中,浏览器会解析 script 脚本,通过动静插入 DOM 的形式展现出相应界面。 客户端渲染的优劣势客户端渲染流程如下: 劣势: 前端负责渲染页面,后端负责实现接口,各自干好各自的事件,对开发效率有极大的晋升;前端在跳转界面的时候不须要申请后盾,减速了界面跳转的速度,进步用户体验。劣势: 因为须要期待 JS 文件加载以及后盾接口数据申请因而首屏加载工夫长,用户体验较差;因为大部分内容都是通过 JS 加载因而搜索引擎无奈爬取剖析网页内容导致网站无奈 SEO 。SSR 服务端渲染SSR 是服务端渲染技术,它自身是一项比拟一般的技术, Node.js 应用 ejs 模板引擎输入一个界面这就是服务端渲染。每次拜访一个路由都是申请后盾服务,从新加载文件渲染界面。 ...

February 20, 2023 · 7 min · jiezi

关于react.js:老大react说schedule我们今年的小目标是一个亿

hello,这里是潇晨,明天来讲个故事 讲个故事:从前,有家z公司,z公司的ceo叫react,它收下有个小弟或者叫小leader,schedule schedule每天负责消化老大react画的大饼,而后将拆解成一个个小小的task,给上面的小弟去实现,并且负责划分优先级,调度小弟们的工作排序。 那schedule怎么给这些工作划分优先级呢,它想了个最简略的方法,用deadline或者过期工夫,给这些task划分优先级,过期工夫越短阐明这个工作越紧急,连忙调配苦力(上面的小弟)去实现,过期工夫越长,阐明这个task越不紧急,能够当前缓缓干,还有一类task曾经过了它的deadline,这个过期的工作优先级最高,没方法,延期之后也是要实现的,可怜了程序员小哥哥了。 于是小leader,scheduler把老板的饼掰碎了,而后给这些小task依照deadline排了个优先级,于是程序员小哥哥开始接工作了 程序员小哥哥A承受了task1和task2,于是他给本人排了个工作清单,依照优先级先做task1,而后做task2,于是小哥进入密集开发中(render阶段),正在做task1 然而天又不测风云,老板依据业务的须要,给scheduler下达了一个十分紧急的需要,苦了程序员小哥了,scheduler说,唉,没方法呀,加加班,把这个十分紧急的需要现插个队吧,程序员小哥单线程的,每次只能做一个task,于是插个队,加加班做最紧急的需要task0吧。 接下来就是密集的加班中。。。(这一阶段称为render阶段) 终于在不屑的致力下,最终程序员小哥还是加班加点的把所有工作实现了,交给测试验证(commit阶段), 以上状况是有紧急任务时候的打断,还有一种状况是老板给的大饼很难消化,然而这个task2还没达到deadline,程序员小哥在做这个工作的时候遇到了艰难,所以就先放一放吧,反正是个艰巨的工作,在闲暇的时候在做吧,先实现优先级高的task0和task1,有工夫在做task2 进入正题:当咱们在相似上面的搜寻框组件进行搜寻时会发现,组件分为搜寻局部和搜寻后果展现列表,咱们冀望输入框能立即响应,搜素列表能够有期待的工夫,如果搜寻列表数据量很大,在进行渲染的时候,咱们又输出了一些文字,因为用户输出事件的优先级是很高的,所以就要进行后果列表的渲染,这就引出了不同工作之间的优先级和调度 Scheduler咱们晓得如果利用占用较长的js执行工夫,比方超过了设施一帧的工夫,那么设施的绘制就会呈现不晦涩的景象。 Scheduler次要的性能是工夫切片和调度优先级,react在比照节点差别的时候会占用肯定的js执行工夫,Scheduler外部借助MessageChannel实现了在浏览器绘制之前指定一个工夫片,如果react在指定工夫内没执行完差别的比照,Scheduler就会强制交出执行权给浏览器 工夫切片 在浏览器的一帧中js的执行工夫如下 requestIdleCallback是在浏览器重绘重排之后,如果还有闲暇就能够执行未实现的工作,所以为了不影响重绘重排,能够在浏览器在requestIdleCallback中执行耗性能的计算,然而因为requestIdleCallback存在兼容和触发机会不稳固的问题,scheduler中采纳MessageChannel来实现requestIdleCallback,如果以后环境不反对MessageChannel就采纳setTimeout。 在performUnitOfWork(render阶段的终点)之后会执行render阶段和commit阶段,如果在浏览器的一帧中,cup的计算还没实现,就会让出js执行权给浏览器,这个判断在workLoopConcurrent函数中,shouldYield就是用来判断残余的工夫有没有用尽。在源码中每个工夫片时5ms,这个值会依据设施的fps调整。 function workLoopConcurrent() { while (workInProgress !== null && !shouldYield()) {//如果fiber链还没遍历完,没有被暂停或者打断 performUnitOfWork(workInProgress);//执行render阶段 }}function forceFrameRate(fps) {//计算工夫片 if (fps < 0 || fps > 125) { console['error']( 'forceFrameRate takes a positive int between 0 and 125, ' + 'forcing frame rates higher than 125 fps is not supported', ); return; } if (fps > 0) { yieldInterval = Math.floor(1000 / fps); } else { yieldInterval = 5;//工夫片默认5ms }}工作的暂停在shouldYield函数中有一段,所以能够晓得,如果以后工夫大于工作开始的工夫+yieldInterval,就打断了工作的进行。 ...

February 19, 2023 · 2 min · jiezi

关于react.js:面试官react中的setState是同步的还是异步的

hello,这里是潇晨,大家在面试的过程是不是常常会遇到这样的问题,react的setState是同步的还是异步的,这个问题答复的时候肯定要残缺,来看上面这几个例子: 例子1:点击button触发更新,在handle函数中会调用两次setState export default class App extends React.Component { state = { num: 0, }; updateNum = () => { console.log("before", this.state.num); this.setState({ num: this.state.num + 1 }); this.setState({ num: this.state.num + 1 }); console.log("after", this.state.num); }; render() { const { num } = this.state; console.log("render", num); return <button onClick={this.updateNum}>hello {num}</button>; }}//打印后果//render 0//before 0//after 0//render 1例子2:例子1的两次setState在setTimeout回调中执行 export default class App extends React.Component { state = { num: 0, }; updateNum = () => { console.log("before", this.state.num); setTimeout(() => { this.setState({ num: this.state.num + 1 }); this.setState({ num: this.state.num + 1 }); console.log("after", this.state.num); }, 0); }; render() { const { num } = this.state; console.log("render", num); return <button onClick={this.updateNum}>hello {num}</button>; }}//打印后果//render 0//before 0//render 1//render 2//after 2例子3:用unstable_batchedUpdates在setTimout中执行,unstable_batchedUpdates的回调函数中调用两次setState ...

February 19, 2023 · 2 min · jiezi

关于react.js:面试官让你说说react状态管理

开发者普遍认为状态是组件的一部分, 然而同时却又在剥离状态上不停的造轮子, 这不是很矛盾么? 对于一个最简略的文本组件而言 function Text(){ const [text, setText] = useState('载入') return (){ <p>{text}</p> }}你感觉应该把 text 从 Text 组件中剥离么? 如果你的直觉通知你不应该这么做, 那为何要应用 redux mobx jotai 等等一系列稀奇古怪的状态治理库来让咱们的代码变得更简单? 所以 why? 还不是 React 本人的锅!!! 因为 React 在组件状态上给出了双重定义, 内敛的 state 和凋谢的 props.同时因为 jsx 的限度导致组件通信只能依赖 props. 有人会说还有 context, 但如果你为组件通信独自减少一层 provide, 那随着利用收缩, 你的状态会被 xml 构造割得支离破碎, 最初只剩下繁多 store 这颗有毒药丸. 因为 React 天生状态同步上的缺点, 才让状态治理这件事在 React 社区如此发达, 这其实是病态的. 想想战国时期群雄逐鹿吧. 还不是周天子失仪, 看看 Vue 就没有这么多狗屁倒灶的事. 状态治理生态的病态凋敝让整个 React 生态变得凌乱. 不同状态治理库之间潜在的集成老本, 以及围绕这些状态治理打造的组件库又须要思考集成. 看看 Route5 吧, 我感觉官网的 React 和 Redux 集成计划基本不够. 毕竟还有好几个库在那等着呢... ...

February 19, 2023 · 1 min · jiezi