概览 React

React 是如何构成的,又该如何使用,一小篇文章足以解释。

最重要的一点:react 是一个完全遵从 javascript 开发模式的类库,语言层面仅仅有几个 API 而已,没有配置。react 更多的是需要开发者从设计模式上去考虑如何构建一个 web 项目。

概念

react 主要有两方面的功能,

  1. 根据数据构建虚拟树
  2. 根据树构建 web 页面

react 开发者仅仅需要关注于第一点即可,后续步骤由 react 按一定顺序进行下去,不需要开发者关心。

虚拟树

一个网页的 html 的代码就可以大致被认为是一个树结构(DOM 树),而虚拟树就是为了模拟 DOM 树结构存在的一种结构。

有了虚拟树结构,我们就能将页面的结构保存在 js 环境下,这样 js 的操作就可以不用依赖 DOM API ,也就是当数据更新的时候我们仅仅需要的是重新生成一个虚拟树即可,至于后续的从虚拟树生成 web 页面我们不关心。

那么如何生成虚拟树?

使用 React.createElement() 即可生成一个树节点。但在 react 中并不直接使用该函数(当然直接使用也可以),大部分情况下使用 jsx

React.createElement

该方法需要传入 3 个参数,节点名称(或是组件),props,子节点(由 React.createElement 创建,或纯文字)。

// 一个 p 节点,带了一些 props,没有子节点
let p = React.createElement('p', {className: 'line', propsName: 'some'});
// 一个 span 节点,带了一些 props,有一个纯文字子节点
let span = React.createElement('span', {className: 'text', propsName: 'some'}, ['some text']);
// 一个 div 节点,带了一些 props,有 p 和 span 两个子节点
let divTree = React.createElement('div', {className: 'box', propsName: 'some'}, [p, span]);

console.log(divTree)

以上代码可在有 React 的环境下执行,可查看最终的结果。

React.createElement
React.createElement

可以看出最终输出的对象通过 props.children 字段实现了子节点的保存。

最新版本的 React.createElement 可以通过 (type, props, ...children) 获取子节点。

jsx

jsxjs 的语法扩展,目的是将 React.createElement 这个方法简洁化,将编程的写法改成描述的写法,我们来改写上面的例子:

let divTree = (
<div className="box" propsName="some">
    <p className="line" propsName="some"></p>
    <span className="text" propsName="some">some text</span>
</div>
)

这样就更贴近了 html 语法,并且比编程的写法更容易让人弄清虚拟树的结构。

在正常的 js 环境中是不认识 jsx 语法的,可以在 babelrepl 中将 jsx 翻译成 js 语法。

jsx 的更多细节

如何在 jsx 中使用 js

let num = 123;
let divTree = (
<div className="box" propsName="some">
    <p className="line" propsName="some">{num}</p>
    <span className="text" propsName="some">some text</span>
</div>
)

将表达式用 {} 包含即可。

虚拟树 to Dom

有了虚拟树我们就可以把虚拟树渲染到浏览器上:

ReactDom.render(divTree, document.body);

react 组件的两种存在形式

ok 了解了虚拟树的生成,那么如何去组织这个虚拟树的生成?这就涉及到 react 组件。

函数组件

let Com1 = function(props){
    console.log(props);
    props.children
    return (
        <div>
            <p>{props.propsName}</p>
        <div>
    )
}

函数组件最终返回一个虚拟树结构,注这里不是 html 代码。

那么如何使用?

// 调用组件时,参一 为组件的引用
let com1 = React.createElement(Com1, {propsName: 'some'}, 'some text');
// 非组件调用时 参一 为字符串
let divTree2 = React.createElement('div', {propsName: 'some'}, com1);

console.log(divTree2);
ReactDOM.render(divTree2, document.body);

组件可以作为 React.createElement 的第一个参数传入,React.createElement 检测到 第一个参数为函数时,将处理好的 props 作为参数调用它,获得函数的返回,处理后作为调用 React.createElement 的调用返回。

那么 jsx 呢?该怎么写,正常写就 ok

let divTree2 = (
    <div propsName="some">
        <Com1 propsName="some">some text</Com1>
    </div>
)

这里需要注意,由于 babel 的转换的原因,如果是组件那么组件的引用的名字必须大写。

类组件

class Com2 extends React.Component {
    render(){
        let props = this.props;
        return (
            <div>
                <p>Com1 text</p>
            <div>
        )
    }
}

let tree = new Com2(props).render()

Com2Com1 实现的功能完全一致。调用方式也完全一致,区别在于 React.createElement 检测到第一个参数为类时,会将处理好的 props 作为类实例化时的参数,并在实例化完成时调用 render 函数,获取返回值处理后作为 React.createElement 函数调用的返回。

两种组件的区别

除了类组件多了一些生命钩子和 state 其他的区别其实都是 js 语法中类和函数的区别,这里不深究。

关于事件

react 库本身实现了事件系统,这不是浏览器里面的事件系统,所以也就不能和浏览器的事件系统混用。

react 中的事件是根据 W3C 标准事件模型实现的,也就是说 react 里的事件能阻止冒泡到 react 的事件上,但不能阻止正常的浏览器标准事件。

而浏览器的事件是能阻止事件冒泡到 react 事件中的,原因是 react 把所有的事件都注册到了 document 上,所有浏览器的事件如果阻止冒泡到 document 上,那么 react 事件系统里面的相应事件就执行不了了。

结论:只用 react 的事件系统,如果不得已使用浏览器的事件系统,在明确结果的情况下阻止冒泡。

资源

React.js 小书

Read more

Gitlab 搭建

Gitlab 搭建

为什么? 想要自己搭建一个代码仓库无非是以下几点原因: 1. 公司内部项目 2. 自己的项目,但不适合在公网 3. 大部分的 git 仓库虽然有私有服务,但价格都不便宜,甚至不如一台云服务器来的便宜 配置及安装文档 Gitlab * 由于 gitlab 会用到 22 端口端口转发的化就走不了 git clone 的默认配置,且占用内存较高,不推荐使用 docker 进行部署; * 由于 gitlab 自带 nginx 默认情况下会与属主机的 nginx 冲突,因此推荐只使用 gitlab 自带的 nginx 进行端口转发; 最小化配置 # path /etc/gitlab/gitlab.rb external_url 'http://git.

By breeze
NPM 私服

NPM 私服

verdaccio 私服搭建,搭建过程中的一些问题以及解决: * docker compose 启动后,可能会报错:配置找不到,添加 config.yaml 文件到映射的 ./conf 目录即可,config.yaml 具体内容可在官网找到,下方也有最小化配置。 services: verdaccio: image: verdaccio/verdaccio container_name: 'verdaccio' networks: - node-network environment: - VERDACCIO_PORT=4873 - VERDACCIO_PUBLIC_URL=http://npm.demo.com ports: - '10001:4873'

By breeze