一,对组件化的理解

1,组件的封装

-视图

-数据

-变化逻辑(数据驱动视图变化)

例:

import React, {
Component
} from 'react';
import List from './list/index.js';
import Input from './input/index.js'; class Todo extends Component {
constructor(props) {
// 数据
super(props)
this.state = {//保存当前组件的变量
list:[]
}
}
render() {
return (
// 视图
<div>
<Input addTitle={this.addTitle.bind(this)}/>
<List data={this.state.list} />
<List data={[1,2,3]} />
</div>
)
}
// 变化逻辑
addTitle(title) {
const currentList = this.state.list;
this.setState({
list:currentList.concat(title)
})
}
} export default Todo

2,组件的复用

-props传递

-复用

例:

import React, {
Component
} from 'react'; class List extends Component {
constructor(props) {
super(props)
}
render(){
const list = this.props.data; //props传递
return (
<ul>
{
list.map((item,index) => {
return <li key={index}>{item}</li>
})
}
</ul>
)
}
} export default List

二,JSX本质

1,JSX语法:

例:

  // html形式
// 引入JS变量和表达式
// if...else...
// 循环
// style和className
// 事件
render() {
const name = '12';
const show = true;
const list = [1,2,3,4,5];
const styleConfig = {
fontSize:'40px',
color:'blue'
}
return (
<div className='container'>
{/* <Todo /> */}
<p>{name}</p>
<p>{name ? 1 : 0}</p>
<p>{(name === '12').toString()}</p>
<p>{name || 'lisi'}</p>
{show ? <img src='./logo.svg' /> : ''}
<ul>
{list.map(function(item,index) {
return <li key={index}>{item}</li>
})}
</ul>
<p style={styleConfig}>this is a p</p>
<p style={{fontSize:'40px',color:'blue'}}>this is a p</p>
</div> );

2,JSX解析成JS:

JSX语法根本无法被浏览器所解析,那么它如何在浏览器运行?-转换成JS运行

思考:为何react组件中,React 没有显示地使用,但却必须要引入?(去掉的话会报错)  'React' must be in scope when using JSX 

import React, {
Component
} from 'react';

看个例子:

    // JSX代码
var profile = <div>
<img src="avatar.png" className="profile" />
<h3>{[user.firstName,user.lastName].join('')}</h3>
</div>;

解析结果:

    // 解析结果 有没有跟vdom的h函数、vue的_c函数很像?yes!
var profile = React.createElement("div",null,
React.createElement("img",{src:"avatar.png",className:"profile"}),
React.createElement("h3",null,[user.firstName,user.lastName].join('')),
);

从上面得知,我们所写的JSX代码,都是需要通过 React.createElement 函数来解析

React.createElement 参数说明
 ReactElement createElement(
string/ReactClass type,
[object props],
[children ...]
)

(类似 vdom 的 h 函数、vue 的 _c 函数)例:

    React.createElement('div',{id:'div1'},child1,child2,child3)
React.createElement('div',{id:'div1'},[...])

再看:

render(){
const list = this.props.data;
return (
<ul>
{
list.map((item,index) => {
return <li key={index}>{item}</li>
})
}
</ul>
)
}

解析如下:

   function render() {
const list = this.props.data;
return React.createElement(
'ul',
null,
list.map((item,index) => {
return React.createElement(
'li',
{key:index},
item
)
})
)
}

JSX的写法大大降低了学习成本和编码工作量

同时,JSX也会增加debug成本

3,独立的标准

JSX 是  React 引入的,但不是 React 独有的,已经是一个标准

React 已经将它作为一个独立标准开放,其他项目也可以使用

React.createElement 是可以自定义修改的

说明:本身功能已经完备;和其他标准兼容和扩展性没问题

使用插件编译jsx代码,测试:

新建文件夹 jsx-test

mkdir jsx-test

进入文件夹

cd jsx-test

初始化:

npm init

新建文件 demo.jsx

touch demo.jsx

全局安装babel

sudo npm i babel -g

安装依赖插件

npm install --sav-dev babel-plugin-transform-react-jsx

创建.babelrc文件,配置:

{
"plugins":["transform-react-jsx"]
}

babel编译命令:

babel --plugins transform-react-jsx demo.jsx

demo.jsx代码如下:

class Input extends Component {
constructor(props) {
super(props)
this.state = {
title:''
}
}
render(){
return (
<div>
<input value={this.state.title} onChange={this.changeHandle.bind(this)} />
<button onClick={this.clickHandle.bind(this)}>submit</button>
</div>
)
}
changeHandle(event){
this.setState({
title:event.target.value
})
}
}

编译结果:

class Input extends Component {
constructor(props) {
super(props);
this.state = {
title: ''
};
}
render() {
return React.createElement(
'div',
null,
React.createElement('input', { value: this.state.title, onChange: this.changeHandle.bind(this) }),
React.createElement(
'button',
{ onClick: this.clickHandle.bind(this) },
'submit'
)
);
}
changeHandle(event) {
this.setState({
title: event.target.value
});
}
}

尝试把 React.createElement 改成 h   在文件顶部加入

/* @jsx h */

运行编译如下:

class Input extends Component {
constructor(props) {
super(props);
this.state = {
title: ''
};
}
render() {
return h(
'div',
null,
h('input', { value: this.state.title, onChange: this.changeHandle.bind(this) }),
h(
'button',
{ onClick: this.clickHandle.bind(this) },
'submit'
)
);
}
changeHandle(event) {
this.setState({
title: event.target.value
});
}
}

总结:

js语法(标签,js表达式,判断,循环,事件绑定)

JSX其实是语法糖(微创新),需被解析成JS才能运行,React.createElement

已经成为独立的标准

三,JSX 和 vdom 关系

1,分析:为何需要vdom

vdom是 React 初次推广开来的,结合 JSX

JSX 就是模版,最终要渲染成 html

初次渲染 + 修改 state 后的 re-render

正好符合 vdom 的应用场景

2,React.createElement 和 h(本质一样)

所有的JSX都要解析成JS,执行最终返回vnode

3,何时 patch ?

(1),初次渲染 ReactDOM.render(<App />, container),会触发 patch(container,vnode)

例:

ReactDOM.render(<App />, document.getElementById('root'));

(2),re-render - setState,会触发 patch(vnode,newVnode)

        // patch(vnode,newVnode)
this.setState({
list:currentList.concat(title)
})

4,自定义组件的解析

'div',直接渲染<div>即可,vdom可以做到

Input和List等自定义组件(class),vdom默认不认识

因此Input和List定义的时候必须声明render函数

根据props初始化实例,然后执行实例的render函数

render函数返回的还是vnode对象

        var list = new List({ data: this.state.list });
var vnode = list.render();

例(demo.jsx)

import List from './list/index.js';
import Input from './input/index.js'; function render() {
return (
// 视图
<div>
<p> this is demo </p>
<Input addTitle={this.addTitle.bind(this)}/>
<List data={this.state.list} />
<List data={[1,2,3]} />
</div>
)

解析如下:

import List from './list/index.js';
import Input from './input/index.js'; function render() {
return (
// 视图
React.createElement(
'div',
null,
React.createElement(
'p',
null,
' this is demo '
),
React.createElement(Input, { addTitle: this.addTitle.bind(this) }),
React.createElement(List, { data: this.state.list }),
React.createElement(List, { data: [1, 2, 3] })
)
);
}

总结:

为何需要vdom:JSX需要渲染成html,数据驱动视图

React.createElement 和 h,都生成vnode (React.createElement 既可以创建 html 默认的标签-字符串形式,可以创建自定义组件名称)

何时patch:ReactDOM.render(...) 和 setState()

自定义组件的解析:初始化实例,然后执行render

四,说下 setState 的过程 ( setState 核心函数)

1,setState 的异步

   addTitle(title) {
const currentList = this.state.list;
// patch(vnode,newVnode)
console.log(this.state.list); //[1,2]
this.setState({
list: currentList.concat(title) //3
})
console.log(this.state.list); //[1,2] 因为上面的setState是异步操作,所以这里仍旧是[1,2]
}

原因:

01,可能会一次执行多次 setState

02,你无法规定、限制用户如何使用 setState

03,没必要每次 setState 都重新渲染,考虑性能

04,即便是每次重新渲染,用户也看不到中间的效果(js执行和DOM渲染是单线程的)

05,只看到最后的结果即可

addTitle(title) {
const currentList = this.state.list;
// 初次想增加 title
this.setState({
list: currentList.concat(title)
}) // 改变注意,想增加 title + 1
this.setState({
list: currentList.concat(title + 1)
}) // 又改变注意,想增加 title + 2
this.setState({
list: currentList.concat(title + 2)
})
}

用户操作后,只会看到最后的结果,即  list: currentList.concat(title + 2)

2,vue 修改属性也是异步

01,效果、原因和 setState 一样

02,对比记忆,印象深刻

03,复习下vue 的实现流程

第一步:解析模版成render函数

第二步:响应式开始监听

第三步:首次渲染,显示页面,且绑定依赖

第四步:data 属性变化,触发 rerender ( set中执行updateComponent 是异步的)

3,setState 的过程

01,每个组件实例,都有 renderComponent 方法 (在Component 组件中定义的)

02,执行 renderComponent 会重新执行实例的 render )

03,render 函数返回 newVnode,然后拿到 preVnode (上次执行的 newVnode)

04,执行 patch(preVnode,newVnode)

addTitle(title) {
const currentList = this.state.list;
// patch(vnode,newVnode)
console.log(this.state.list); //[1,2]
this.setState({
list: currentList.concat(title) //3
},() => {
console.log(this.state.list); //这里能拿到实时结果 [1,2,3]
// this.renderComponent()
})
console.log(this.state.list); //[1,2] 因为上面的setState是异步操作,所以这里仍旧是[1,2]
}

模拟 Component

class Component {
constructor(props) { }
renderComponent() {
const preVnode = this._vnode;
const newVnode = this.render();
patch(preVnode,newVnode)
this._vnode = newVnode; }
}

五,对 React 和 vue 的认识

国内使用,首推vue,文档更易读、易学,社区够大

如果团队水平较高,推荐使用React,组件化和JSX做的更好

1,两者的本质区别

vue-本质是MVVM框架,由MVC发展而来

React-本质是前端组件化框架,由后端组件化发展而来

但这并不妨碍它们两者都能实现相同的功能

2,模版的区别:

vue-使用模版(最初由 angular 提出)

React-使用JSX

模版语法上,更倾向于JSX

模版分离上,更倾向于Vue

3,组件化的区别:

React本身就是组件化,做的更彻底

vue也支持组件化,不过是在MVVM上的扩展

4,两者共同点

都支持组件化

都是数据驱动视图

六,总结:

组件化的理解:

1,组件的封装:封装视图,数据,变化逻辑

2,组件的复用:props传递,复用

JSX本质:

1,语法

2,语法糖,需被解析成JS才能运行

3,JSX是独立的标准,可被其他项目使用

JSX和vdom的关系

1,为何需要vdom:JSX需要渲染成html,还有rerender

2,React.createElement 和 h,都生成vnode

3,何时patch:ReactDOM.render() 和 setState

4,自定义组件的解析:初始化实例,然后执行render

setState过程:

异步:效果、原因 (vue修改属性也是异步,效果、原因)

setState的过程:最终走到 patch(preVnode,newVnode)

附:用 React 实现 todo-list

创建 React 开发环境

全局安装

sudo npm i create-react-app -g --registry=https://registry.npm.taobao.org

运行

create-react-app react-rest

成功之后:

Inside that directory, you can run several commands:

  yarn start
Starts the development server. yarn build
Bundles the app into static files for production. yarn test
Starts the test runner. yarn eject
Removes this tool and copies build dependencies, configuration files
and scripts into the app directory. If you do this, you can’t go back! We suggest that you begin by typing: cd react-rest
yarn start Happy hacking!

进入文件夹

cd react-rest

运行

yarn start

实现todo组件

import React, {
Component
} from 'react';
import List from './list/index.js';
import Input from './input/index.js'; class Todo extends Component {
constructor(props) {
super(props)
this.state = {//保存当前组件的变量
list:[]
}
}
render() {
return (
<div>
<Input addTitle={this.addTitle.bind(this)}/>
<List data={this.state.list} />
</div>
)
}
addTitle(title) {
const currentList = this.state.list;
this.setState({
list:currentList.concat(title)
})
}
} export default Todo

todo中使用的Input组件:

import React, {
Component
} from 'react'; class Input extends Component {
constructor(props) {
super(props)
this.state = {
title:''
}
}
render(){
return (
<div>
<input value={this.state.title} onChange={this.changeHandle.bind(this)} />
<button onClick={this.clickHandle.bind(this)}>submit</button>
</div>
)
}
changeHandle(event){
this.setState({
title:event.target.value
})
}
clickHandle(){
const title = this.state.title;
// 把title添加进列表
const addTitle = this.props.addTitle;
addTitle(title);//重点
this.setState({
title:''
}) }
} export default Input

todo中使用的List组件

import React, {
Component
} from 'react'; class List extends Component {
constructor(props) {
super(props)
}
render(){
const list = this.props.data;//list组建期望别人传入的列表
return (
<ul>
{
list.map((item,index) => {
return <li key={index}>{item}</li>
})
}
</ul>
)
}
} export default List

最后,修改App.js

import React, {
Component
} from 'react';
import logo from './logo.svg';
import './App.css';
import Todo from './components/todo/index.js' class App extends Component {
render() {
return (
<div>
<Todo />
</div>
);
}
} export default App;

附:

react 父子组件互相通信

1,父组件向子组件传递 在引用子组件的时候传递,相当于一个属性

                <Input addTitle={this.addTitle.bind(this)} />
<List data={this.state.list} />

2,子组件向父组件传递 子组件通过 调用父组件传递到子组件的方法 向父组件传递消息的。

class Input extends Component {
constructor(props) {
super(props)
this.state = {
title:''
}
// console.log(this.props)
}
render(){
return (
<div>
<input value={this.state.title} onChange={this.changeHandle.bind(this)} />
<button onClick={this.clickHandle.bind(this)}>submit</button>
</div>
)
}
changeHandle(event){
this.setState({
title:event.target.value
})
}
clickHandle(){
const title = this.state.title;
// 把title添加进列表
const addTitle = this.props.addTitle;
addTitle(title);//重点 调用父组件方法
this.setState({
title:''
}) }
}

附:

React:Rethinking Web App Development at Facebook  只负责view层,不是完整的MVVM框架

React 特点:轻,组件化开发,高度可重用

React应用场景:

复杂场景下的高性能

重用组件库,组件组合

React组件的生命周期和事件处理

React Components Lifecycle

Mounted: React Components 被render解析,生成对应的DOM节点,并被插入浏览器的DOM结构的一个过程( React.renderComponent() )

Update:一个 mounted 的 React Components 被重新render 的过程 (setState() 或者 setProps()  ----> render)

Unmounted:一个mounted的 React Components 对应的 DOM 节点被从DOM结构中移除的过程

每一个状态 React 都封装了对应的 hook 函数

未完待续...

组件化和 React的更多相关文章

  1. client高性能组件化框架React简单介绍、特点、环境搭建及经常使用语法

    [本文源址:http://blog.csdn.net/q1056843325/article/details/54729657 转载请加入该地址] 明天就是除夕了 预祝大家新春快乐 [ ]~( ̄▽ ̄) ...

  2. 【前端知识体系-JS相关】组件化和React

    1. 说一下使用jQuery和使用框架的区别? 数据和视图的分离,(jQuery数据和视图混在一起,代码耦合)-------开放封闭原则 以数据驱动视图(只关注数据变化,DOM操作被封装) 2.说一下 ...

  3. React Native 之 组件化开发

    前言 学习本系列内容需要具备一定 HTML 开发基础,没有基础的朋友可以先转至 HTML快速入门(一) 学习 本人接触 React Native 时间并不是特别长,所以对其中的内容和性质了解可能会有所 ...

  4. 从DOM操作看Vue&React的前端组件化,顺带补齐React的demo

    前言 接上文:谈谈我对前端组件化中“组件”的理解,顺带写个Vue与React的demo 上次写完博客后,有朋友反应第一内容有点深,看着迷迷糊糊:第二是感觉没什么使用场景,太过业务化,还不如直接写Vue ...

  5. 谈谈我对前端组件化中“组件”的理解,顺带写个Vue与React的demo

    前言 前端已经过了单兵作战的时代了,现在一个稍微复杂一点的项目都需要几个人协同开发,一个战略级别的APP的话分工会更细,比如携程: 携程app = 机票频道 + 酒店频道 + 旅游频道 + ..... ...

  6. 移动web端的react.js组件化方案

     背景: 随着互联网世界的兴起,web前端开发的方式越来越多,出现了很多种场景开发的前端架构体系,也对前端的要求日益增高,早已经不是靠一个JQuery.js来做前端页面的时代了,而今移动端变化最大,近 ...

  7. React 面向组件化编程 - 封装了webpack - npm run build 产生的包的 /static 引用路径问题

    React 面向组件化编程 面向对象 ----> 面向模块 ----> 面向组件 套路: 注意: 组件名必须大写开头: 只能有一个根标签: <input />虚拟DOM 元素必 ...

  8. 前端开发组件化设计vue,react,angular原则漫谈

    前端开发组件化设计vue,react,angular原则漫谈 https://www.toutiao.com/a6346443500179505410/?tt_from=weixin&utm_ ...

  9. atitit.React   优缺点 相比angular react是最靠谱的web ui组件化方案了

    atitit.React   优缺点 相比angular react是最靠谱的web ui组件化方案了 1. React的组件化才是web ui部件的正确方向1 1.1. 组件化集成html ,css ...

随机推荐

  1. libRTMP 整体说明

    函数结构 (libRTMP)的整体的函数调用结构图如下图所示: 原图地址:http://img.my.csdn.net/uploads/201602/10/1455087168_7199.png 基本 ...

  2. 三种方法在当前目录下打开cmd命令窗口

    概述 运行npm的时候,每次都要cd到目录,很麻烦,所以总结了三种在当前目录下直接打开cmd窗口的方法,供以后开发时参考,相信对其他人也有用. 方法一 在当前目录按住shift再右键. 会看到右键菜单 ...

  3. 通过Anaconda在Ubuntu16.04上安装 TensorFlow(GPU版本)

    一. 安装环境 Ubuntu16.04.3 LST GPU: GeForce GTX1070 Python: 3.5 CUDA Toolkit 8.0 GA1 (Sept 2016) cuDNN v6 ...

  4. Centos 7 安装 rabbitmq

    1.安装erlang rabbitmq 官方下载地址 "http://www.rabbitmq.com/download.html" ,选择"RHEL, CentOS, ...

  5. Java:Cookie实现记住用户名、密码

    package com.gamecenter.api.util; import java.io.IOException; import java.io.PrintWriter; import java ...

  6. EL表达式报错:  According to TLD or attribute directive in tag file, attribute value does not accept any expressions

    EL表达式报错: According to TLD or attribute directive in tag file, attribute value does not accept any ex ...

  7. 从零开始学 Web 之 Vue.js(一)Vue.js概述,基本结构,指令,事件修饰符,样式

    大家好,这里是「 从零开始学 Web 系列教程 」,并在下列地址同步更新...... github:https://github.com/Daotin/Web 微信公众号:Web前端之巅 博客园:ht ...

  8. C语言第三讲,基本数据类型

    C语言第三讲,基本数据类型 一丶基本数据类型讲解 在C语言当中,有四种基本数据类型 分别是: 整形 浮点型 指针 聚合类型(数组和结构) 整型家族包括: 字符 短整型 整形 长整型 ** 都分为有符号 ...

  9. AD预测论文研读系列1

    A Deep Learning Model to Predict a Diagnosis of Alzheimer Disease by Using 18F-FDG PET of the Brain ...

  10. FFmpeg时间戳详解

    本文为作者原创,转载请注明出处:https://www.cnblogs.com/leisure_chn/p/10584910.html 1. I帧/P帧/B帧 I帧:I帧(Intra-coded pi ...