2019年人工智能系统学:
https://edu.csdn.net/topic/ai30?utm_source=csdn_bw
BAT中,谁是老大不好说,但是论争议性,百度确实相对较多。
一方面,“百度搜索引擎已死”的说法愈演愈烈;
另一方面,许多优秀的开发者都出身自百度,其更是在当下火热的人工智能领域再一次获得AI的黄埔军校之称。
而百度最近又凭着春晚红包,上了不少头条。
在今年的春晚红包活动中,百度用十万台服务器,扛住了峰值每秒5000万的流量。
由此成为BAT中唯一一家春晚发红包不宕机的厂商。
那么,百度在BAT中“到底算老几”?
3月3日,李彦宏又被记者问起了该问题。
记者:“李总,您认为百度在BAT里占据怎么样的位置?”
李彦宏:“百度还是专注于我们自己擅长的技术创新,大概八九年以前,我们就开始大规模的投入人工智能技术的研发。这几年研发投入占总收入的15%左右,这应该是国内主流公司里面研发占比最高的。”
记者:“有人说百度被落下了,您是不认同的,对吧?”
李彦宏:“我们还是专注于自己最擅长的事情吧,有些机会是属于我们的,有些机会是不属于我们的。不可能每个机会都属于百度。”
记者:“哪些机会是不属于百度的呢?”
李彦宏:“就是技术含量没有那么高的,我们做起来就相对困难一点。技术含量比较高的,像无人驾驶汽车,像智能助力、智能音箱,这些是百度比较擅长的。”
李彦宏当时接受采访的视频,视频来源梨视频
正是这样反向的谦虚,再次让李彦宏陷入一场小小的舆论风波。
细数过往,李彦宏虽然公众发言没有马云多,但却比马云更多地因为“说话耿直”上新闻。
去年他说“国人不在乎隐私”,便引起滔天争议。
而这次网友们在微博上也是各种怼。
但是部分网友还是很认可百度的AI和春晚的战绩。
都说百度的技术、阿里的运营、腾讯的产品。
为什么百度技术强?
这并不难理解,毕竟总部在北京,一方面拥有全国最牛高校群的北京,每年都在给百度等大厂输送人才;另一方面,北京的城市属性,决定了它可以吸引全国的人才往这儿涌。
而由杭州、深圳起家的阿里及腾讯在这一先天条件上已稍逊于百度。
拥有精兵良将的百度,这些年确实在技术上打了不少漂亮战。
搜索和信息流作为百度的看家本领自不必说,毕竟这方面百度在国内是孤独的成功者。
其他方面是骡子是马,还得战场上遛一遛。
OK,打开你的时光机,让我们来到几年前的云盘恶战。
云盘恶战的胜利者
没有硝烟的战争,时间尤其长。从2012年到2016年,那场足以载入国内科技史的云盘大战,持续了整整四年。
百度网盘甫一面世,就面临着山雨欲来风满楼。
当时,华为、金山、115、华硕等一众厂商,纷纷推出个人云存储服务。
各家云为了抢用户,在扩容上杀红了眼,金山快盘出50G,UC云盘出2TB,115云盘出8TB,腾讯出10TB,360延续了红衣教主的吓死人风格,一出手就是36TB。
鏖战到此戛然而止。
暴风雨中的忽然宁静,往往意味着更大的动静。
据自媒体“朱思码记”报道,“2016年3月4日,115网盘最先传出停用部分功能的消息。14天后,阿里巴巴旗下UC网盘宣布关闭。4月25日,新浪微盘宣布关闭,次日金山快盘宣布关闭。5月3日,华为网盘停止用户数据存储分享服务,24天后腾讯微云的突然关闭更令人感到不可思议。”当年10月,“360不仅关闭了个人云盘服务,还公告将在次年2月1日清空全部用户数据,并注销所有云盘账号。”
过山车一般的结局就此诞生——后入场的百度网盘,反而活了下来。
养兵千日用兵一时,若不是百度一直在强化技术,怕也赢不了。
BAT中百度做AI似乎最顺理成章
BAT三家都在做AI。
在棋子落定AI之前,百度没少试错。
因为痛惜错过移动互联网,于是学别人做糯米、做外卖、做音乐、做移动支付,但是这些都没成。
都没成,不是因为失败在技术上,笔者认为,很大一部分原因是因为百度没有做运营的基因。
所以,李彦宏调整舵头转向AI,不仅做了自己擅长的事儿,还顺应了历史趋势,特别是将AI和汽车结合起来。
毕竟,汽车在国人眼中,正在变得像手机一样普通。
今年过年回老家,笔者大哥劝我赶快考下驾照,他说:“你得赶紧考啦!现在人们学开车,就像几年前学电动车一样。”
的确如此,我所在的豫西小村,大约十年前开始流行电动车,大约五年前,基本家家都有电动车。
到现在,村里平均几户都会有一辆小轿车。
这样来看,百度做的以Apollo自动驾驶为代表的无人驾驶,尽管暂时无法普及开来,但是在未来,前景十分可观。
不仅是汽车,百度的DuerOS智能家居、智能交通方案、工业人工智能和城市智能,都是和人类生活强关联的项目。
而百度2月份公布的2018年四季度、及全年未经审计财报,也证实了AI的变现能力。
这份财报显示,搜索和信息流的盈利仍在增多,云和AI亦开始小步慢跑。
结语
这几年,百度确实没有阿里腾讯那么耀眼,其内部也不是没有过担心出局BAT的恐慌。
但是从宏观上看,国内最牛的互联网巨头们,要是一直是BAT,对市场不好,对用户也不好。
历史规律也证明,没有永恒的前排。头条系就是最好的明证。
所以,BAT中有人相对落后是必然。
但是对于百度来说,“外面没有别人,只有自己。”
以上。
参考文章:
-
朱思码记《百度技术战略10年:2008-2018》
-
浅黑科技《百度的春晚战事:如何扛住腾讯、阿里都宕机的量?》
-
深几度《用户红利到技术红利,百度磨亮 AI 之刃开切中国互联网新蛋糕》
【End】
热
人工智能的现状及今后发展趋势如何?
https://edu.csdn.net/topic/ai30?utm_source=csdn_bw
文 推 荐
☞ TIOBE 3 月编程语言排行榜:主流 Java、C++ 惨遭嫌弃,Python 势头迅猛
☞ 中国开发者真实现状:40 岁不做开发,算法工程师最稀缺!
☞ 阿里云又宕机!
☞13 岁编程!少年比尔·盖茨如何成为最成功的自学成才程序员?
☞ 云评测 | 开发者最有用的开源云监控工具有哪些呢? 这7款神器总有一款适合你!
☞ 中央音乐学院招音乐AI方向博士生,玩一把代码与音符齐飞?
print_r('点个好看吧!');
var_dump('点个好看吧!');
NSLog(@"点个好看吧!");
System.out.println("点个好看吧!");
console.log("点个好看吧!");
print("点个好看吧!");
printf("点个好看吧!\n");
cout << "点个好看吧!" << endl;
Console.WriteLine("点个好看吧!");
fmt.Println("点个好看吧!");
Response.Write("点个好看吧!");
alert("点个好看吧!")
echo "点个好看吧!"
点击阅读原文,输入关键词,即可搜索您想要的 CSDN 文章!
喜欢就点击“好看”吧!


前面很多地方的文章,其实提到了这个东西,本教程会系统一点来帮助从未接触过 GUI 开发、或者熟悉 JavaScript 但未使用过 Reactor 的开发者快速上手,所以细节看文档,这会全面一些介绍大体上开发过程中用得到的知识。
什么是 Reactor?
简单来说,Sciter.js Reactor 不是一个框架或库,而是 Sciter.js 内置的一组功能,它借鉴了 ReactJS 的核心思想,让你能够用声明式的方式构建用户界面。
它主要包含两个核心特性:
- 原生 JSX 支持: 你可以直接在 JavaScript 代码中编写类似 HTML 的 JSX 语法,无需任何额外的编译步骤。
- 高效的 DOM 更新: 通过
element.patch(jsx)
方法,Reactor 能够智能地比较虚拟 DOM (JSX 表达式的结果) 和真实 DOM 的差异,并只更新必要的部分,从而实现高效的 UI 渲染。
为什么选择 Reactor?
- 原生集成: 无需引入外部库,开箱即用。
- 简洁高效: 语法简洁,性能优异,尤其适合桌面应用开发。
- ReactJS 相似性: 如果你熟悉 ReactJS,你会发现很多概念是相通的,上手会更快。
- 桌面 UI 优化: 针对桌面 UI 的特点进行了优化,例如支持窗口化弹出元素等。
核心概念
1. JSX (JavaScript XML)
JSX 允许你在 JavaScript 代码中编写 UI 结构,就像写 HTML 一样。
javascript 代码解读复制代码// 一个简单的 JSX 表达式
const greeting = <h1>你好, Sciter!h1>;
document.body.append(greeting); // 将 JSX 渲染到页面
关键点:
- JSX 标签可以是标准的 HTML 标签 (如 ,
),也可以是自定义组件。
- 可以在 JSX 中使用
{}
嵌入 JavaScript 表达式。- 组件名称必须以大写字母开头。
2. 组件 (Components)
组件是 Reactor 应用的基本构建块。它们是可重用的 UI 单元,可以接收输入数据 (称为
props
) 并返回要在屏幕上显示的虚拟元素。函数组件 (Function Components): 最简单的方式是使用函数定义组件。
javascript代码解读复制代码// 一个简单的函数组件 function Welcome(props) { return <h1>你好, {props.name}!h1>; } // 使用组件 document.body.patch(<Welcome name="开发者" />);
类组件 (Class Components): 你也可以使用 ES6 类来定义组件。类组件通常用于需要管理自身状态或使用生命周期方法的场景。
javascript代码解读复制代码class Clock extends Element { // 构造函数,初始化状态 constructor() { super(); this.time = new Date(); } // 生命周期方法:组件挂载到 DOM 后调用 componentDidMount() { this.timerId = setInterval(() => { // 更新组件状态 this.componentUpdate({ time: new Date() }); }, 1000); } // 生命周期方法:组件从 DOM 卸载前调用 componentWillUnmount() { clearInterval(this.timerId); } // 渲染方法:返回要显示的 JSX render() { return <p>当前时间: {this.time.toLocaleTimeString()}p>; } } // 使用类组件 document.body.patch(<Clock />);
关键点:
- 组件可以将 UI 拆分成独立、可复用的部分。
props
是从父组件传递给子组件的数据,是只读的。- 类组件通过
this
访问props
和自身状态。
3. 渲染 (Rendering) 与
element.patch()
Reactor 使用
element.patch(jsx)
方法将 JSX 描述的 UI 更新到真实的 DOM 上。它会进行高效的 diff 算法,只更新变化的部分。javascript代码解读复制代码function tick() { const element = ( <div> <h1>你好, 世界!h1> <h2>现在是 {new Date().toLocaleTimeString()}.h2> div> ); document.body.patch(element); // 高效更新 DOM } setInterval(tick, 1000);
4. 状态 (State) 与
componentUpdate()
对于类组件,可以使用
this
来存储组件的内部状态。当状态需要改变时,必须 调用this.componentUpdate(newState)
方法来通知 Reactor 更新 UI。javascript代码解读复制代码class Counter extends Element { count = 0; // 初始化状态 increment() { // 使用 componentUpdate 更新状态 this.componentUpdate({ count: this.count + 1 }); } render() { return ( <div> <p>点击次数: {this.count}p> <button onclick={() => this.increment()}>点击我button> div> ); } } document.body.patch(<Counter />);
关键点:
- 不要直接修改
this
上的状态属性 (除了在constructor
中初始化)。 componentUpdate()
会触发render()
方法重新渲染。componentUpdate()
是异步的,并且会将多次更新合并为一次。
5. 生命周期 (Lifecycle)
类组件有一系列特殊的“生命周期方法”,允许你在组件的不同阶段执行代码:
constructor(props, kids)
: 组件实例创建时调用,用于初始化状态和绑定方法。this(props, kids)
: 组件接收新的 props 或 kids 时调用。render()
: 必须的方法,返回要渲染的 JSX。当状态或 props 改变时会被调用。componentDidMount()
: 组件首次挂载到真实 DOM 后调用。适合执行需要 DOM 节点的操作,如网络请求、设置定时器等。componentWillUnmount()
: 组件从 DOM 中卸载前调用。适合执行清理操作,如清除定时器、取消网络请求等。componentDidUpdate()
: 在componentUpdate()
触发的更新完成后调用。
参考示例:上面的
Clock
组件就使用了componentDidMount
和componentWillUnmount
。6. 事件处理 (Event Handling)
在 Reactor 中处理事件非常直观。可以直接在 JSX 中使用
on
属性绑定事件处理器。javascript代码解读复制代码function ActionButton() { function handleClick(event) { console.log('按钮被点击了!', event); } return <button onclick={handleClick}>点我button>; }
对于类组件,通常在类中定义事件处理方法:
javascript代码解读复制代码class Search extends Element { handleSearchClick() { const query = this.$('input').value; // 获取输入框的值 console.log('搜索:', query); // 可以触发一个自定义事件,通知父组件 this.post(new Event('do-search', { data: query })); } render() { return ( <search> <button onclick={() => this.handleSearchClick()}>搜索button> search> ); } }
Sciter 还支持更高效的类事件处理器语法 (详见
component-styles-events.md
), 我个人是非常非常喜欢这种写法的,所见所得,不用自己到处去绑定,好象是 ES2020 的新语法:javascript代码解读复制代码class Search extends Element { // ... render 方法 ... // 使用特殊语法处理按钮点击 ["on click at button"](evt, button) { const query = this.$('input').value; console.log('搜索:', query); this.post(new Event('do-search', { data: query })); } }
7. 样式 (Styling)
你可以像在普通 HTML 中一样使用 CSS 来为组件添加样式。
全局样式: 在 HTML 文件中通过
标签或链接外部 CSS 文件。
组件级样式 (
styleset
): 为了更好地封装组件样式,避免全局污染,Reactor 推荐使用styleset
属性。-
外部 CSS 文件:
javascript代码解读复制代码// component.js class MyComponent extends Element { render() { // 使用 __DIR__ 获取当前脚本文件所在目录 return <div styleset={__DIR__ + "styles.css#my-component"}>内容div>; } }
css代码解读复制代码/* styles.css */ @set my-component { :root { /* :root 指向组件根元素 */ display: block; border: 1px solid red; padding: 10px; } :root p { color: blue; } }
-
内联 CSS (使用
CSS.set
):javascript代码解读复制代码// component.js const myComponentStyles = CSS.set` :root { display: block; border: 1px solid green; padding: 8px; } `; class MyComponent extends Element { render() { return <div styleset={myComponentStyles}>内联样式内容div>; } }
开始第一个 Reactor 应用
让我们创建一个简单的“计数器”应用。
-
创建 HTML 文件 (
counter.htm
):html代码解读复制代码<html> <head> <title>Reactor 计数器title> <style> body { padding: 20px; font-family: sans-serif; } button { margin-left: 10px; padding: 5px 10px; } style> <script type="module"> // 导入或定义 Counter 组件 (见下一步) import { Counter } from './counter.js'; // 将 Counter 组件渲染到 body document.body.patch(<Counter initialCount={0} />); script> head> <body> body> html>
-
创建 JavaScript 文件 (
counter.js
):javascript代码解读复制代码export class Counter extends Element { // 从 props 获取初始值 constructor(props) { super(); this.count = props.initialCount || 0; } increment() { this.componentUpdate({ count: this.count + 1 }); } decrement() { this.componentUpdate({ count: this.count - 1 }); } render() { return ( <div> <span>当前计数: {this.count}span> <button onclick={() => this.increment()}>+button> <button onclick={() => this.decrement()}>-button> div> ); } }
-
运行: 使用 Sciter 加载
counter.htm
文件。
现在你应该能看到一个可以增加和减少计数的简单应用了!
最佳实践
- 组件化: 将 UI 拆分成小的、可复用的组件。
- 单一职责: 每个组件最好只做一件事。
- Props 向下传递: 数据流应该是单向的,从父组件通过 props 传递给子组件。
- 状态最小化: 只在必要时使用组件内部状态。尽可能将状态提升到共同的父组件中管理。
- 使用 Keys: 当渲染列表时,为每个列表项提供一个唯一的
key
属性,帮助 Reactor 识别哪些项发生了变化。javascript代码解读复制代码function ItemList(props) { const listItems = props.items.map((item) => <li key={item.id}>{item.text}li> ); return <ul>{listItems}ul>; }
- 善用生命周期: 在合适的生命周期方法中执行副作用(如 API 调用、定时器设置)。
- 组件命名: 组件名称(函数或类)始终使用大写字母开头。
- 样式封装: 优先使用
styleset
来封装组件样式。
示例代码参考
Sciter SDK 提供了丰富的 Reactor 示例,强烈建议查看:
samples.reactor/basic/
: 包含基础概念的示例,如时钟 (component-clock.htm
)、组件更新 (component-update.htm
)。samples.reactor/form/
: 表单处理示例。samples.reactor/todo/
: 一个经典的 TODO 应用示例。samples.reactor/styling/
: 不同的样式定义方式。samples.reactor/tabs/
: Tabs 组件示例。
结语
本教程介绍了 Sciter.js Reactor 的基础知识。Reactor 提供了一种现代、高效的方式来构建桌面应用程序的用户界面。通过实践和参考 SDK 中的示例,你将能够更快地掌握它,但不要忘记原生的文档哦。可以直接去 docs.sciter.com 网站上看。
下一步的建议:
- 深入阅读官方文档
docs/md/Reactor/
目录下的其他文件。 - 动手尝试修改和运行
samples.reactor/
目录下的示例。 - 开始构建你自己的 Reactor 组件!
- 可以在 JSX 中使用
评论记录:
回复评论: