美文网首页
PHP的全栈之路3

PHP的全栈之路3

作者: foxman | 来源:发表于2018-01-06 14:27 被阅读10次

死磕React 第一回

上帝视角

官网当然是我们最佳的学习资料,但我记得一句话,好老师从来都不是按照课本顺序来讲义的,所以对于官网上的文档,我觉得最佳的学习顺序也并非从头看到尾,我们首先要开启上帝视角

为什么要有react呢,他解决了一类什么问题?
React 理念这篇官网的文章让我找到了一些答案,水平有限,我只读懂了文章里的第一步、第二步,后面就开始晕了,建议第一次接触的人也不要急于全部搞懂,这篇文章给我两个很重要的信息。

  • 前端分层解决方案——组件
    第一次让我见识到,原来前端不再是像以前那样,写一大串html,来完成整个页面的静态编码,而是将页面切割成不同的部分,用组件来表示页面的元素
  • 组件的实现方式——react
    react是什么呢?我认为它就是组件的一种实现方式之一,组件是一种思想,落实到编码实现上,就是react了,react也就显的不再那么高深了,由此我还能猜想到Vue和Angular无非就是组件的另外两种实现方式而已

了解概念

接下来就要撸一堆概念了,建议撸完本文后,可以官网上撸概念

组件

将UI切分成一些的独立的、可复用的部件,这样你就只需专注于构建每一个单独的部件,这样的部件称为组件,在React中有其特有的语法表示,组件从概念上看就像是函数,它可以接收任意的输入值(称之为“props”),并返回一个需要在页面上展示的React元素

函数定义/类定义组件

定义一个组件最简单的方式是使用JavaScript函数:

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

它接收一个单一的“props”对象并返回了一个React元素,可能你会对这句话里的propsReact元素理解起来困难,没关系,就将其当成PHP里的参数和返回值好了。

你也可以使用 ES6 class 来定义一个组件:

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

上面两个组件在React中是相同的,我就当第一种是过程编程,第二种是对象编程吧,这样有助于我记忆,毕竟利用学过的知识来映射新的知识,这样能更清楚的记住

组合组件

组件可以在它的输出中引用其它组件,这就可以让我们用同一组件来抽象出任意层次的细节。在React应用中,按钮、表单、对话框、整个屏幕的内容等,这些通常都被表示为组件。
我们可以创建一个App组件,用来多次渲染Welcome组件:

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')
);

警告:组件的返回值只能有一个根元素。这也是我们要用一个<div>来包裹所有<Welcome />元素的原因。

元素

上面我们提到一个组件会返回一个React元素,所谓元素是构成 React 应用的最小单位,元素用来描述我们在屏幕上看到的内容:

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

与浏览器的 DOM 元素不同,React 当中的元素事实上是普通的对象,React DOM 可以确保 浏览器 DOM 的数据内容与 React 元素保持一致

元素渲染到 DOM 中

首先我们在一个 HTML 页面中添加一个 id="root" 的 <div>:

<div id="root"></div>

在此 div 中的所有内容都将由 React DOM 来管理,所以我们将其称之为 “根” DOM 节点。

我们将 元素传入一个名为 ReactDOM.render() 的方法来将其渲染到页面上:

const element = <h1>Hello, world</h1>;
ReactDOM.render(
  element,
  document.getElementById('root')
);

Props&纯函数

上文中我们搁置了对Props的解释,只是暂且看作PHP函数的参数来理解,实际上也是如此。

对于函数声明的组件,props就是外部使用组件时,传入组件的参数

// Welcome组件通过props.name拿到调用者传入的数据
function Welcome(props) {
  return <h1>Hello, {props.name}</h1>;
}

// 组件App 返回一个react元素,元素中使用了Welcome组件,并将name属性传入组件
function App() {
  return (
    <div>
      <Welcome name="Sara" />
    </div>
  );
}

// 渲染App组件到DOM中
ReactDOM.render(
  <App />,
  document.getElementById('root')
);

/*output
<h1>Hello, Sara</h1>
*/

对于类声明的组件,props就是类的一个属性,通过这个属性能取到外部使用组件时,传入组件的一些必要数据

// Welcome组件通过this.props.name拿到调用者传入的数据
class Welcome extends React.Component {
  render() {
    return <h1>Hello, {this.props.name}</h1>;
  }
}

// 组件App 返回一个react元素,元素中使用了Welcome组件,并将name属性传入组件
function App() {
  return (
    <div>
      <Welcome name="Sara" />
    </div>
  );
}

// 渲染App组件到DOM中
ReactDOM.render(
  <App />,
  document.getElementById('root')
);

/*output
<h1>Hello, Sara</h1>
*/

当然这还不是全部,Props相比一般的参数,具有只读性,也就是其值不会被改变,这里正好引入了纯函数和非纯函数的概念

function sum(a, b) {
  return a + b;
}

类似于上面的这种函数称为“纯函数”,它没有改变它自己的输入值,当传入的值相同时,总是会返回相同的结果

与之相对的是非纯函数,它会改变它自身的输入值:

function withdraw(account, amount) {
  account.total -= amount;
}

React是非常灵活的,但它也有一个严格的规则:
所有的React组件必须像纯函数那样使用它们的props

State&生命周期

应用的界面是随时间动态变化的,State可以在不违反props规则的情况下,根据用户操作、网络响应、或者其他状态变化,使组件动态的响应并改变组件的输出

我们在定义组件的时候,虽然可以通过函数和类声明这两种方式,但是当涉及到局部状态、生命周期钩子等高级用法时,只能通过类的方式来声明组件

官网的例子写的非常详细,细致的说出了其演变,我重新再拜读下官网例举的定时器例子,并试着给代码用1、2、3标注执行的顺序,加上注释

class Clock extends React.Component {
  // 2. 组件被外部调用时,会优先执行构造函数,这里是初始化this.state的地方
  constructor(props) {
    super(props);
    this.state = {date: new Date()};
  }

  // 4. 当组件返回的元素输出到屏幕时,调用此钩子设置一个定时器,每秒钟调用一次tick()
  componentDidMount() {
    this.timerID = setInterval(
      () => this.tick(),
      1000
    );
  }

  // 6. 一旦Clock组件被从DOM中移除,会调用这个钩子函数清除定时器
  componentWillUnmount() {
    clearInterval(this.timerID);
  }

  /* 5. 调用tick()方法,通过使用包含当前时间的对象调用setState()来调度UI更新。
        通过调用setState() ,React 知道状态已经改变,并再次调用render()方法
        来确定屏幕上应当显示什么。这一次,render()方法中的this.state.date将不同,
        所以渲染输出将包含更新的时间,并相应地更新DOM。
  */
  tick() {
    this.setState({
      date: new Date()
    });
  }

  // 3. 随后render方法被调用,将Clock组件返回的元素输出到屏幕
  render() {
    return (
      <div>
        <h1>Hello, world!</h1>
        <h2>It is {this.state.date.toLocaleTimeString()}.</h2>
      </div>
    );
  }
}

// 1. 渲染Clock组件
ReactDOM.render(
  <Clock />,
  document.getElementById('root')
);

我们可以在组件类上声明特殊的方法,当组件挂载或卸载时,来运行一些代码

上例中的componentDidMountcomponentWillUnmount这些方法被称作生命周期钩子,分别在组件输出到 DOM 后、组件从DOM中移除时执行

正确地使用状态

关于 setState() 这里有三件事情需要知道

  1. 不要直接更新状态

例如,此代码不会重新渲染组件:

// Wrong
this.state.comment = 'Hello';

应当使用 setState():

// Correct
this.setState({comment: 'Hello'});

构造函数是唯一能够初始化 this.state 的地方。

  1. 状态更新可能是异步的

React 可以将多个setState() 调用合并成一个调用来提高性能。

因为 this.propsthis.state 可能是异步更新的,你不应该依靠它们的值来计算下一个状态。

例如,此代码可能无法更新计数器:

// Wrong
this.setState({
  counter: this.state.counter + this.props.increment,
});

要修复它,请使用第二种形式的 setState() 来接受一个函数而不是一个对象。 该函数将接收先前的状态作为第一个参数,将需要更新的值作为第二个参数:

// Correct
this.setState((prevState, props) => ({
  counter: prevState.counter + props.increment
}));

上方代码使用了箭头函数,但它也适用于常规函数:

// Correct
this.setState(function(prevState, props) {
  return {
    counter: prevState.counter + props.increment
  };
});
  1. 状态更新合并

当你调用 setState() 时,React 将你提供的对象合并到当前状态。例如,你的状态可能包含一些独立的变量:

  constructor(props) {
    super(props);
    this.state = {
      posts: [],
      comments: []
    };
  }

你可以调用 setState() 独立地更新它们:

  componentDidMount() {
    fetchPosts().then(response => {
      this.setState({
        posts: response.posts
      });
    });

    fetchComments().then(response => {
      this.setState({
        comments: response.comments
      });
    });
  }

这里的合并是浅合并,也就是说this.setState({comments})完整保留了this.state.posts,但完全替换了this.state.comments

相关文章

  • PHP的全栈之路3

    死磕React 第一回 上帝视角 官网当然是我们最佳的学习资料,但我记得一句话,好老师从来都不是按照课本顺序来讲义...

  • PHP的全栈之路5

    AntD 之旅 项目实战 一个更复杂的例子

  • PHP的全栈之路1

    对于一个上了年纪的普通程序员(年过三十),突然想成为全栈开发 迫于中年危机引发的思考之后的行为 先简单介绍下自己的...

  • PHP的全栈之路4

    死磕React 第二回 概念之间的关系 主题学习

  • PHP的全栈之路2

    回顾需求 选择前端框架 前端三大件Vue,Angular,React。只听过三位前辈的大名,未曾结识过 起初我打算...

  • PHP全栈进阶之路-A段

    计划: 1.独立完成十个不同类型的网站练手2.深度研究TP5底层源码,精通使用框架,争取达到私活级别3.通读前端知...

  • PHP全栈学习笔记3

    trim()函数,用于去除字符串首尾空格和特殊字符返回的是去掉的空格和特殊字符后的字符串 ltrim()函数,用于...

  • PHP全栈学习笔记3

    trim()函数,用于去除字符串首尾空格和特殊字符返回的是去掉的空格和特殊字符后的字符串 ltrim()函数,用于...

  • 全栈之路

    Why? 静下心来回顾自己进入学习计算机开始,种种的学习过程,从爱上游戏,想要学习游戏开始,自己用C++写了一个游...

  • PHP高级工程师必知必会知识点web全栈大福袋

    课程目标 PHP高级工程师必知必会知识点web全栈大福袋 适应人群 PHP工程师,全栈开发工程师 课程目录 0...

网友评论

      本文标题:PHP的全栈之路3

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