React——第一阶段

根据胡子大哈的文章学习,感谢大胡分享
胡子大哈-react.js第一阶段

2017.6.19更新完毕
2017.6.18更新至state


正文开始

毕设搞定,工作搞定,终于。。。其实也不是没有时间,而是心里不静,不想写。

公司要用react,所以,先复习下,开始

一、什么是组件化?

总的来说,各种框架只是为了解决一个问题——开发效率。组件化是一种解决方案。
前端说起来也就三部分——结构,样式,交互。将某一功能的这三部分抽象出来,提升复用性、可维护性、代码效率。

那么问题的关键是——如何抽象

  1. 较广泛的属性——>较特殊的属性
  2. 输入不同——>输出不同

直白点就是类、函数。很明显,对于前端也就是,用js生成想要的结构,并为其添加功能和样式

具体分析

用js生成页面,再直白点就是——一个字符串形式的dom结构,用js解析、加入功能,然后插入到页面。

1.结构
那么首先要有一个render函数,返回这个字符串形式的dom结构。(也就是最开始的输入)

class oneComponent{
  render() {
    this.el = this.createDOM(`字符串dom结构`);
    return this.el;
  }
  createDOM(str) {
    const div = document.createElement('div');
    div.innerHTML = str;
    return div;
  }
}

结构有了,但显然不够,还要有交互

2.交互
一个思想——状态机。
用一些变量来表示状态,不同的状态,对应不同的页面展示。
首先要有一个状态池,页面的展示由多个状态决定,当状态改变时候,自动重新渲染所有dom。

上边的思路明显有一个问题,自动渲染所有dom开销太大,虽然避免了手工操作dom的各种弊端。解决方案是虚拟dom,其技术细节还有待研究。

首先是状态池:

class oneComponent{
  constructor() {
    this.state = {};
  }
  setState (state) {
    this.state = state;
    this.render();
  }
  render () {
    this.el = this.createDOM(str);
    return this.el;
  }
  
  // 功能函数
  createDOM(str) {
    const div = document.createElement('div');
    div.innerHTML = str;
    return div;
  }
}

有了状态池,功能就很好做了。比如一个点击切换内容功能(实际情况的肯定比较复杂了)

class oneComponent{
  constructor() {
    this.state = {
      isShowOK: true;
    };
  }
  setState (state) {
    this.state = state;
    this.render();
  }
  render () {
    this.el = this.createDOM(`<span>${this.state.isShowOK ? 'ok' : '不ok'}</span>`);
    this.el.addEventListener('click', this.clickChangeContent.bind(this), false);
    return this.el;
  }

  // 交互功能
  clickChangeContent () {
    this.setState ({
      isShowOK: !this.state.isShowOK
    })
  }
  
  // 功能函数
  createDOM(str) {
    const div = document.createElement('div');
    div.innerHTML = str;
    return div;
  }
}

3.插入页面
这一部分其实是在使用组件,有两个阶段:

  • 第一次使用
    第一次使用组件显然不是自己的事情,而是父组件的事情。
  • 状态改变
    每次状态改变,组件自身都要做到自我更新。
class oneComponent{
  constructor() {
    this.state = {
      isShowOK: true;
    };
  }
  setState (state) {
    let oldEl = this.el;
    this.state = state;
    this.render();
    if (this.onStateChange) {
      // 留下处理改变的接口
      this.onStateChange(oldEl, this.el);
    }
  }
  render () {
    this.el = this.createDOM(`<span>${this.state.isShowOK ? 'ok' : '不ok'}</span>`);
    this.el.addEventListener('click', this.clickChangeContent.bind(this), false);
    return this.el;
  }

  // 交互功能
  clickChangeContent () {
    this.setState ({
      isShowOK: !this.state.isShowOK
    })
  }
  
  // 以下功能函数

  // 组件初始化
  init() {
    this.render();
  }
  // 生成dom str->dom
  createDOM(str) {
    const div = document.createElement('div');
    div.innerHTML = str;
    return div;
  }
  // 使用子组件 这个过程发生在解析父组件自身dom的过程中。遇到了组件的语法,就调用这个函数,并传入对应组件的实例。
  useChildComponent(childComponent) {
    let el  = childComponent.init();
    功能:将el插入到对应的位置。
  }

  // 自身更新
  onStateChange (oldEl, newEl) {
    功能:对比前后的dom,哪变化了,就更新哪。
  }
}

稍微抽象下

输入输出上抽象,组件大概就是上边这样,当然有的功能太复杂,就用文字直接简要说明了下。
虽然看起来还不错,但是明显,组件本身也是可以再抽象一下基类。
为了更灵活,可以对基类子类加入props为组件进行配置。这样可定制性更高了。

class Component {
  constructor (props = {}) {
    this.props = props;
  }
  setState (state) {
    let oldEl = this.el;
    this.state = state;
    this.renderDOM();
    if (this.onStateChange) {
      // 留下处理改变的接口
      this.onStateChange(oldEl, this.el);
    }
  }

  renderDOM () {
    this.el = this.createDOM(this.render());
    此处在解析dom过程中添加事件。类似下边注释里边的。
    // this.el.addEventListener('click', this.clickChangeContent.bind(this), false);
    return this.el;
  }

  // 组件初始化
  init() {
    this.renderDOM();
  }

  // 生成dom str->dom
  createDOM(str) {
    const div = document.createElement('div');
    div.innerHTML = str;
    return div;
  }

  // 使用子组件 这个过程发生在解析父组件自身dom的过程中。遇到了组件的语法,就调用这个函数,并传入对应组件的实例。
  useChildComponent(childComponent) {
    let el  = childComponent.init();
    功能:将el插入到对应的位置。
  }

  // 自身更新
  onStateChange (oldEl, newEl) {
    功能:对比前后的dom,哪变化了,就更新哪。
  }
}

class oneComponent extends Component{
  constructor() {
    super(props);
    this.state = {
      isShowOK: true;
    };
  }

  render () {
    return `<span>${this.state.isShowOK ? 'ok' : '不ok'}</span>`;
  }

  // 交互功能
  clickChangeContent () {
    this.setState ({
      isShowOK: !this.state.isShowOK
    })
  }
}

组件化的概念结束,接下来是基础知识复习

总结一下

组件化设计需要:

  • 像上边这样的组件类
  • 特殊的语法分析器
  • 虚拟dom

二、基础知识

1.杂项

  • 项目生成
    使用create-react-app

  • 组件要引入react、{ Component }react-dom

  • JSX
    将js文件中的类似html的语法结构解析成js对象
    JSX-->(babel+React.js)-->js对象-->(ReactDOM.render)-->DOM-->插入页面

  • 为什么react和react-dom要分离开

    • 构造出的js对象不一定非要渲染成dom,还有可能渲染到canvas上,或者手机app上。
    • 方便更新组件,使用算法操作这个对象,然后整体更新,减少重排,比较快。

2.组件render方法
写react就是写组件,每个组件都必须有一个render方法,返回一个JSX元素
注意

  • 返回中,最外层只要一个元素
  • 在JSX中,class要用className,for要用htmlFor
  • JSX中用{}插入表达式
    • 表达式可以是循环,条件,函数,等等
    • 表达式中的变量来自组件作用域

3.事件监听
在JSX中的原生HTML标签(注意:对组件没用),为对应的事件接口添加回调即可。
比如onClick,onKeyDown
react事件列表

  • event对象

react封装的对象,属性与浏览器自己的event对象基本一致,保证了浏览器兼容性,对外api符合w3c标准。

  • 回调中的this

单纯指定回调,不绑定this的话,是无法在回调函数中通过this拿到组件实例的。
为什么?
很简单,回调函数直接将引用传递出去,其真正执行阶段的作用域是在全局作用域下,也就是说,这是一个在全局环境执行,但是没有明确指出是window对象调用的函数。
es5规定,在严格模式下,不直接用window对象调用函数,其内部this为undefined。react当然用的严格模式。
所以,拿不到组件实例,也拿不到window,最后是一个undined。

解决方法:
method.bind(this, arg1, arg2, ...)

4.state
状态池,就像上一部分说的。
注意:

  • 在组件的构造器中定义
  • state状态自动更新要使用setState()方法,以便于自动触发render
  • setState()参数
  • 对象——表示组件需要更新的状态。
  • 函数
  • setState()的使用
  1. 更新对象放入更新队列中,在本趟结束后更新。所以,前后数据改变存在逻辑关系的话,在同一个函数中,不能只传入对象,解决方法如下。
  2. 使用函数参数解决上边的问题,参数属性为上一个setState的结果。这种情况下,react会把setState一趟更新队列中的状态合并,并一次渲染。
  3. 传入第一个对象参数,并传入第二个当状态改变后的回调函数,封装成一个promise,当成异步来处理。这种情况的话,显然是更新了三次。

5.props
配置组件,组件是比较抽象的,实例化组件就是一个特殊化的过程,通过props来配置。

  • 父组件调用子组件时候,通过标签特性传入。所有的标签特性都会对应到子组件的props字段上。

  • 可以传递任何类型的值。比如函数,对象。

  • props一旦传入进来,就不能被改变。这是为了使得组件的形态/行为可以预测。

  • 只有通过父组件重新渲染,才能改变props。

  • 默认props(defaultProps)

static defaultProps = {
    likedText: '取消',
    unlikedText: '点赞'
  }

6.state与props
总结一下:

  • state组件自己控制自己的状态池,组件外部不可改变。

  • props父组件对子组件的初始化状态池,子组件内部不可改变。

  • 没有state的组件,叫做无状态组件,更利于组建维护。因为有了内部状态,就意味着组件很复杂,复用性降低。

  • react.js鼓励无状态组件。甚至在后来版本引入了函数式组件——不能用state的组件。

const dog = (props) => {
  const say = (event) => alert('dog')
  return (
    <div onClick={say}>dog</div>
  )
}

7.渲染列表
渲染列表的一般步骤:
拿到数组-->map遍历-->返回元素-->罗列渲染

  • 注意key值
    key,元素的标识,一般是后台数据的id。

(完)

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 157,298评论 4 360
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 66,701评论 1 290
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 107,078评论 0 237
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,687评论 0 202
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,018评论 3 286
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,410评论 1 211
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,729评论 2 310
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,412评论 0 194
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,124评论 1 239
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,379评论 2 242
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,903评论 1 257
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,268评论 2 251
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,894评论 3 233
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,014评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,770评论 0 192
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,435评论 2 269
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,312评论 2 260

推荐阅读更多精彩内容

  • 原教程内容详见精益 React 学习指南,这只是我在学习过程中的一些阅读笔记,个人觉得该教程讲解深入浅出,比目前大...
    leonaxiong阅读 2,766评论 1 18
  • 本笔记基于React官方文档,当前React版本号为15.4.0。 1. 安装 1.1 尝试 开始之前可以先去co...
    Awey阅读 7,532评论 14 128
  • 最近看了一本关于学习方法论的书,强调了记笔记和坚持的重要性。这几天也刚好在学习React,所以我打算每天坚持一篇R...
    gaoer1938阅读 1,614评论 0 5
  • 1. 永远不要买一件你很喜欢但没有你size的大衣 2. 永远不要买一件只是款式好看但品质没有达到你要求的大衣 3...
    陈清念阅读 302评论 0 3
  • 很多人上大学以后发现并不喜欢自己的专业,就产生换专业的念头,但是很多人在了解换专业的条件以后,很多都放弃了。 因为...
    毛哌专佳阅读 706评论 0 0