[每周日-先行者课堂笔记] -- react版的倒计时实现

各位同学们大家好,今天是4月9号周日,今天我们继续来做“倒计时”这个前端组件。之前我们是使用原生js来实现的,其实更多的只是实现了功能。

这一次我们使用ReactJs来实现它。react本身就不做过多的介绍了,相信真心关注前端的小伙伴们不可能对它一无所知。只提一下它的重点吧,一虚拟dom;二是全组件化。

而我们在日常使用react的过程中,更多的是跟组件化这三个字打交道。一般来讲,组件就是指被封装好的,且有一定功能的ui零件。

而react的思考方式,就是把页面上的每一个部分都按组件来看待。简单来讲,就是每个div,在react中都可以被看做一个组件,然后把这些react编写的组件,像div嵌套那样,进行大组件套小组件的这种层层包装的形式,组装成整个ui页面。

新的开发方式会肯定有它的好处,就是模块之间的彻底分离。比之前的所谓mvc更加彻底。

另外老话重提,react组件三特征:可组合,可重用,可维护。

来看ui图,先一分析一下结构。其实结构很简单,就是div里有一个ul,ul里有三个li容器横向排列,每个li里有从上到下的label span 而已。

在我看来,如果前端新人对于react的组件概念不太好理解,不太容易分得清每个组件要包含哪些东西?

那么可以直接用div容器的概念来理解react的组件。因为它们不管它们在开发、生产环境是什么样的形式,落实到页面dom中,全都是dom节点了。所以开始的时候,可以反着来理解一下。

就说这个倒计时应用吧,在开发它的时候,你可以按着先页面,后js的顺序。也就是先用react来把页面结构生成出来,然后在再相应的页面组件中添加各种js程序。

//==============

首先把页面的结构先搭出来,新建一个目录,。。。新建个html文件,js,css目录,

js目录里放这三个文件:

react.js 、react-dom.js 和 Browser.js

然后在html中引用。

其中,react.js 是 React 的核心库,

react-dom.js 是提供与 DOM 相关的功能,

Browser.js 的作用是将 JSX 语法转为 JavaScript 语法

最后写一个 <script> 标签,注意它的 type 属性为 text/babel 。

<script type="text/babel">

这是因为 React 独有的 JSX 语法,跟 JavaScript 不兼容。

凡是使用 JSX 的地方,都要加上 type="text/babel" 。

现在我们就可以开始写react了

回忆一下我们切静态页面的时候会怎么做?肯定是先搞个大的父容器出来,然后再在父容器中添加相应的各个子容器。

首先肯定得有个“根”节点做为最外层的父容器呀,那么,

  <body>
    <div id="timeWrap"></div>
  </body>

这个timewrap的div,它就是最外层的父容器。而我们刚才已经分析过,div里面就是ul,ul里面就是li,,,,

那么,用react生成的第一个组件类,就是ul,使用 React.createClass 生成第一个组件类:

//要记得react里的组件类,第一个字母要大写

var TimeWrapUl = React.createClass({
 render:function(){
 return <ul>...</ul>
 }
});

这里用到了 render 方法,该方法会返回一个React组件树,用来接受该组件树的变量名称必须首字母大写。并且该组件树只能有一个根节点,最终这棵组件树会被ReactDOM.render渲染成HTML标签。

这时的ul,它并不是一个真正的DOM节点,而是一个虚拟的DOM节点,这些节点就是一些标记之类的记号,只是React知道该如何处理它们。

ReactDOM.render(
  <TimeWrapUl />,
  document.getElementById('timeWrap')
);

按切页面的套路,接下来就该li了,

用 React.createClass 再来生成一个组件类,Day:

var Day = React.createClass({
  render:function(){
    return:<li></li>
  }
});

它里面要有li。

写好的Day这个组件类,怎么放呢?其实很简单,就是跟切页面的思路一样,就是放在ul里面就好,这样:

var TimeWrapUl = React.createClass({
  render: function() {
    return <ul>
  <Day />
    </ul>;
  }
});

接下来,把时,分,秒的都如此写出来,好了,到此时,页面结构搭完,就类似于静态页面切完了,该往里写js了。

//===================

按照一般的js开发思路,在写js之前 应该先搞一些初始值,然后开始加载 dom,

再搞一些function方法来修改操作这些值

当dom都加载好了,开始绑定事件,

然后再把这些值传递到“更新dom”的方法中。

//===================

而react它的特点之一,就是把组件看成一个状态机,有一个初始状态。

然后当“情况或条件”发生改变的时候,导致状态变化,然后重新渲染ui了。

而不能用以往操作dom的思路,不能想操作哪些,就去用id控制哪里

//===================

react中

初始化的方法: getInitialState (只会在组件初始化的时候调用一次)就是用来初始化状态的,这就相当于一般js开发之中的init()方法。

而传统前端开发中的“当dom加载完成”,在react中对应的,

// componentDidMount

就可以理解为,只会在组件渲染结束后调用一次

有点类似于window.onload

那么,一些要在dom加载之后才做的事情,应该放在它里面

我们可以通过this.setState()来修改状态。状态的每次修改都会出发render函数。

好啦,初始化,加载dom,修改状态都找到对应的方法了。

那么就这样,

在ul这个组件中添加相应的初始化方法 getInitialState

加载dom之后执行的方法 componentDidMount

//===================

getInitialState,用于定义初始状态,就是一个对象,

它可以通过this.state 属性读取

//===================

初始化完了,该加载dom了,用 componentDidMount 方法

在它里面写 this.setState() 来修改状态,触发 return 修改

为啥没变?

你得往Day这个组件里传数据啊,

我们需要给组件添加一个属性

组件的属性可以接受任意值,字符串、对象、函数等等都可以,

也就是说,基本可以随便命名,当然你不能乱写,差不多就行

写一个属性dayVal,

<Day dayVal = {this.state.day} />

为啥还没变?

//===================

因为Day这个组件类里,还没有写接收参数呢。

它也得有 初始化方法,getInitialState

然后还得有个接收参数的方法,它得用来显示日期呀,

因为状态改变了,它做为被加载的组件,得接受新的参数啊

需要使用,componentWillReceiveProps( object nextProps ) 方法

然后 this.setState() 修改状态,在Day中触发 render 修改,

在修改中用 this.state来获取属性

//===========

我们按着day的样式,把时,分,秒都这样写好。这样就是整个组件在初始化的时候给一个值,然后当dom加载完成之后给了另一个值,然后触发了render方法。

接下来我们就要使用setInterval方法,让这个过程不断的重复。这样计时器就Ok了。

把之前的倒计时js拿过来,就这样放这,间隔1000毫秒。

然后这个 this.setState 是不是应该放在setInterval里呀?这样才可以每隔一秒修改一次时分秒的值。

报错!!

说是this.setState is not a function,为啥?

因为在setInterval里,this的值变了。console.log看一下this,它的值变成了window,因为setInverval是window的方法

这有二种解决方法,

第一种,

我们需要一个绑定方法,bind(),许多同学可能以为它是react的。

但事实上,它是es5的方法,

参看,https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Function/bind

Function.prototype.bind()

bind()方法会创建一个新函数。当这个新函数被调用时,bind()的第一个参数将作为它运行时的 this,

bind() 函数会创建一个新函数(称为绑定函数),新函数与被调函数(绑定函数的目标函数)具有相同的函数体(在 ECMAScript 5 规范中内置的call属性)。

其实很简单,就是把componentDidMount所对应的匿名函数的this,传到了 setInterval里面去,

其实这种情况我更喜欢这样做,

var _self...

//===========

到这一步,这个倒计时的react版本,基本就算是做完了吧。

原文发布于微信公众号 - web前端教室(webfeel)

原文发表时间:2017-04-09

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏梦魇小栈

面试分享:2018阿里巴巴前端面试总结(题目+答案)

最开始的思路是用定时器实现,最后没有想的太完整,面试官给出的答案是用requestAnimationFrame。

1133
来自专栏较真的前端

Chrome开发者工具还有这些功能,你知道吗?

2728
来自专栏IMWeb前端团队

简单的实现Javascript的MVC

最近看了一篇文章,“30行代码实现Javascript中的MVC”,原文链接:http://www.jqsite.com/notes/1603205925.ht...

4197
来自专栏雪胖纸的玩蛇日常

vue学习(3)

webpack:打包机,它能将我们的html、css、js,font,png进行打包,交给服务器。

2072
来自专栏DeveWork

WordPress 中部署真正的懒加载(Lazy Load)

不少WordPress 主题(包括DeveWork.com目前的主题)都有部署jquery 插件“懒加载”(Lazy Load),但其实很多都不能产生真正的懒加...

2137
来自专栏从零开始学自动化测试

Selenium+python自动化82-只截某个元素的图

前言 selenium截取全图小伙伴们都知道,曾经去面试的时候,面试官问:如何截图某个元素的图?不要全部的,只要某个元素。。。小编一下子傻眼了, 苦心人,天不负...

4714
来自专栏木制robot技术杂谈

常用命令行快捷键

1465
来自专栏静晴轩

你所不知道的setTimeout

JavaScript提供定时执行代码的功能,叫做定时器(timer),主要由setTimeout()和setInterval()这两个函数来完成。它们向任务队列...

44912
来自专栏程序员宝库

Chrome 调试技巧

想必大家都在用console.log在控制台输出点东西,其实console还有其它的方法:

2492
来自专栏python3

tkinter -- OptionMenu

OptionMenu 的创建需要两个必要的参数,与当前值绑定的变量,通常为一 StringVar 类型;另一个是提供可选的内容列表,由 OptionMenu 的...

953

扫码关注云+社区