邂逅React

简介

React是一个用于构建用户界面的JavaScript库

用户界面User Interface,简称UI)是系统和用户之间进行交互和信息交换的介质,在这里指代的就是网页前端界面

传统的JS的问题

  1. 需要频繁的操作DOM,而操作DOM对于不同的浏览器之间存在一定的兼容性问题
  2. 而过多的兼容性代码,会在一定程度上造成业务逻辑代码的冗余
  3. 代码组织和规范的问题
  4. 我们编写页面的时候,需要过多的关注界面的细节,也就是说我们即需要操作DOM,还需要去管理和维护页面的状态(数据)
  5. 数据(状态)的定义和使用往往会分散到各个地方,不方便管理和维护

react框架的思想

  1. 以组件的方式去划分一个个功能模块
  2. 组件内以jsx来描述UI的样子,以state来存储组件内的状态
  3. 当应用的状态发生改变时,通过setState来修改状态,状态发生变化时,UI会自动发生更新

特点

声明式编程

声明式编程只需要维护自己的状态,当状态改变时,React可以根据最新的状态去渲染我们的UI界面

在React中,表示界面的JSX是依赖于state的,

而当state发生改变的时候,可以使用setState去重新调用render函数,从而重新渲染界面

1.png

在react中,上述的f函数就是render函数

组件化开发

网站的整体看成是一个组件,也就是根组件

随后网页根据功能点进行划分成一个个小的组件

最后再通过打包工具,将这一个个小的组件整合起来

1.png

跨平台开发

  • 2013年,React发布之初主要是开发Web页面
  • 2015年,Facebook推出了ReactNative,用于开发移动端跨平台
  • 2017年,Facebook推出ReactVR,用于开发虚拟现实Web应用程序

React依赖的库

说明
react 包含了react和react-native所共同拥有的核心代码
react-dom react渲染在不同平台所需要的核心代码
babel 编译器

react-dom会根据需要渲染的平台,将对于的vdom渲染成对应的dom或组件

平台 说明
web端 react-dom会讲jsx最终渲染成真实的DOM,显示在浏览器中
native端 react-dom会讲jsx最终渲染成原生的控件(比如Android中的Button,iOS中的UIButton)

babel是目前前端使用非常广泛的编辑器,

虽然ES6很方便,但是某些老版本浏览器不支持ES6,只支持ES5

babel让我们可以直接在编写代码的时候使用ES6

在部署的时候,会将我们ES6的代码转换为ES5的代码,从而适配我们所有需要适配的浏览器

默认情况下开发React其实可以不使用babel

但是React默认情况下需要使用React.createElement来编写页面结构,

而React.createElement本身编写是非常繁琐的和可读性差

所以React提供了React.createElement的语法糖JSX

默认情况下jsx(JavaScript XML),React是无法直接解析的

所以需要babel将jsx转换为React.createElement形式的代码后在交给React来进行解析

Hello World

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <!-- 全局挂载React对象 -->
  <script src="https://unpkg.com/react@17/umd/react.development.js" crossorigin></script>
  <!-- 全局挂载ReactDOM对象 -->
  <script src="https://unpkg.com/react-dom@17/umd/react-dom.development.js" crossorigin></script>
  <script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
</head>
<body>
  <!-- 挂载点 -->
  <div id="app"></div>

  <!-- type="text/babel" -> 告诉浏览器这些脚本要交给babel进行解析 -->
  <script type="text/babel">
    // 将参数1的内容挂载到参数2上,并覆盖原本挂载点中的内容
    // 参数1 -- JSX对象 需要渲染的内容 经过React.createElement处理后返回ReactRenderObject对象  也就是VDom对象
    // 参数2 --- 挂载点
    ReactDOM.render(<h2>Hello World</h2>, document.getElementById('app'))
  </script>
</body>
</html>

命令式编程 vs 声明式编程

示例

  1. 在界面显示一个文本: Hello World
  2. 点击下方的一个按钮,点击后文本改变为Hello React

命令式编程

<!--
  这种即需要关心页面状态又需要关心模板
  还需要在界面发生改变的时候,手动去操作DOM来更新界面的编程范式就被称之为响应式编程
  响应式编程的本质就是每一步都是向浏览器发送一条条的指令,凡事都是亲力亲为的
-->
<div id="app">
  <h2 id="msg"></h2>
  <button id="btn">change</button>
</div>

<script type="text/babel">
    let msg = 'Hello World'

    const msgEl = document.getElementById('msg')
    const btnEl = document.getElementById('btn')

    msgEl.innerHTML = msg

    btnEl.addEventListener('click', () => {
      msg = 'Hello React'
      msgEl.innerHTML = msg
    })
</script>

声明式编程

let msg = 'Hello World'

function render() {
  // 使用小括号是为了表示成一个整体,同时可以进行换行显示
  const jsx = (
    // JSX有且只能有一个根元素
    <div>
      {/* 使用大括号语法来插入变量 */}
      <h2>{msg}</h2>
      {/* 在react中原生事件使用小驼峰,因为react对原生事件进行了二次封装 */}
      <button onClick={ handleChange }>change</button>
    </div>
  )

  ReactDOM.render(jsx, document.getElementById('app'))
}

function handleChange() {
  msg = 'Hello React'
  render()
}

// 初始化渲染
render()

但是上边的代码看起来有点凌乱,且整个逻辑其实可以看做一个整体,也就是整个逻辑本身就可以看成是一个功能点,即整个逻辑其实可以封装为一个组件,也就是根组件

// 这种只要定义模板和状态即可,不需要我们频繁的去操作DOM的编程范式就是响应式编程

// 一个类继承自React.Component后就成为了React组件
class App extends React.Component {
  constructor() {
    // 继承类必须在构造器的第一行调用super方法
    // 以初始化父类实例
    super()
    // 如果定义的对象是需要响应式的对象
    // 也就是那些当值发生改变后,界面也需要相应发生刷新的那些对象
    // 在定义这些响应式对象的时候,必须定义在state对象中
    this.state = {
      msg: 'Hello World'
    }
  }


  // 组件必须实现一个render函数
  // 该函数需要返回对应的jsx对象
  // 用于告诉React需要显示的template
  render() {
    // 如果return后边的div需要和return分两行来进行编写
    // 就需要给div外包裹小括号,以表示这是个整体
    return (
      <div>
        {/* render不是react中的原生函数,所以其内部的this指向是正确的 */}
        <h2>{this.state.msg}</h2>
        <button onClick={ this.handleChange }>change</button>
      </div>
    )
  }

  // 默认情况下,React内置的原生事件在调用的时候,会将原生事件中的this置为undefined
  // 所以我们需要使用箭头函数进行重置
  handleChange = () => {
    // render函数本质是返回JSX对象
    // 但是单独调用render函数并不会将新的JSX交给ReactDOM来重新渲染
    // 所以在更新响应式数据的时候,必须调用setState函数
    // 在实际开发中,我们一般不会手动去调用render函数
    // this.render()

    // 响应式数据发生改变的时候
    // 调用setState方法进行界面刷新
    this.setState({
      msg: 'Hello React'
    })
  }
}

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

简单案例

电影列表

class App extends React.Component {
  constructor() {
    super()
    this.state = {
      movies: ['电影1', '电影2', '电影3', '电影4', '电影5']
    }
  }

  render() {
    return (
      <div>
        {/*
          react直接显示数组的时候,会主动调用数组的join方法,分隔符为空字符串
          所以这里实际展示的是this.state.moives.join('')
        */}
        { this.state.movies }
      </div>
    )
  }
}

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

既然react在显示的时候,会主动调用数组的join方法,那么我们所需要做的就是为数组中的每一项包裹li标签即可

class App extends React.Component {
  constructor() {
    super()
    this.state = {
      movies: ['电影1', '电影2', '电影3', '电影4', '电影5']
    }
  }

  render() {
    return (
      <ul>
        {
          this.state.movies.map(moive => <li>{ moive }</li>)
        }
      </ul>
    )
  }
}

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

计数器

class App extends React.Component {
  constructor() {
    super()
    this.state = {
      count: 0
    }
  }

  render() {
    return (
      <div>
        <h2>{ this.state.count }</h2>
        <button onClick={() => this.change(1)}>+1</button>
        <button onClick={() => this.change(-1)}>-1</button>
      </div>
    )
  }

  change = step => {
    this.setState({
      count: this.state.count + step
    })
  }
}

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

推荐阅读更多精彩内容

  • 邂逅React开发 React是什么? ■React是什么呢?相信每个做开发的人对它都或多或少有一些印象。 口这...
    songstar阅读 296评论 0 0
  • 前言:终于结束了紧张的一个学期,网课上的挺有趣,就是课程太挤了点。这个暑假,就从React开始吧。 一、为什么学习...
    waigo阅读 282评论 0 0
  • React框架学习 React的起源和发展 起初facebook在建设instagram(图片分享)的时候嘞,因为...
    hcySam阅读 663评论 0 1
  • 1. React 特点: 声明式编程:(1) 声明式编程现在是目前整个大前端开发模式: Vue React Flu...
    coderhzc阅读 1,179评论 0 1
  • 深入JSX date:20170412笔记原文其实JSX是React.createElement(componen...
    gaoer1938阅读 8,032评论 2 35