精读《React Conf 2019 - Day1》

1 引言

React Conf 2019 在今年 10 月份举办,内容质量还是一如既往的高,如果想进一步学习前端或者 React,这个大会一定不能错过。

希望前端精读成为你学习成长路上的布道者,所以本期精读就介绍 React Conf 2019 - Day1 的相关内容。

总的来看,React Conf 今年的内容视野更广了,不仅仅有技术内容,还有宣扬公益、拓展到移动端、后端,最后还有对 web 发展的总结与展望。

前端世界正变得越来越复杂,可以看到大家对未来都充满了希望,永不停歇的探索精神是这场大会的主旋律。

2 概述 & 精读

本期大会思想、设计上的内容较多,具体实现层内容较少,因为行业领导者需要引领规范,而真正技术价值在于思维模型与算法,理解了解题思路,实现它其实并不难。

开发者体验与用户体验

  • 开发者体验:DX(develop experience)
  • 用户体验:UX(user experience)

技术人解决的问题总是围绕 DX 与 UX,而一般来说,优化了 DX 往往会带来 UX 的提升,这是因为一个解决开发者体验的技术创新往往也会带来用户体验的升级,至少也能让开发者有更好的心情、更充足的时间做出好产品。

如何优化开发者体验呢?

易上手

React 确实致力于解决这个问题,因为 React 实际上是一个开发者桥梁,无论你开发 web、ios 还是单片机,都可以通过一套统一的语法去实现。React 是一个协议标准(读到 reactReconciler 章节会更有体感),React 像 HTML,但 React 不止能构建 HTML 应用,React 希望构建一切。

高效开发

React 解决调试、工具问题,让开发者更高效的完成工作,这也是开发者体验重要组成部分。

弹性

React 编写的程序拥有良好可维护性,包括数据驱动、模块化等等特征都是为了更好服务于不同规模的团队。

对于 UX 问题,React 也有 Concurrent mode、Suspense 等方案。

虽然 React 还不完美,但 React 致力于解决 DX 与 UX 的目标和效果都是我们有目共睹的,更好的 DX、UX 一定是前端技术未来发展的大趋势。

样式方案

Facebook 使用 css-in-js,而今年的 React conf 给出了一种技术方案,将 413 kb 的样式文件体积降低到 74kb!

一步步了解这个方案,从用法开始:

const styles = stylex.create({blue: { color: "blue" },red: { color: "red" }
});function MyComponent(props) {return <span className={styles("blue", "red")}>I'm red now!</span>;
}

如上是这个方案的写法,通过 stylex.create 创建样式,通过 styles() 使用样式。

主题方案

如果使用 CSS 变量定义主题,那么换肤就可以由最外层 class 轻松决定了:

.old-school-theme {--link-text: blue;
}.text-link {color: var(--link-text);
}

字体颜色具体的值由外层 class 决定,因此外层的 class 就可以控制所有子元素的样式:

<div class="old-school-theme"><a class="text-link" href="...">I'm blue!</a>
</div>

将其封装成 React 组件,也不需要用 context 等 JS 能力,而是包裹一层 class 即可。

function ThemeProvider({ children, theme }) {return <div className={themes[theme]}>{children}</div>;
}

图标方案

下面是设计师给出的 svg 代码:

<svg viewBox="0 0 100 100"><path d="M9 25C8 25 8..." />
</svg>

将其包装为 React 组件:

function SettingsIcon(props) {return (<SVGIcon viewBox="0 0 100 100" {...props}><path d="M9 25C8 25 8..." /></SVGIcon>);
}

结合上面提到的主题方案,就可以控制 svg 的主题颜色。

const styles = stylex.create({primary: { fill: "var(--primary-icon)" },gighlight: { fill: "var(--highlight-icon)" }
});function SVGIcon(color, ...props) {return (<svg>{...props}className={styles({primary: color === "primary",highlight: color === "highlight"})}{children}</svg>);
}

减少样式大小的秘密

const styles = stylex.create({blue: { color: "blue" },default: { color: "red", fontSize: 16 }
});function MyComponent(props) {return <span className={styles("default", props.isBlue && "blue")} />;
}

对于上述样式文件代码,最终会编译成 c1c2c3 三个 class

.c1 {color: blue;
}
.c2 {color: red;
}
.c3 {font-size: 16px;
}

出乎意料的是,并没有根据 bluedefault 生成对应的 class,而是根据实际样式值生成 class,这样做有什么好处呢?

首先是加载顺序,class 生效的顺序与加载顺序有关,而按照样式值生成的 class 可以精确控制样式加载顺序,使其与书写顺序对应:

// 效果可能是 blue 而不是 red
<div className="blue red" />// 效果一定是 red,因为 css-in-js 在最终编排 class 时,虽然两种样式都存在,但书写顺序导致最后一个优先级最高,
// 合并的时候就会舍弃失效的那个 class
<div className={styles('blue', 'red')} />

这么做永远不会出现头疼的样式覆盖问题。

更重要的是,随着样式文件的增多,class 总量会减少。这是因为新增的 class 涵盖的属性可能已经被其他 class 写到并生成了,此时会直接复用对应属性生成的 class 而不会生成新的:

<Component1 className=".class1"/>
<Component2 className=".class2"/>
.class1 {background-color: mediumseagreen;cursor: default;margin-left: 0px;
}
.class2 {background-color: thistle;cursor: default;justify-self: flex-start;margin-left: 0px;
}

正如这个 Demo 所示,正常情况的 class1class2 存在许多重复定义的属性,但换成 css-in-js 的方案,编译后的效果等价于将 class 复用并拆解了:

<Component1 classNames=".classA .classB .classD"><Component2 classNames=".classA .classC .classD .classE">
.classA {cursor: default;
}
.classB {background-color: mediumseagreen;
}
.classC {background-color: thistle;
}
.classD {margin-left: 0px;
}
.classE {justify-self: flex-start;
}

这种方式不仅节省空间、还能自动计算样式优先级避免冲突,并将 413 kb 的样式文件体积降低到 74kb。

字体大小方案

rem 的好处是相对的字体大小,使用 rem 作为单位可以很方便实现网页字体大小的切换。

但问题是现在工业设计都习惯了以 px 作为单位,所以一种全新的编译方案产生了:在编译阶段将 px 自动转换成 rem

这等于让以 px 为单位的字体大小可以跟随根节点字体大小随意缩放。

代码检测

静态检测类型错误、拼写错误、浏览器兼容问题。

在线检测 dom 节点元素问题,比如是否有可访问性,比如替代文案 aria-label。

提升加载速度

普通网页的加载流程是这样的:

先加载代码,然后会渲染页面,在渲染的同时发取数请求,等取数完成后才能渲染出真实数据。

那么如何改善这个情况呢?首先是预取数,提前解析出请求并在脚本加载的同时取数,可以节省大量时间:

那么下载的代码可以再拆分吗?注意到并不是所有代码都作用于 UI 渲染,我们可以将模块分为 ImportForDisplayimportForAfterDisplay

这样就可以优先加载与 UI 相关的代码,其余逻辑代码在页面展示出之后再加载:

这样可以实现源码分段加载,并分段渲染:

对取数来说也是如此,并不是所有取数都是初始化渲染阶段必须用上的。可以通过 relay 的特性 @defer 标记出可以延迟加载的数据:

fragment ProfileData on User {classNameprofile_picture { ... }...AdditionalData @defer
}

这下取数也可以分段了,首屏的数据会优先加载:

利用 relay 还可以以数据驱动方式结合代码拆分:

... on Post {... on PhotoPost {@module('PhotoComponent.js')photo_data}... on VideoPost {@module('VideoComponent.js')video_data}... on SongPost {@module('SongComponent.js')song_data}
}

这样首屏数据中也只会按需加载用到的部分,请求时间可以再次缩短:

可以看到,与 relay 结合可以进一步优化加载性能。

加载体验

可以 React.SuspenseReact.lazy 动态加载组件。通过 fallback 指定元素的占位图可以提升加载体验:

<React.Suspense fallback={<MyPlaceholder />}><Post><Header /><Body /><Reactions /><Comments /></Post>
</React.Suspense>

Suspense 可以被嵌套,资源会按嵌套顺序加载,保证一个自然的视觉连贯性。

智能文档

通过解析 Markdown 自动生成文档大家已经很熟悉了,也有很多现成的工具可以用,但这次分享的文档系统有意思之处在于,可以动态修改源码并实时生效。

不仅如此,还利用了 Typescript + MonacoEditor 在网页上做语法检测与 API 自动提示,这种文档体验上升了一个档次。

虽然没有透露技术实现细节,但从热更新的操作来看像是把编译工作放在了浏览器 web worker 中,如果是这种实现方式,原理与 CodeSandbox 实现原理 类似。

GraphQL and Stuff

这一段在安利利用接口自动生成 Typescript 代码提升前后端联调效率的工具,比如 go2dts。

我们团队也开源了基于 swagger 的 Typescript 接口自动生成工具 pont,欢迎使用。

React Reconciler

这是知识密度最大的一节,介绍了如何使用 React Reconclier。

React Reconclier 可以创建基于任何平台的 React 渲染器,也可以理解为通过 React Reconclier 可以创建自定义的 ReactDOM。

比如下面的例子,我们尝试用自定义函数 ReactDOMMini 渲染 React 组件:

import React from "react";
import logo from "./logo.svg";
import ReactDOMMini from "./react-dom-mini";
import "./App.css";function App() {const [showLogo, setShowLogo] = React.useState(true);let [color, setColor] = React.useState("red");React.useEffect(() => {let colors = ["red", "green", "blue"];let i = 0;let interval = setInterval(() => {i++;setColor(colors[i % 3]);}, 1000);return () => clearInterval(interval);});return (<divclassName="App"onClick={() => {setShowLogo(show => !show);}}><header className="App-header">{showLogo && <img src={logo} className="App-logo" alt="logo /" />}// 自创语法<p bgColor={color}>Edit <code>src/App.js</code> and save to reload.</p><aclassName="App-link"href="https://reactjs.org"target="_blank"rel="noopener noreferrer">Learn React{" "}</a></header></div>);
}ReactDOMMini.render(<App />, codument.getElementById("root"));

ReactDOMMini 是利用 ReactReconciler 生成的自定义组件渲染函数,下面是完整的代码:

import ReactReconciler from "react-reconciler";const reconciler = ReactReconciler({createInstance(type,props,rootContainerInstance,hostContext,internalInstanceHandle) {const el = document.createElement(type);["alt", "className", "href", "rel", "src", "target"].forEach(key => {if (props[key]) {el[key] = props[key];}});// React 事件代理if (props.onClick) {el.addEventListener("click", props.onClick);}// 自创 api bgColorif (props.bgColor) {el.style.backgroundColor = props.bgColor;}return el;},createTextInstance(text,rootContainerInstance,hostContext,internalInstanceHandle) {return document.createTextNode(text);},appendChildToContainer(container, child) {container.appendChild(child);},appendChild(parent, child) {parent.appendChild(child);},appendInitialChild(parent, child) {parent.appendChild(child);},removeChildFromContainer(container, child) {container.removeChild(child);},removeChild(parent, child) {parent.removeChild(child);},insertInContainerBefore(container, child, before) {container.insertBefore(child, before);},insertBefore(parent, child, before) {parent.insertBefore(child, before);},prepareUpdate(instance,type,oldProps,newProps,rootContainerInstance,currentHostContext) {let payload;if (oldProps.bgColor !== newProps.bgColor) {payload = { newBgCOlor: newProps.bgColor };}return payload;},commitUpdate(instance,updatePayload,type,oldProps,newProps,finishedWork) {if (updatePayload.newBgColor) {instance.style.backgroundColor = updatePayload.newBgColor;}}
});const ReactDOMMini = {render(wahtToRender, div) {const container = reconciler.createContainer(div, false, false);reconciler.updateContainer(whatToRender, container, null, null);}
};export default ReactDOMMini;

笔者拆解一下说明:

React 之所以具备跨平台特性,是因为其渲染函数 ReactReconciler 只关心如何组织组件与组件间关系,而不关心具体实现,所以会暴露出一系列回调函数。

创建实例

由于 React 组件本质是一个描述,即 tag + 属性,所以 Reconciler 不关心元素是如何创建的,需要通过 createInstance 拿到组件基本属性,在 Web 平台利用 DOM API 实现:

createInstance(type,props,rootContainerInstance,hostContext,internalInstanceHandle) {const el = document.createElement(type);["alt", "className", "href", "rel", "src", "target"].forEach(key => {if (props[key]) {el[key] = props[key];}});// React 事件代理if (props.onClick) {el.addEventListener("click", props.onClick);}// 自创 api bgColorif (props.bgColor) {el.style.backgroundColor = props.bgColor;}return el;}

之所以说 React 对 DOM 事件都做了一层代理,是因为 JSX 的所有函数都没有真正透传给 DOM,而是通过类似 el.addEventListener("click", props.onClick) 的方式代理实现的。

而自定义这个函数,我们甚至能创建例如 bgColor 这种特殊语法,只要解析引擎实现了这个语法的 Handler。

除此之外,还有 创建、删除实例 的回调函数,我们都要利用 DOM 平台的 API 重新实现一遍,这样不仅可以实现对浏览器 API 的兼容,还可以对接到比如 react-native 等非 WEB 平台。

更新组件

实现了 prepareUpdatecommitUpdate 才能完成组件更新。

prepareUpdate 返回的 payloadcommitUpdate 函数接收到,并根据接收到的信息决定如何更新实例节点。这个实例节点就是 createInstance 回调函数返回的对象,所以如果在 WEB 环境返回的 instance 就是 DOMInstance,后续所有操作都使用 DOMAPI。

总结一下:react 主要用平台无关的语法生成具有业务含义的 AST,而利用 react-reconciler 生成的渲染函数可以解析这个 AST,并提供了一系列回调函数实现完整的 UI 渲染功能,react-dom 现在也是基于 react-reconciler 写的。

图标体积优化

Facebook 团队通过优化,将图标大小从 4046.05KB 降低到了 132.95kb,体积减少了惊人的 96.7%,减少体积占总包体积的 19.6%!

实现方式很简单,下面是原始图标使用的代码:

<FontAwesomeIcon icon="coffee" />
<Icon icon={["fab", "twitter"]} />
<Button leftIcon="user" />
<FeatureGroup.Item icon="info" />
<FeatureGroup.Item icon={["fail", "info"]} />

在编译期间通过 AST 分析,将所有字符串引用换成了图标实例的引用,利用 webpack 的 tree-shaking 功能实现按需加载,从而删除了没有使用到的图标。

import {faCoffee,faInfo,faUser} from "@fontawesome/free-solid-svg-icons"
import {faTwitter} from '@fontawesome/free-brands-svg-icons'
import {faInfo as faInfoFal} from '@fontawesome/pro-light-svg-icons'<FontAwesomeIcon icon={faCoffee} />
<Icon icon={faTwitter} />
<Button leftIcon={faUser} />
<FeatureGroup.Item icon={faInfo} />
<FeatureGroup.Item icon={faInfoFal} />

替换工具 的链接放出来了,感兴趣的同学可以点进去了解更多。

这也从某种意义上说明了 iconFont 注定被淘汰,因为字体文件目前无法按需加载,只有全部使用 SVG 图标的项目才能使用这种优化。

Git & Github

这一节介绍了基本 Git 知识以及 Github 用法,笔者略过比较水的部分,直接列出两个可能你不知道的点:

干预 Github 项目主要语言检测

如果你提交的代码包含许多自动生成的文件,可能你实际使用的语言不会被 Github 解析为主要语言,这时候可以通过 .gitattributes 文件忽略指定文件夹的检测:

static/* linguist-vendored

这样语言文件占比统计就会忽略 static/ 文件夹。

Git hooks 的技巧

以下是几个比较具有启发的点,我们可以利用 Git hooks 做点什么:

  • 阻止提交到 master。
  • 在 commit 之前执行 prettier/eslint/jest 检测。
  • 检测代码规范、合并冲突、检测是否有大文件。
  • commit 成功后给出提示或记录到日志。

但 Git hooks 仍然有局限性:

  • 容易被绕过:–no-verifuy --no-merge --no-checkout —force。
  • 本地 hooks 无法提交,导致项目开发规则可能不尽相同。
  • 无法替代 CI、服务端分支保护、Code Review。

可以畅想一下,在 WebIDE 环境可以通过自定义 git 命令禁止检测绕过,自然解决第二条环境不一致的问题。

GraphQL + Typescript

GraphQL 是没有类型支持的,如果要手动创建一遍类型文件是非常痛苦的:

interface GetArticleData {getArticle: {id: number;title: string;};
}const query = graphql(gql`query getArticle {article {idtitle}}
`);apolloClient.query<GetArticleData>(query);

同样的代码分散在两处维护一定会带来问题,我们可以利用比如 typed-graphqlify 这种库解决类型问题:

import { params, types, query } from "typed-graphqlify";const getArticleQuery = {article: params({id: types.number,title: types.string})
};const gqlString = query("getUser", getUserQuery);

只要一遍定义就可以自动生成 GQLString,并且拿到 Typescript 类型。

React 文档国际化

即便是谷歌翻译也不是很靠谱,国际化文档还是要靠人肉,Nat Alison 利用 Github 充分发动各国人民的力量,共同打造了一个个 reactjs group 下的国际化仓库。

国际化仓库命名规则是 reactjs/xx.reactjs.org,比如简体中文的国际化仓库是:https://github.com/reactjs/zh-hans.reactjs.org

从仓库的 readme 可以看到维护规则是这样的:

  • 请 fork 这个仓库。
  • 基于 fork 后的仓库中 master 分支拉取一个新的分支(名字自取)。
  • 翻译(校对)你所选择的文章,提交到新的分支。
  • 此时提交 Pull Request 到该仓库。
  • 会有专人 Review 该 Pull Request,当两人以上通过该 Pull Request 时,你的翻译将被合并到仓库中。
  • 删除你所创建的分支(如继续参与,参考同步流程)。

之后定期从 React 官方文档项目拉取最新代码即可保持文档的同步更新。

你需要 redux 吗?

关于数据流的话题目前没有什么新意,但这次 React Conf 关于数据流总结的算是比较真诚的,总结了以下几个点:

  1. 全局数据流现在不是必须的,比如 Redux,但也不能说完全不能用,至少在全局状态较为复杂时有必要使用。
  2. 不要只使用一种数据流方案,根据状态的作用域确定方案比较好。
  3. 工程技术与科学不同,工程世界没有最好的方案,只有更好的方案。
  4. 就算有了完美方案也不要停止学习的步伐,总会有新知识产生。

web 历史

很精彩的演讲,不过新鲜内容并不多,比较有感触一点是:以前的网页地址对应到的是服务器磁盘的某个具体文件,比如早期 php 应用,现在后端不再是文件化而是服务化了,这层抽象让服务端摆脱了对文件结构的依赖,可以构建更多复杂动态逻辑,也支持了前后端分离的技术方案。

3 总结

这届 React Conf 让我们看到前端更多的可能性,我们不仅要关注技术实现细节,更要关注行业标准以及团队愿景。

React 团队的愿景是让 React 包罗万象,提升全球开发者的开发体验、提升全球产品的用户体验,基于这个目标,React Conf 自然不能只包含 DOM Diff、Reconciler 等等技术细节,更需要展示 React 如何帮助全球开发者,如何让这些开发者帮助到用户,如何推动行业标准的演进,如何让 React 打破国界、语言的壁垒。

相比其他前端大会非常多的干货来说,React Conf 虽然显得主题比较杂,但这正是人文情怀的体现,我相信只有带着更高的使命愿景,真诚帮助他人的技术团队才可以走得更远。

讨论地址是:精读《React Conf 2019 - Day1》 · Issue #214 · dt-fe/weekly

如果你想参与讨论,请 点击这里,每周都有新的主题,周末或周一发布。前端精读 - 帮你筛选靠谱的内容。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/726877.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

2024主流测试工具测评,总有一款适合你!

大家好&#xff01;我是测试元宝~ 在软件开发周期中&#xff0c;测试是确保产品质量的关键环节。随着企业对于软件质量的要求日益提升&#xff0c;测试人员面临着前所未有的挑战&#xff0c;“工欲善其事必先利其器”&#xff0c;选择一款高效、实用的软件测试工具&#xff0c…

LeetCode # 547. 省份数量

547. 省份数量 题目 有 n 个城市&#xff0c;其中一些彼此相连&#xff0c;另一些没有相连。如果城市 a 与城市 b 直接相连&#xff0c;且城市 b 与城市 c 直接相连&#xff0c;那么城市 a 与城市 c 间接相连。 省份 是一组直接或间接相连的城市&#xff0c;组内不含其他没有…

Git 基于ED25519、RSA算法生成 SSH 密钥

Git 基于ED25519、RSA算法生成 SSH 密钥 基于ED25519算法&#xff0c;生成密钥对命令如下&#xff1a; ssh-keygen -t ed25519 -C "邮箱地址"基于RSA算法&#xff0c;生成密钥对命令如下&#xff1a; ssh-keygen -t rsa -C "<注释内容>"基于ED255…

若依集成MybatisPlus步骤

目录 一、新建业务模块二、集成MybatisPlus三、测试 一、新建业务模块 新建Maven模块&#xff0c;并建立如下目录 新模块的pom.xml添加如下内容 <description>业务模块</description><dependencies><!-- Mysql驱动包 --><dependency><groupI…

Locust中wait_time中匿名函数使用方法浅析

前言 翻出之前做个压测项&#xff0c;看到locust中对等待时间的实现方式感到好奇&#xff0c;于是总结下来。 源代码实现 def between(min_wait, max_wait):"""Returns a function that will return a random number between min_wait and max_wait.Example:…

thinkphp学习12-数据库的时间查询

传统方式 可以使用>、<、>、<来筛选匹配时间的数据&#xff1b; public function index() {$res Db::name(user)->where(create_time, >, 2018-1-1)->select();dump($res); }可以使用 between 关键字来设置时间的区间&#xff1b; public function in…

如何在Linux系统部署MeterSphere服务并配置固定公网访问地址

文章目录 推荐 前言1. 安装MeterSphere2. 本地访问MeterSphere3. 安装 cpolar内网穿透软件4. 配置MeterSphere公网访问地址5. 公网远程访问MeterSphere6. 固定MeterSphere公网地址 推荐 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#…

影响APP广告变现收益的4个关键因素

APP的广告收入&#xff08;IAA&#xff09;展示 * eCPM/1000 IAA收入其实是由广告总展示量和每次展示的平均收入共同决定的。所以&#xff0c;提高IAA收入&#xff0c;我们需要双管齐下&#xff1a;同时提高广告总展示量和平均每次展示的收入。 app广告变现对接点击⬇️链接&…

单机版openstack安装

说明&#xff1a; 本文环境&#xff1a;CentOS 7 x64位 1.创建虚拟机 2.在虚拟机中安装 centos 7&#xff08;最小安装&#xff09;&#xff0c;修改主机名&#xff1a;openstack&#xff0c;设置 root 密码&#xff1a;12345678 3. 网卡设置&#xff0c;重启网络服务&#…

20240306-1-大数据的几个面试题目

面试题目 1. 相同URL 题目: 给定a、b两个文件&#xff0c;各存放50亿个url&#xff0c;每个url各占64字节&#xff0c;内存限制是4G&#xff0c;让你找出a、b文件共同的url&#xff1f; 方案1&#xff1a;估计每个文件的大小为50G64320G&#xff0c;远远大于内存限制的4G。所以…

VUE前端问题

一、图表内容不显示 watch: {chartData3: {handler() {this.init();},},timeData3: {handler() {this.init();},},}, 添加上面代码可以动态监控数据&#xff0c;实现图表的展示。 二、背景图片报错显示不出来 解决方法&#xff1a; background: url(~/assets/login/e.png) …

Day23:安全开发-PHP应用后台模块SessionCookieToken身份验证唯一性

目录 具体安全知识点 身份验证-Cookie使用 身份验证-Session使用 唯一性判断-Token使用 总结 源码 思维导图 PHP知识点&#xff1a; 功能&#xff1a;新闻列表&#xff0c;会员中心&#xff0c;资源下载&#xff0c;留言版&#xff0c;后台模块&#xff0c;模版引用&…

Mysql date_format 格式化时间输出

网上的文章都是列一个大而全的表格&#xff0c;还有错误&#xff0c;我完全用不到那么多形式。遂自己开篇文章记录。 把datetime格式化为形如 2024-12-15 18:59:59的形式&#xff1a; %Y-%m-%d %H:%i:%S# 日期格式化输出select date_format(now(),%Y-%m-%d %H:%i:%S) time1,no…

C语言指针总结(完结篇)

前言 这篇博客终于迎来了指针博客的大结局&#xff0c;本篇主要分析习题来回顾之前的指针总结的知识点&#xff0c;这篇博客的题有点绕&#xff0c;哈哈算是经典了 个人主页&#xff1a;小张同学zkf 若有问题 评论区见 感兴趣就关注一下吧 目录 1. sizeof和strlen的对比 1.1 …

开源爬虫技术在金融行业市场分析中的应用与实战解析

一、项目介绍 在当今信息技术飞速发展的时代&#xff0c;数据已成为企业最宝贵的资产之一。特别是在${industry}领域&#xff0c;海量数据的获取和分析对于企业洞察市场趋势、优化产品和服务至关重要。在这样的背景下&#xff0c;爬虫技术应运而生&#xff0c;它能够高效地从互…

企业级数字人形象自定义解决方案

在品牌传播、线上营销等领域&#xff0c;一个独特且符合企业形象的数字人形象&#xff0c;无疑能为企业带来更强的品牌识别度和市场竞争力。美摄科技&#xff0c;作为业界领先的数字人形象解决方案提供商&#xff0c;凭借多年的技术积累和深厚的行业经验&#xff0c;推出了一套…

Linux第68步_旧字符设备驱动的一般模板

file_operations结构体中的函数就是我们要实现的具体操作函数。 注意&#xff1a; register_chrdev()和 unregister_chrdev()这两个函数是老版本驱动使用的。现在新字符设备驱动已经不再使用这两个函数&#xff0c;而是使用Linux内核推荐的新字符设备驱动API函数。 1、创建C…

公众号公司主体变更如何操作?

公众号迁移有什么用&#xff1f;只能改主体吗&#xff1f;好多朋友都想做公众号迁移&#xff0c;但是又不太清楚具体有啥用&#xff0c;今天我就来详细说说。首先&#xff0c;公众号迁移最重要的作用就是可以修改主体。比如你的公众号原来是 A 公司的&#xff0c;现在 A 公司不…

SpringCloud(20)之Skywalking Agent原理剖析

一、Agent原理剖析 使用Skywalking的时候&#xff0c;并没有修改程序中任何一行 Java 代码&#xff0c;这里便使用到了 Java Agent 技术&#xff0c;我 们接下来展开对Java Agent 技术的学习。 1.1 Java Agent Java Agent 是从 JDK1.5 开始引入的&#xff0c;算是一个比较老的…