美文网首页
Days30 React

Days30 React

作者: biu丶biubiu | 来源:发表于2018-08-30 15:08 被阅读0次

React & Vue

React 起源于 Facebook 的内部项目,因为该公司对市场上所有 [JavaScript MVC 框架],都不满意,就决定自己写一套,用来架设 [Instagram]的网站。做出来以后,发现这套东西很好用,就在2013年5月[开源]了。
React 与 Vue 的对比

技术层面

  • Vue 生产力更高(更少的代码实现更强劲的功能)
  • React 更 hack 技术占比比较重
  • 两个框架的效率都采用了虚拟 DOM
    • 性能都差不多
  • 组件化
    • Vue 支持
    • React 支持
  • 数据绑定
    • 都支持数据驱动视图
    • Vue 支持表单控件双向数据绑定
    • React 不支持双向数据绑定
  • 它们的核心库都很小,都是渐进式 JavaScript 库
  • React 采用 JSX 语法来编写组件
  • Vue 采用单文件组件
    • template
    • script
    • style
      开发团队
  • React 由 Facebook 前端维护开发
  • Vue
    • 早期只有尤雨溪一个人
    • 由于后来使用者越来越多,后来离职专职开发维护
    • 目前也有一个小团队在开发维护
      社区
  • React 社区比 Vue 更强大
  • Vue 社区也很强大
    Native APP 开发
  • React Native
    • 可以原生应用
    • React 结束之后会学习
  • Weex
    • 阿里巴巴内部搞出来的一个东西,基于 Vue

babel 自动编译执行:

    <!--
    当 babel-standalone 发现 type="text/babel" 类型标签的时候:
        1. 将 script 标签中的内容转换为浏览器可以识别的 JavaScript
        2. 使用 eval 执行编译结果代码
    -->
    <script type="text/babel">
      const getMessage = () => "Hello World";
      console.log(getMessage())
    </script>

初始化及安装依赖

$ mkdir react-demos
$ cd react-demos
$ npm init --yes
$ npm install --save react react-dom @babel/standalone

Hello World

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <title>demo - Hello World</title>
  <script src="node_modules/@babel/standalone/babel.js"></script>
  <script src="node_modules/react/umd/react.development.js"></script>
  <script src="node_modules/react-dom/umd/react-dom.development.js"></script>
</head>

<body>
  <div id="root"></div>
  <script type="text/babel">
    ReactDOM.render(
      <h1>Hello, react!</h1>,
      document.getElementById('root')
    )
  </script>
</body>

</html>

JSX基本语法规则

  • 必须只能有一个根节点

  • 多标签写到包到一个小括号( )中,防止 JavaScript 自动分号不往后执行的问题。

  • 遇到 HTML 标签 (以 < 开头) 就用 HTML 规则解析

    • 单标签不能省略结束标签。
  • 遇到代码块(以 { 开头),就用 JavaScript 规则解析

  • JSX 允许直接在模板中插入一个 JavaScript 变量

    • 如果这个变量是一个数组,则会展开这个数组的所有成员添加到模板中
  • 单标签必须结束 />

基本语法:

const element = <h1>Hello, world!</h1>;

在 JSX 中嵌入 JavaScript 表达式

  • 语法
  • 如果 JSX 写到了多行中,则建议包装括号避免自动分号的陷阱
    function formatName(user) {
      return user.firstName + ' ' + user.lastName;
    }
    const user = {
      firstName: 'Harper',
      lastName: 'Perez'
    };
       const element = (
      <h1>
        Hello, {formatName(user)}!
      </h1>
    );
    ReactDOM.render(
      element,
      document.getElementById('root')
    );
    const user = {
      name: '张三',
      age: 18,
      gender: 0
    }
    const element = (
      <div>
        <p>姓名:{user.name}</p>
        <p>年龄:{user.age}</p>
        <p>性别:{user.gender === 0 ? '男' : '女'}</p>
      </div>
    )

在 JavaScript 表达式中嵌入 JSX

    function getGreeting (user) {
      if (user) {
        return <h1>Hello, {user.name}</h1>
      }
      return <h1>Hello, Stranger.</h1>
    }  
    const user = {
      name: 'Jack'
    }  
    const element = getGreeting(user)
      ReactDOM.render(
      element,
      document.getElementById('root')
    )

JSX 中的节点属性

  • 动态绑定属性值
  • class 使用 className
  • tabindex 使用 tabIndex
  • for 使用 htmlFor

普通的属性:

const element = <div tabIndex="0"></div>;

在属性中使用表达式:

const element = <img src={user.avatarUrl}></img>;

声明子节点

  • 必须有且只有一个根节点

如果标签是空的,可以使用 /> 立即关闭它。

const element = <img src={user.avatarUrl} />;

JSX 子节点可以包含子节点(最好加上小括号,防止自动分号的问题):

const element = (
  <div>
    <h1>Hello!</h1>
    <h2>Good to see you here.</h2>
  </div>
);

JSX 自动阻止注入攻击

原样输出:

const element = <div>{'<h1>this is safe</h1>'}</div>

输出 html:

function createMarkup() {
  return {__html: 'First &middot; Second'};
}

function MyComponent() {
  return <div dangerouslySetInnerHTML={createMarkup()} />;
}

在 JSX 中使用注释

在 JavaScript 中的注释还是以前的方式:

// 单行注释

/*
 * 多行注释
 */

在 jsx 的标签中写注释需要注意:

写法一(不推荐):

{
  // 注释
  // ...
}

写法二(推荐,把多行写到单行中):

{/* 单行注释 */}

写法三(多行):

{
  /*
   * 多行注释
   */
}

JSX 原理

Babel 会把 JSX 编译为 React.createElement() 函数。

下面两种方式是等价的:

const element = (
  <h1 className="greeting">
    Hello, world!
  </h1>
);

const element = React.createElement(
  'h1',
  {className: 'greeting'},
  'Hello, world!'
);

// Note: this structure is simplified
const element = {
  type: 'h1',
  props: {
    className: 'greeting',
    children: 'Hello, world'
  }
};

Class 和 Style

<div className="before" title="stuff" />
<div style={{color: 'red', fontWeight: 'bold'}} />

组件

React 允许将代码封装成组件(component),然后像插入普通 HTML 标签一样,在网页中插入这个组件。

组件规则注意事项

  • 组件类的第一个首字母必须大写

  • 组件类必须有 render 方法

  • 组件类必须有且只有一个根节点

  • 组件属性可以在组件的 props 获取

    • 函数需要声明参数:props

    • 类直接通过 this.props

函数式组件(无状态)

  • 名字不能用小写

    • React 在解析的时候,是以标签的首字母来区分的

    • 如果首字母是小写则当作 HTML 来解析

    • 如果首字母是大小则当作组件来解析

    • 结论:组件首字母必须大写

function Welcome(props) {
  return <h1>Hello, {props.name}</h1>;
}

const element = <Welcome name="Sara" />;
ReactDOM.render(
  element,
  document.getElementById('root')
);

组件构成:

function Welcome(props) {
  return <h1>Hello, {props.name}</h1>;
}

function App() {
  return (
    <div>
      <Welcome name="Sara" />
      <Welcome name="Cahal" />
      <Welcome name="Edite" />
    </div>
  );
}

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

抽取组件

function Comment(props) {
  return (
    <div className="Comment">
      <div className="UserInfo">
        <img className="Avatar"
          src={props.author.avatarUrl}
          alt={props.author.name}
        />
        <div className="UserInfo-name">
          {props.author.name}
        </div>
      </div>
      <div className="Comment-text">
        {props.text}
      </div>
      <div className="Comment-date">
        {formatDate(props.date)}
      </div>
    </div>
  );
}

类方式组件(有状态)

class 补充

本质就是对 EcmaScript 5 中构造函数的一个语法糖

就是让你写构造函数(类)更方便了

  • 基本语法

  • constructor 构造函数

  • 实例成员

    • 实例属性

    • 实例方法

  • 类成员

    • 静态方法

    • 静态属性

class 组件语法

在 React 中推荐使用 EcmaScript 6 Class 的方式类定义组件

<script>
    class Person {
      constructor (name, age, gender) {
        this.name = name
        this.age = age
        this.gender = gender
        this.type = 'human'
      }

      sayHello () {
        window.alert('hello ' + this.name)
      }
    }

    // class 可以使用 extends 关键字实现对父类的继承
    // 不仅可以继承属性,还可以继承父类的原型方法
    // 这里继承的本质是使用的:原型式继承
    // 注意:在子类中,如果没有写 constructor 则不需要调用 super
    //        如果一旦写了 constructor ,就必须手动调用一下 super 父类构造函数,否则报错
    class Student extends Person {
      constructor (name, age, gender, id) {
        // super 就父类构造函数
        // 借用父类构造函数,把 name、age、gender 初始化到 Student 实例中
        super(name, age, gender)
        this.id = id
      }

      study () {
        console.log(this.name + ' 在学习。。。')
      }
    }

    class Teacher extends Person {
      constructor (name, age, gender) {
        // super 就父类构造函数
        // 借用父类构造函数,把 name、age、gender 初始化到 Student 实例中
        super(name, age, gender)
      }

      teaching () {
        console.log(this.name + ' 在上课。。。')
      }
    }

    const s1 = new Student('张三', 18, '男')
  </script>

组件传值 Props

  • Props 是只读的,不能修改

EcmaScript 5 构造函数:

function Welcome(props) {
  return <h1>Hello, {props.name}</h1>;
}

EcmaScript 6 Class:

class Welcome extends React.Component {
  render() {
    return <h1>Hello, {this.props.name}</h1>;
  }
}

this.props.children

this.props 对象的属性与组件的属性一一对应,但是有一个例外,就是 this.props.children 属性。

它表示组件的所有子节点。

this.props.children 的值有三种可能:如果当前组件没有子节点,它就是 undefined;如果有一个子节点,数据类型是 object ;如果有多个子节点,数据类型就是 array 。所以,处理 this.props.children 的时候要小心。

React 提供一个工具方法 React.Children 来处理 this.props.children 。我们可以用 React.Children.map 来遍历子节点,而不用担心 this.props.children 的数据类型是 undefined 还是 object

事件处理

<script type="text/babel">
    function handleClick () {
      window.alert('hello')
    }

    // 1. 使用驼峰命名
    // 2. 必须绑定一个函数
    // 3. 不能使用字符串的方式,一定要使用 {函数} 来绑定
    const element = (
      <div>
        <button onClick={handleClick}>点我</button>
        {/* 直接绑定一个匿名函数 */}
        <button onClick={() => alert('hello world')}>行内处理</button>
      </div>
    )

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

函数式组件

 <script type="text/babel">
    // 这不叫组件,只是一个变量,没有状态
    // const header = (
    //   <div className="header">
    //     <h1>头部</h1>
    //   </div>
    // )

    // 组件的名字首字母必须大写
    function AppHeader () {
      return (
        <div className="header">
          <h1>头部</h1>
        </div>
      )
    }

    function AppAside () {
      return (
        <div className="aside">
          <ul>
            <li>正在热映</li>
            <li>即将上映</li>
          </ul>
        </div>
      )
    }

    function Welcome (props) {
      return <h1>Hello, {props.name}</h1>
    }

    // EcmaScript 6 Class
    class AppFooter extends React.Component {
      constructor () {
        super()
        // state 就是组件的状态,也就是把数据驱动视图的数据初始化到 state 中
        // state 类似于 Vue 中的 data
        this.state = {
          foo: 'bar'
        }

        setTimeout(() => {
          // 这样不行
          // this.state.foo = 'baz'

          // 这才是正确的修改 state 数据的方式
          this.setState({
            foo: 'baz'
          })
        }, 2000)
      }

      render () {
        return (
          <div className="footer">
            <p>底部 {this.state.foo}</p>
          </div>
        )
      }
    }


    const element = (
      <div>
        <AppHeader />
        <div className="main">
          <AppAside />
          <div className="content">
            <Welcome name="张三" />
            <Welcome name="李四" />
            <Welcome name="Jack" />
          </div>
        </div>
        <AppFooter />
      </div>
    )

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

带有状态的组件及事件绑定this

<script type="text/babel">
    class MyComponent extends React.Component {
      constructor () {
        // 如果子类加入了 constructor 构造函数,则一定要手动调用父类的构造函数 super
        super()
        // React 组件需要通过手动为组件类添加 state 成员来初始化:ViewModel
        // state 等价于 Vue 中的 data
        // 接下来就可以在该组件管理的模板中通过 {} 来访问绑定数据了
        this.state = {
          message: 'Hello, MyComponent!'
        }
      }

      render () {
        return (
          <div>
            <h1>{this.state.message}</h1>
            <h1>{this.state.message}</h1>
            <h1>{this.state.message}</h1>
            <h1>{this.state.message}</h1>
            <h1>{this.state.message}</h1>
            <h1>{this.state.message}</h1>
            {/*
              * 事件绑定函数默认情况下内部的 this 指向 Window
              * 自动接收一个 event 事件源对象
              * 1. this 指向了 Window
              * 2. 只能得到 event 无法传参
              */}
            <button onClick={this.handleClick}>点击改变 message</button>

            {
              /*
               * bind 了 this 的函数调用的时候,好会给你传递一个 event 事件源对象
               * 内部的 this 就是你 bind 的那个参数
               * 1. 可以指定 this
               * 2. 支持传参数,参数在前,事件源对象在最后
               * 推荐这种方式
               */
            }
            <button onClick={this.handleClick.bind(this, 123, 456)}>点击改变 message</button>

            {/*
              * 当点击 onClick 的时候,调用绑定了 this 的箭头函数
              * 箭头函数内部的 this 是组件实例
              * 所以我可以直接在调用函数中再调用 this.handleClick() 函数
              */}
            <button onClick={(e) => {this.handleClick(e, 123, 456)}}>点击改变 message</button>
          </div>
        )
      }

      // 规范:处理事件方法都取名为 handlexxx
      handleClick (num1, num2, e) {
        console.log(num1, num2, e)
        // console.log('handle click')
        // console.log(this) // 默认是 window
        
        // React 不是使用的类似于 Vue 中的 Object.defineProperty() 方式 get、set
        // this.state.message = 'hello world'

        // 现在只需要知道,如果要修改 state 中的数据并且希望得到视图更新,则一定要使用
        // this.setState 方法
        // this.setState({
        //   message: 'hello world'
        // })
      }
    }

    const element = <MyComponent />

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

相关文章

  • Days30 React

    React & Vue React 起源于 Facebook 的内部项目,因为该公司对市场上所有 [JavaScr...

  • 【时间管理】学习第59、60讲

    NO.R7202 Days30/49 7月30日 晴家中 【时间管理第59、60讲】 1、慢以致远:跑步,当我们慢...

  • 2018-07-31

    2018.7.3.周一复盘Days30章孝萍 人生效率手册的作者张萌一直在强调要打造个人品牌,昨天再次领略了品...

  • React基础

    react 教程 react 组件介绍 react state 介绍 react Props 介绍 React:组...

  • 学习react no.1

    学习react no.1 react 定义 react 特点 react

  • React Native 学习之路

    React 相关资料 React Components React Properties React State ...

  • React基础

    React包含react元素和react组件 react元素 react组件 react组件分为函数组件和类组件 ...

  • React面试题 整理脑图

    react基础 React生命周期 react-router react进阶 react Hooks redux 其他

  • react 导入中的 as

    import React from 'react'只导入 是 React。 而import * as React ...

  • ES5与ES6小结部分

    1var React=require('react'); 等价 import React from ' react...

网友评论

      本文标题:Days30 React

      本文链接:https://www.haomeiwen.com/subject/ttzrwftx.html