2019年1月

20190119 日迹

这段时间在找工作啦。

重新梳理了下自己的生活,发现之所以在2018欠下N多的债务,无非是因为贪婪的意识作祟,一直妄图有一步登天一样的效率来进行第一桶金的积累,结果正是被人顺着这种想法一直牵着走。

欲望是没有终止的,不管自己身处何处、身边何人给予肯定、当下有何种积累等,都无一例外地要把自己放到最客观的位置看待。经常有人说回归初心,我认为回归初心就是尝试用几年前那个自己来看待自己。在2018的困顿期,我一直果断地认为之前的我太过愚蠢、对利益无所算计,反而是在2018年对利益斤斤计较的我失去的更多。

这个2018年,涉足过灰色地带,冒出过大量的空手套白狼的想法,甚至有几次险些彻底违背本心和法律去做一些奇葩勾当,好在自己身边有个靠谱的人拉住了自己,没有一脚踏进深渊无法回头。很多次在想、在讨论怎样通过操作来得到一些政策上的补贴,口头上讲的是拿到了补贴可以用于事业发展,其实本心想的无非是回收成本、行为变现,这种想法本身就是危险的。

如今要做的事情,就是找到工作,老老实实做一些靠谱的事情,回到2017之前那种心态,真心把力量放到硬本领的提升和沉淀里,做长期的规划,认同现在的生活,寻找更健康更透明的前方。

很想对自己说一句,好久不见。

翻译:《5分钟入手React.js》

原文地址:[Learn React.js in 5 minutes](https://medium.freecodecamp.org/learn-react-js-in-5-minutes-526472d292f4)。
因为想撸一撸 React ,寻思着直接伸手应该比较愉快,就顺便翻译一篇国外的入门好啦。

5分钟入手 React.js ———— 超热门JavaScript库的快速指南

在这篇教程中,你会通过构建一个超简单小应用的方式对于 React.js 有一个基本的理解,我会把其中我个人认为不是特别核心的知识点暂且抛去不谈哈。

当你阅读这篇文章的时候,你也可以点击链接看一下发布在Scrimba的免费React课程,在那你可以通过48个互动视频来相对完整地学习这个库。

废话少说,整!

基础配置

刚开始使用React的时候,我们应该尽量使用最简单的配置来上手:比如像这样只是用<script />标签引入了ReactReactDOM的简单HTML文件:

    <html>
    <head>
    <script src="https://cdn.bootcss.com/react/15.5.4/react.min.js"></script>
    <script src="https://cdn.bootcss.com/react/15.5.4/react-dom.min.js"></script>
    <script src="https://cdn.bootcss.com/babel-standalone/6.15.0/babel.min.js"></script>
    </head>
    <body>
        <div id="root"></div>
        <script type="text/babel">
        
        /* 
        在此处写入React相关代码
        */
        
        </script>
    </body>
    </html>

译者:原作者使用的免费CDN加速是https://unpkg.com/,为了符合国情我全部替换成了https://www.bootcdn.cn/的同类文件,代码可以放心复制~

同时我们引入了Babel,因为我们在React相关代码中要使用一些用JSX语法来描述HTML内容的部分,此时我们需要将JSX来转化成普通的JavaScript,这样浏览器才能正常解析这段程序。

这里有两个地方需要注意一下:

  • 一个是我们标记了#root这个id的<div />标签。它是我们整个应用的根节点,我们程序的编译结果将出现在这个标签中;
  • 还有<script type="text/babel"></script>这个标签。这个标签是我们将要编写React.js代码的地方。

如果你想实验这段代码,可以查看Scrimba playground

译者:除了Scrimba网站,可以根据2016年10月的这篇文章了解下其他的在线编辑器以及特点。

组件

在React的世界里,一切都是组件,组件通常继承于一个JavaScript类。你可以通过继承React.Component类来创建组件,如下代码所示,我们来创建一个名为“Hello”的组件。

class Hello extends React.Component {
    render() {
        return <h1>Hello world!</h1>;
    }
}

然后,我们可以定义组件的方法,不过我们的示例中只定义了一个render()方法。

render()方法中我们返回了一串希望React渲染到页面中的HTML代码,我们想让React把<h1>Hello world!</h1>代码渲染到根节点中。

然后我们调用ReactDOM.render()来给我们的小应用进行DOM渲染:

ReactDOM.render(
    <Hello />, 
    document.getElementById("root")
);

这段代码是我们让根节点与Hello组件产生关联的关键,结果请点击链接查看。

译者:点击这个CodePen地址查看这个例子。

刚刚出现的与HTML语法很相似的<Hello />就是我们刚刚提到的JSX。它并不是HTML,但是最终会转换成HTML来渲染。

下一步我们来学习数据绑定。

数据绑定

在React中有两种数据:Props 以及 State。最开始我们或许比较难以理解这两者的区别,不用太担心,在开始使用它们之后你就会更容易理解它们的具体意义。

State也可以称之为状态,它是组件所私有的、可以在组件内部修改的;而Props是外部传入的,不受组件本身控制。Props从可以控制数据的高层组件向低层组件传递。

一个组件可以直接地修改它的State,而不能直接修改它被传入的Props。

我们先看一下Props。

Props

我们的“Hello”组件是一个非常基础的组件,它无论如何渲染都智慧渲染出相同的数据。React中一个很重要的部分就是它的复用性,也就是说你可以只编写一次组件、却在各种不同的时候调用它——比如显示不同的信息。

为了给刚刚的组件增加复用性,我们来为它添加 Props 。下面的message="my friend"就是你使用 Props 将数据传递给组件的方式:

ReactDOM.render(
    <Hello message="老铁" />, 
    document.getElementById("root")
);

这个被命名为“message”的prop我们为他赋值为“老铁”,我们在组件内使用this.props.message的语法来调用它:

class Hello extends React.Component {
    render() {
        return <h1>Hello {this.props.message}!</h1>;
    }
}

结果请点击链接查看。

译者:点击这个CodePen地址查看这个例子。

我们在代码中用一个大括号来包裹了{this.props.message}代码,这个大括号是用来进行转义操作的,它来标识这段大括号中的JSX为JavaScript表达式。

那么我们现在就有一个可以复用的组件了,它可以让我们给任何宾语喊“Hello”!真牛逼!

那我们该怎么让组件能够拥有自己修改数据的能力呢?那就要使用State了!

State

State是React中的另一种数据形式,它可以在组件内部由组件自己来直接修改,不需要外部传入。

所以你如果需要组件内部能够通过用户交互等形式让数据产生变化,你就需要把它存在组件的State里。

初始化状态

为了将状态进行初始化,我们需要在组件的constructor()方法中简单设置一下this.state参数。在我们的例子中,我们依然是只设置一个“message”属性。

class Hello extends React.Component {
    
    constructor(){
        super();
        this.state = {
            message: "State中的Message"
        };
    }
    
    render() {
        return <h1>Hello {this.state.message}!</h1>;
    }
}

在我们设置State的具体属性的时候,我们需要先在constructor(){}中调用super()方法,只有这样才能在继承父类的子类中正确获取到类型的this

更新 State 中的数据

想要修改State里面的值,最简单的做法是调用this.setState(),并把要更新的值放置其中。下面我们在组件中定义一个updateMessage()方法来更新数据。

class Hello extends React.Component {
    
    constructor(){
        super();
        this.state = {
            message: "State中的Message"
        };
        this.updateMessage = this.updateMessage.bind(this);
   }
    updateMessage() {
        this.setState({
            message: "更新过的State中的Message"
        });
    }    
    render() {
        return <h1>Hello {this.state.message}!</h1>;
    }
}

这个时候要注意一下,我们在updateMessage()中胡作非为的时候,必须要确认this已经绑定到了组件方法中,不然我们无法访问到正确的this

下一步我们在render()中创建一个点击后就能触发updateMessage()的按钮:

render() {
  return (
     <div>
       <h1>Hello {this.state.message}!</h1>
       <button onClick={this.updateMessage}>点我更新State!</button>
     </div>   
  )
}

这样我们就在按钮上挂了一个事件监听器,来监听onClick事件。当事件触发时,组件就会调用updateMessage()方法。如下为完整组件代码:

class Hello extends React.Component {
    
    constructor(){
        super();
        this.state = {
            message: "State中的Message"
        };
        this.updateMessage = this.updateMessage.bind(this);
   }
    updateMessage() {
        this.setState({
            message: "更新过的State中的Message"
        });
    }    
    render() {
        return (
         <div>
           <h1>Hello {this.state.message}!</h1>
           <button onClick={this.updateMessage}>点我更新State!</button>
         </div>   
        )
    }
}

点击按钮后,updateMessage()方法就会调用this.setState(),并通过传值来修改其中的this.state.message。点击之后的效果点击链接查看。

译者:点击这个CodePen地址查看这个例子。

恭喜你!你已经对于React中比较重要的概念有了一个基本的认识啦!

译者:后面作者的感叹、广告、自我介绍都不翻译了,在DocsChina也有类似的React快速入门的中文文档,需要的小伙伴可以自取。

Fiftone

前段时间在博客给自己标了一个新的名字,伍时壹,终于满足了自己中二的期冀。
于是在博客也写了一句:闲情择月 不如心散无常。
赶上今天在阿里的语雀上注册账号建库,就想起了这句,就给闲情择月两句配了文,居然感觉回到了八九年前的时候,内心洋溢出一股莫名其妙的青涩。

信笔轻言闲情事,溯誉尝究择月光;
清植溉荟求心散,黄道飞星录无常;
卸甲无人以为伍,却已笑谈止惶张;
任尔来去度几时,壹品黑茶暖未央。

或许男人,多少都会有一点仿佛是个诗人的时候吧。

倒计时功能在JavaScript实现中的毫秒级时间差调试及思考

在一个脑洞里有个倒计时功能,正在想怎么实现,突然想起一个很关键的问题:

之前一些应用场景的倒计时中我使用了 setTimeout 进行递归处理,setTimeout 和 setInterval 一定是有效率区别的,区别有多大?

然后做一个尝试:

先定义提示方法

function timer(id){ console.timeEnd(id); console.time(id); setTimeout('timer("'+id+'")',1000); }

首先定义一下setTimeout的循环计时器。

function timer2(id){ console.timeEnd(id); console.time(id); }

然后定义一下setInterval中循环的方法。

启动!

timer('setTimeout'); setInterval('timer2("interval")',1000)

五年过去了……

如图所示:
运行截图

根据图上打印的日志情况可以粗略猜到了,setInterval计时1000的时候如果因为机器性能等影响到的时候(我在测试的过程中左右切换应用和进行了其他操作),会自己进行一些调节性的操作,很鸡贼;setTimeout就很憨厚了,踏踏实实计时,一次做慢了无所谓下次该咋样还咋样,这种着眼现实的精神很值得我们学习(鼓掌)。

深入一步

刚刚的毕竟是猜测,我们可以继续去研究下它的更向下一些的原理。首先刚刚的demo就不是特别完善,于是我又参考 StackOverflow 的一个回答优化了下撸了另一个可视化程度比较好的 点击查看demo,有兴趣的小伙伴可以点击去看一下。

测试的结果和之前是一样的,都是interval出现了“效率更高一点”的样子。

然后在JavaScriptInfo上查了下资料,资料中显示了如下两张图:

jsinfo-pic1

此图为setInterval(function_name,100)的执行图,

jsinfo-pic2

此图为setTimeout(function() {...}, 100);的递归执行图。

这里给的解释说明了几个事情:

  • 两个计时器时间上的准确是没有问题的,也不存在合理微小延迟的说法
  • setInterval的计时器触发后即刻开始下次计时,setTimeout的计时器触发后到递归到下次计时之间涉及了业务代码的执行周期,所以相对而言会体现出“用时更长”的感觉

看到这里方才明白,并不是setTimeout有延迟,而是在demo中我忽略掉了两个计时器使用后业务代码的执行时间。

应用

如上所述,两种计时器的差别就在于业务代码执行周期产生的延迟了,也就是说并不是setTimeout不准确,只是他们的用途不完全相同。

在应用过程中,使用其中哪个计时器,要取决于我们的业务代码执行周期何如。比如业务代码运算量极其小、或者只是作为本地监听器,用setInterval会更好用一些;如果业务代码执行周期较长,如定期提交用户操作信息,每次执行过程可能会突然出现执行时间超出计时器本身计时周期的情况,用setTimeout显然更稳妥也更合适。

所以说,还是放弃Baidu,健康搜索吧。