Zeno Tian


  • 首页

  • 归档

  • 标签

React官方文档笔记

发表于 2017-04-13

JSX语法

1.基础

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

2.JSX中嵌入表达式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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')
);

  1. JSX做表达式

    1
    2
    3
    4
    5
    6
    function getGreeting(user) {
    if (user) {
    return <h1>Hello, {formatName(user)}!</h1>;
    }
    return <h1>Hello, Stranger.</h1>;
    }
  2. JSX设置属性

    1
    2
    const element = <div tabIndex="0"></div>;
    const element = <img src={user.avatarUrl}></img>;
  3. JSX包含子元素

    1
    2
    3
    4
    5
    6
    7
    const element = <img src={user.avatarUrl} />; //不包含可直接关闭
    const element = (
    <div>
    <h1>Hello!</h1>
    <h2>Good to see you here.</h2>
    </div>
    );

6.JSX会转义所有值,所以可以防止XSS

渲染元素

JSX产生的是真实的DOM
当需要更新的时候与之前进行对比,只更新变更的部分
TODO:HRM多入口,官网示例是否更新整个DOM

组件和props

组件让您将UI拆分成独立的可重复使用的部分,并单独考虑每个部分。 在概念上,组件就像JavaScript函数。他们接受任意输入(称为“props”),并返回描述应该在屏幕上显示的React元素。

功能组件和类组件

1
2
3
function Welcome(props) {
return <h1>Hello, {props.name}</h1>;
}
1
2
3
4
5
class Welcome extends React.Component {
render() {
return <h1>Hello, {this.props.name}</h1>;
}
}

组件渲染

1
const element = <Welcome name="Sara" />;

当React看到一个表示用户定义组件的元素时,它将JSX属性作为单个对象传递给该组件。我们称这个对象为“道具”。 例如,该代码在页面上显示“Hello,Sara”:

组件开头字母大写

组件组成

只能有一个根组件

组件提取

学会拆分组件

Props只读

纯函数,相同输入输出相同

state和生命周期

ES6的class语法,创建的类组件才有自己的state和生命周期
继承自react

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class Clock extends React.Component {
constructor(props) {
super(props)
this.state = {date: new Date}
}
componentDidMount() {
//生命周期等函数
}
render() {
return (
<div>
<h2>现在是{this.state.date.toLocaleTimeString()}</h2>
</div>
)
}
}

设置state

  1. 必须调用setState

2.

  • React可以将多个setState()调用批量化为单个更新以实现性能。 因为this.props和this.state可能会异步更新,所以您不应该依靠它们的值来计算下一个状态。
  • 可以异步设置state,setState()接受回调函数,异步更新
    1
    2
    3
    4
    this.setState((prevState, props) => ({
    //在上一轮state设置完成后,再去计算设置state
    counter: prevState.counter + props.increment
    }));
  1. setState是一个浅复制操作

数据单向流

state可以作为子组件的props传递下去

事件

驼峰式事件名
不能通过返回fasle阻止默认事件,必须调用preventDefault

1
2
3
4
5
6
7
8
9
10
11
12
function ActionLink() {
function handleClick(e) {
e.preventDefault();
console.log('The link was clicked.');
}
return (
<a href="#" onClick={handleClick}>
Click me
</a>
);
}

在这里,e是一个合成事件。 React根据W3C规范定义了这些合成事件,因此您不必担心跨浏览器的兼容性。请参阅SyntheticEvent参考指南了解更多信息。 当使用React时,您通常不需要调用addEventListener来在创建DOM元素之后添加监听器。而是在元素最初呈现时提供一个监听器。 当您使用ES6类定义组件时,常见的模式是将事件处理程序作为类上的方法。例如,此Toggle组件呈现一个按钮,让用户在“ON”和“OFF”状态之间切换:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
class Toggle extends React.Component {
constructor(props) {
super(props);
this.state = {isToggleOn: true};
//绑定this,确保函数在实例上呗吊桶
this.handleClick = this.handleClick.bind(this);
}
handleClick() {
this.setState(prevState => ({
isToggleOn: !prevState.isToggleOn
}));
}
render() {
return (
<button onClick={this.handleClick}>
{this.state.isToggleOn ? 'ON' : 'OFF'}
</button>
);
}
}
ReactDOM.render(
<Toggle />,
document.getElementById('root')
);

函数绑定问题,因为JS的calss的机制必须在构造器中绑定一次this
一般来说onClck={this.handleClick}这样无参数的绑定事件,必须在构造器中使用绑定

或者使用实验性的语法

  1. 属性初始化语法
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    class LoggingButton extends React.Component {
    handleClick = () => {
    console.log('this is:', this);
    }
    render() {
    return (
    <button onClick={this.handleClick}>
    Click me
    </button>
    );
    }
    }

2.回调中使用箭头函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class LoggingButton extends React.Component {
handleClick() {
console.log('this is:', this);
}
render() {
// This syntax ensures `this` is bound within handleClick
return (
<button onClick={(e) => this.handleClick(e)}>
Click me
</button>
);
}
}

这种语法的问题是每次LoggingButton渲染时都会创建一个不同的回调函数。在大多数情况下,这很好。但是,如果这个回调作为props传递给较低的组件,这些组件可能会进行额外的重新渲染。我们通常建议在构造函数中使用绑定或使用属性初始化器语法来避免这种性能问题。

条件渲染

1
2
3
4
5
6
7
8
9
10
11
12
13
function Greeting(props) {
const isLoggedIn = props.isLoggedIn;
if (isLoggedIn) {
return <UserGreeting />;
}
return <GuestGreeting />;
}
ReactDOM.render(
// Try changing to isLoggedIn={true}:
<Greeting isLoggedIn={false} />,
document.getElementById('root')
);

元素变量

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
render() {
const isLoggedIn = this.state.isLoggedIn;
let button = null;
if (isLoggedIn) {
button = <LogoutButton onClick={this.handleLogoutClick} />;
} else {
button = <LoginButton onClick={this.handleLoginClick} />;
}
return (
<div>
<Greeting isLoggedIn={isLoggedIn} />
{button}
</div>
);
}

从组件的render方法返回null不会影响组件生命周期方法的触发。例如,componentWillUpdate和componentDidUpdate仍将被调用

List和Key

遍历输出组件,必须带key,用来优化
键帮助React确定哪些项目已更改,添加或删除。应该给数组中的元素赋予元素一个稳定的身份:
实在不行用索引(但是项目重新排序容易造成性能低下)
key必须唯一

Forms

可控表单

不可控表单

高级指南

JSX深入

JSX

JSX只是语法糖
使用打包器,在使用JSX的时候必须将React引入
使用点.的方式,调用模块内的组件
用户组件必须大写

您不能使用通用表达式作为React元素类型。如果您想使用通用表达式来表示元素的类型,请先将其分配给大写的变量。当您要根据道具渲染不同的组件时,会出现这种情况

1
2
3
4
5
6
7
8
9
10
11
12
import React from 'react';
import { PhotoStory, VideoStory } from './stories';
const components = {
photo: PhotoStory,
video: VideoStory
};
function Story(props) {
// Wrong! JSX type can't be an expression.
return <components[props.storyType] story={props.story} />;
}

1
2
3
4
5
6
7
8
9
10
11
12
13
import React from 'react';
import { PhotoStory, VideoStory } from './stories';
const components = {
photo: PhotoStory,
video: VideoStory
};
function Story(props) {
// Correct! JSX type can be a capitalized variable.
const SpecificStory = components[props.storyType];
return <SpecificStory story={props.story} />;
}

props in JSX

表达式

1
2
3
4
5
6
7
8
9
function NumberDescriber(props) {
let description;
if (props.number % 2 == 0) {
description = <strong>even</strong>;
} else {
description = <i>odd</i>;
}
return <div>{props.number} is an {description} number</div>;
}

props默认为true

扩展运算符

1
2
3
4
function App2() {
const props = {firstName: 'Ben', lastName: 'Hector'};
return <Greeting {...props} />;
}

Children in JSX

Refs和DOM

  • 管理焦点,文本选择或媒体播放。
  • 触发强制性动画。
  • 与第三方DOM库集成。

    React支持一个可以附加到任何组件的特殊属性。 ref属性采用回调函数,并且在组件被装载或卸载之后立即执行回调。 当在HTML元素上使用ref属性时,ref回调接收底层的DOM元素作为其参数。例如,此代码使用引用回调来存储对DOM节点的引用:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    class CustomTextInput extends React.Component {
    constructor(props) {
    super(props);
    this.focus = this.focus.bind(this);
    }
    focus() {
    // Explicitly focus the text input using the raw DOM API
    this.textInput.focus();
    }
    render() {
    // Use the `ref` callback to store a reference to the text input DOM
    // element in an instance field (for example, this.textInput).
    return (
    <div>
    <input
    type="text"
    ref={(input) => { this.textInput = input; }} />
    <input
    type="button"
    value="Focus the text input"
    onClick={this.focus}
    />
    </div>
    );
    }
    }

当组件挂载时,React将使用DOM元素调用ref回调,并在卸载时将其调用为null。 使用ref回调只是为了在类上设置属性是访问DOM元素的常见模式。首选的方法是在ref回调中设置属性,就像上面的例子一样。甚至有一个较短的写法:
ref = {input => this.textInput = input}

在类组件上使用Ref

1
2
3
4
5
6
7
8
9
10
11
12
class AutoFocusTextInput extends React.Component {
componentDidMount() {
this.textInput.focus();
}
render() {
return (
<CustomTextInput
ref={(input) => { this.textInput = input; }} />
);
}
}

函数组件是不能使用refs的,因为没有实例,但是在原生dom元素上可以使用
this.refs.textInput写法作废

性能优化

编译设置生产环境
chromeTimeline工具

高阶组件

一种设计模式
具体来说,高阶分量是一个获取组件并返回新组件的函数。

你不知道的JS-作用域

发表于 2017-03-13

作用域

1.1编译原理

  • 分词/词法分析(Tokenizing/Lexing)
    将字符串分解成代码块(词法单元)
    分词和词法分析的差异在于词法单元的识别是通过有状态还是无状态的
  • 解析/语法分析(Parsing)
    将词法单元流(数组)转换为由元素逐级嵌套组成的代表程序语法结构的树(抽象语法树AST)
  • 代码生成
    将AST转换为可执行代码

1.2作用域

JS运行

  • 引擎:负责JS编译与执行
  • 编译器:负责语法分析以及代码生成
  • 作用域:收集并维护所有声明的变量(标识符),根据规则确保执行代码对变量的访问权限

声明解析

1
var a = 2
1. `var a`编译器查询作用域是否存在变量`a`,有则忽略继续编译,无则要求作用域在当前作用域集合中声明一个为`a`的变量
2. 编译器生成运行代码给引擎,处理`a = 2`赋值操作。引擎询问作用域,当前作用域是否存在`a`,存在就使用,否则继续查找。
   最终没有查找到将会报错。

LHS/RHS

变量出现在赋值操作左侧进行LHS,非左侧进行RHS

LHS:只查找
BHS:查找并取到值()

1
2
3
4
5
6
7
8
function foo(a) {
console.log(a)
//RHS,获得a的值传入console.log方法
//RHS,获得console对象,并得到log方法
}
foo(2)
//函数调用RHS,查找foo并获得foo的值
//LHS查询,将2赋值给参数a

1
2
3
4
5
6
7
8
9
10
11
12
13
function foo(a) {
var b = a
//LHS,b=
//RHS,=a
return a + b
//RHS, a
//RHS, b
}
var c = foo(2)
//LHS,c=
//RHS,foo(2)
//LHS,(2)
//LHS,foo

1.3作用域嵌套

作用域嵌套,在当前作用域无法找到变量时,引擎会在外层作用域中继续查找

1.4异常

RHS查询找不到会抛出异常
非严格LHS找不到会创建一个
严格模式LHS找不到也会抛出异常
RHS进行不合理操作会抛出TypeError

第二章:词法作用域

两种工作模型

  1. 词法作用域
  2. 动态作用域

    2.1词法阶段

    定义在词法阶段的作用域。(写代码是将变量和块作用域写在哪里决定的)

查找:

遮蔽效应:内部标识符”遮蔽”外部标识符

2.2欺骗词法

欺骗词法作用域会导致性能下降

2.2.1 eval

eval中包含一个或多个声明会对作用域进行修改
严格模式下,eval有自己的词法作用域

setTimeout(),setInterval()第一个参数是字符串的时候,字符串可以被解释为动态生成的函数代码

new Function()接受代码字符串,转换为动态生成的函数

避免使用以上方式

2.2.2 with

严格模式下被禁止

2.2.3 性能

在编译阶段进行的性能优化,有些依赖于能够根据代码词法进行静态分析,预先确定所有变量和函数的定义位置,才能执行时快速找到标识符。

第三章,函数作用域和块作作用域

3.1 函数中的作用域

Js基于函数的作用域
含义:属于这个函数的全部变量都可以在整个函数范围内使用以及复用

3.2 隐藏内部实现

最小授权,最小暴露原则:最小限度的暴露必要内容

规避冲突:避免同名标识符之间的冲突

  1. 全局命名空间
    通过全局作用域生命对象,将功能通过对象暴露给外界
  2. 模块管理

3.3 函数作用域

让函数名不污染所在作用域,并能够自动运行
函数表达式写法
如果function 是声明的第一个词,就是函数声明,否则是函数表达式
函数声明和函数表达式的区别:名称标识符绑定在何处
函数声明会绑定在所在作用域中
函数表达式会绑定在函数表达式自身的函数中

3.3.1 匿名和具名

匿名函数的缺点:

1. 调试困难
2. 引用自身需要`arguments.callee`
3. 可读性差
行内函数表达式可以指定函数名,所以给函数表达式命名是最佳实践

3.3.2 立即执行函数表达式IIFE

IIFE的两种写法

  1. (function(){})()
  2. (function(){}())

IIFE的用途

  1. 函数调用传参
    1
    2
    3
    (function(global){})(window)
    (function(undefined){})()
    可以确保undefined是undefined

2.倒置代码运行顺序
将需要运行的函数放在第二位,在IIFE执行之后当参数传递进去

1
2
3
4
5
6
7
(function IIFE (def){
def(window)
}(function def(global) {
var a =3
console.log(3)//3
console.log(global.a)//a
}))

3.4 块作用域

块作用域是对最小授权原则进行扩展的工具

3.4.1 with

用with从对象中创建出的作用域仅在with声明中有效

3.4.2 try/catch

catch会创建一个块级作用域,其中声明的变量仅在catch内部有效

3.4.3 let

let 可以将变量绑定到所在的任意作用域中({内部})
推荐显式的使用块级作用域,

1
2
3
4
5
if (foo) {
{
let bar
}
}

  1. 垃圾收集
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    function process (data) {}
    var someReallyBigData = {}
    process(someReallyBigData)
    var btn = document.getElementById('my_button')
    btn.addEventListener('click', function click(evt) {
    //形成了闭包, 保留了整个外层作用域
    console.log('button clicked')
    }, false)

通过块级作用域,将变量进行本地绑定

1
2
3
4
5
6
7
8
9
10
11
12
13
14
function process (data) {}
{
let someReallyBigData = {}
process(someReallyBigData)
}
var btn = document.getElementById('my_button')
btn.addEventListener('click', function click(evt) {
//形成了闭包, 保留了整个外层作用域
console.log('button clicked')
}, false)

  1. let循环
    将i重新绑定到了循环的每一个迭代中
    1
    2
    3
    4
    5
    6
    7
    //代码说明
    {
    let j
    for (j=0; j<10; j++) {
    let i = j
    }
    }

let声明属于一个新的作用域而不是当前函数作用域也不是全局作用域

3.4.4

const固定常量不可修改

4 提升

4.2 编译器与提升

包含变量和函数在内的所有声明都会在任何代码被执行前首先被处理
定义声明在编译阶段进行,只有声明本身会被提升

4.3 函数优先

函数与变量声明都会提升,函数优先

5 作用域闭包

5.2 闭包实质

定义:函数可以记住并访问所在的词法作用域时,就产生了闭包。

1
2
3
4
5
6
7
8
9
function foo() {
var a = 2
function bar() {
console.log(a)
}
return bar
}
var baz = foo()
baz()

在自己定义的词法作用域之外执行,foo内存无法回收,导致foo内部作用域依然存在。
bar()依然持有对该作用域的引用,这个引用叫闭包

5.3 闭包深入

1
2
3
4
5
function wait (message) {
setTimeout(function timer(){
console.log(message)
}, 1000)
}
1
2
3
4
5
6
function setupBot (name, selector) {
$(selector).click(function activator(){
console.log('Activating:' + name)
})
}
setupBot('Closure Bot1', '#bot_1')

只要使用回调函数,实际上就是在使用闭包。

5.4 循环和闭包

1
2
3
4
5
6
for (var i=1; i<=5; i++) {
setTimeout(function timer(){
console.log(i)
}, 0)
}
//66666

定时器的回调函数在循环结束时才执行。

1
2
3
4
5
6
7
for (var i=1; i<=5; i++) {
(function(j) {
setTimeout(function timer(){
console.log(j)
}, 0)
})(i)
}

迭代内使用IIFE为每个迭代都生成一个新的作用域
延迟函数的回调在新的作用域封闭在每个迭代内部

块级作用域

1
2
3
4
5
for (let i=1; i<=5; i++) {
setTimeout(function timer(){
console.log(i)
}, 0)
}

let为每一次迭代生成块级作用域

5.5 模块

函数通过return,将内部函数暴露在外部,内部函数依旧保持函数的作用域。形成模块

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
function CoolModule() {
var something = 'coll'
var another = [1, 2, 3]
function doSomething() {
console.log(something)
}
function doAnother() {
console.log(anoyher.join('!'))
}
return {
doSomething: doSomething,
doAnother: doAnother
}
}
var foo = CoolModule()
foo.donSomething()//coll
foo.doAnother()//1!2!3
//每次调用都会创建新的模块实例

模块模式的两个条件

  1. 必须有外部的封闭函数,至少被调用一次(创建模块实例)
  2. 封闭函数必须返回一个内部函数,内部函数才能在私有作用域中形成闭包

一个从函数调用所返回的,只有数据属性而没有闭包函数的对象并不是真正的模块

单例模式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
var foo = ( function CoolModule() {
var something = 'coll'
var another = [1, 2, 3]
function doSomething() {
console.log(something)
}
function doAnother() {
console.log(anoyher.join('!'))
}
return {
doSomething: doSomething,
doAnother: doAnother
}
})()
foo.donSomething()//coll
foo.doAnother()//1!2!3
//转换为IIFE,只生成了一个实例

命名将要作为公共API返回的对象

1
2
3
4
5
var foo = (function CollModule(id){
function change(){
publicAPI.identify = identify2
}
})

5.5.1 模块机制

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
var MyModules = (function Manager(){
var modules = {}
function define(name, deps, impl) {
for (var i=0; i<deps.length; i++) {
deps[i] = modules[deps[i]]
//依赖注入
}
modules[name] = impl.apply(impl, deps)
}
function get(name) {
return modules[name]
}
return {
define: define,
get: get
}
})()
//定义模块
MyModules.define('bar', [], function () {
function hello(who) {
return 'let me introduce:' + who
}
return {
hello: hello
}
//闭包,保持内部函数hello引用
})
MyModules.define('foo', ['bar'], function (bar) {
var hungry = 'hippo'
function awesome() {
console.log(bar.hello(hungry).toUpperCase())
}
return {
awesome: awesome
}
//闭包,保持内部函数awesome引用
})
var bar = MyModules.get('bar')
var foo = MyModules.get('foo')
console.log(bar.hello('hippo'))
foo.awesome()//

5.5.2 未来模块机制

ES6的模块语法支持,将单个文件当做独立模块处理

基于函数的模块不稳定(不能被编译器识别/动态)
es6模块可以再编译器检查导入模块的API和成员是否真实存在(可以进行静态检查)

5.6 小结

当函数可以记住并访问所在的词法作用域,既是函数是在当前词法作用域之外执行,这时产生了闭包

模块的两个主要特征:

  1. 为创建内部作用域而调用包装函数
  2. 包装函数的返回值至少包括一个队内部函数的引用,这样才能创建涵盖整个包装函数内部作用域的闭包

动态作用域

词法作用域特征:定义在代码书写阶段
动态作用域:作用域链是基于调用栈的,而不是作用域嵌套
js并不具有动态作用域,但是this机制某种程度上像动态作用域

1
2
3
4
5
6
7
8
9
10
11
function foo() {
console.log(a)//如果是动态作用域,理论上输出3
//实际上Js没有动态作用域,所以结果为2
}
function bar() {
var a = 3
foo()
}
var a = 2
bar()

this词法

箭头函数将当前的词法作用域覆盖this本来的值

缺点:

  1. 容易混淆this绑定规则和词法作用域规则
  2. 匿名而非具名的

自控力

发表于 2017-03-11

自控力

1. 什么是自控力

  • 为什么会有意志力?
    意志力的根本是在面临问题时做出正确的选择。
    意志力是抑制冲动的能力。
  • 意志力的神经学原理
    前额皮质的作用控制人体运动,控制关注什么想什么。
  • 两个自我导致的问题
    人类虽然进化出自控系统,但是原始的本能也依然存在。
    人的大脑中一般都会有两个想法,向着相反的方向,不论选择哪一个都没有做错。只是两个想法觉得重要的东西不同。
    剖析:自身面临的意志力的挑战。在面临挑战的时候,需要自己意识的两种想法的存在。可以通过标签化(起名字)的方式,具象两个想法
    原始冲动虽然会带来麻烦,但是对我们也是有利的。没有欲望,容易沮丧,没有恐惧,无法保护自我。
    学会利用原始本能
  • 认识自己(自我意识)
    做一件事的时候,一定要意识到自己在做什么?我们为什么这样做?做这件事情之前我们需要做什么?
    没有自我意识的时候,大脑会默认选择最简单的事情。
    现代社会充斥的诱惑和刺激,不断冲击着人们的自控力。注意力分散的人更容易向诱惑屈服。
    想要更强的自控力需要有更多的自我意识。
    实验:选择与一天将所做的决定都记下来。回想分析,哪些有利于实现目标,哪些在消磨意志?
  • 训练大脑,增强意志力
    大脑可以像肌肉一样锻炼
    五分钟冥想训练:
    1. 原地不动安静做好
    2. 注意呼吸,吸气与呼气在脑海中默念‘呼’,‘吸’。
    3. 感受呼吸,任何事情不要想,专注于呼吸。如果走神,通过默念‘呼’和‘吸’将注意力重新集中
    4. 每天训练也比将训练拖到明天好。

      2. 意志力的本能

  • 两种威胁
    1. 面临真正为危险的时候,原始本能会启动应激反应。应激反应会自动让身体做出调整。应激反应是一种管理能量的本能,决定了如何利用有限的体力和脑力
    2. 现实生活很少有真正的威胁,不会对自己造成直接的伤害,一般是由神经刺激造成的欲望,欲望无法消灭只能克制。此时不会触发应激反应,所以需要别的办法来克制。
      剖析:什么是威胁?我们总觉得诱惑和麻烦来自外部,但问题出现在自己身上。想要解决问题也只能在自己身上。思考自身受到诱惑的时候,自己的内心世界。
  • 意志力本能:三思而后行
    三思而后行与应激反应的区别:前者起因是认识到了内在冲突,而不是外在威胁。本能(欲望)会促使你做出潜在的错误决定。想要保护自己必须需要自控力。最有效的办法是放慢速度。
  • 大脑和身体
    三思而后行:大脑让身体意识到你的目标,同时克制冲动。前额皮质要传递自控要求,降低控制心率、血压、呼吸的大脑区域运转速度。

    但是在事实中,三思而后行不行像本能。按照欲望从事更像是本能。

  • 心率变异度
    反应压力状态和平静状态下不同的身体状态。
    感受到压力,交感神经系统控制身体,心率升高,心率变异度降低。伴随着应激反应产生焦虑或愤怒,心率被迫保持在较高水平。
    自控时:副交感神经系统发挥主要作用,缓解压力,控制冲动,心率降低,心率变异度升高。可以更好的集中注意力并保持平静。

    心率变异度反映意志力的程度。心理学家将心率变异度称为身体的意志力储备。

    任何给身心带来压力的东西都会影响自控力的生理基础。焦虑、愤怒、抑郁和孤独都与低的心率变异度和自控力有关。慢性疼痛和慢性疾病也会消耗意志力储备。

    减轻压力,保持健康的方法:锻炼,保证良好睡眠,保证健康饮食。都可以增强身体和意志力储备

  • 实验:通过呼吸实现自控
    练习将呼吸降低至每分钟4-6次。每天可进行20分钟练习。
    或者当面临意志力挑战的时候,尝试放慢呼吸。

  • 训练身心
    两种增长方法增强自控力的生理基础

    1. 体育锻炼:提高心率变异度的基准线,从而改善自控力的生理基础。
      5分钟锻炼放松即可。
    2. 睡眠:长期睡眠不足容易感到压力,萌生欲望,难控制情绪,注意力下降。
  • 问题:当睡眠成为意志力挑战
    明知道需要睡觉,却没办法早睡。就不要想睡觉这件事。思考到底对什么事情说了’我想要’。

  • 自控力太强的代价
    科学家认为:长时间自控像是慢性压力。适当的自控是必须的,试图控制所有的思想、情绪、行为会带来过重的生理负担。

  • 实验:放松恢复意志力
    生理学放松:心率和呼吸放缓,血压降低,肌肉放松,大脑不去规划未来,也不分析过去。
    躺着,枕头垫着膝盖,腿稍稍抬起,闭上眼睛,几次深呼吸。如果觉的身体有地方紧张。有意识的挤压或收缩肌肉,然后不再管它。

  • 压力:意志力的死敌
    压力和自控的生理学基础是相互排斥的。
    想要更好的应对意志力挑战,需要更有效地管理压力,照顾自己。

  • 剖析:压力和自控
    担忧和过度工作如何影响自己的选择?负面情绪度意志力的消耗?

3. 自控力的极限

人们早上的意志力最强,随后跟随时间推移逐渐减弱。

  • 自控力的肌肉模式
    与肌肉锻炼类似,一旦时间过长注意力训练不仅会分散注意力,还会消耗身体的能量。自控力如同肌肉,使用之后会渐渐疲惫。
    很多认为不需要意志力的事情,会消耗有限的能量。每次试图对抗冲动的时候,都会使用有限的意志力。
  • 剖析:意志力波动
    观察自身什么时候意志力最强?
    通过了解自己更明智的规划日程。

  • 为什么自控力存在局限?
    大脑能量耗尽导致了意志力的枯竭?适时补充糖分?
    大脑可能将血糖含量作为资源稀缺或资源充足的标准。只有在能量充足的情况下,大脑才会将资源分配给自控系统使用。

  • 实验:意志力饮食方案
    突然增加的糖分,可以在短期内面对紧急情况时有更强的意志力。但是过度依赖糖分并不是自控的好办法。
    推荐低血糖饮食:瘦肉蛋白,坚果和豆类,粗纤维谷物类和麦片,水果和蔬菜。

  • 训练‘意志力肌肉’
    控制自己以前不会去控制的小事。在一些小事上持续自控也可以提高整体的意志力。

  • 实验:锻炼意志力
    我不要:不随便发誓,坐下不抖腿,不二郎腿,用不常用的手进行日常活动
    我要:每天做一件事,不再找接口,冥想五分钟,或者每天给家人电话。
    自我监控:认真记录平时不关注的事。支出,饮食,或者时间

  • 自控力的极限
    感受到疲惫,不是身体反应,而是一种感觉,一种情绪。
    大脑中的过度保护性的监督机制发生作用,产生虚假疲惫。
    事实上的意志力储备比感觉上的要多,犹如长跑中的虚假疲惫,挺过去就好。

  • 剖析:疲惫感是真的吗?

  • 实验:你想要什么?
    意志力告急,挖掘自己’我想要’的力量。
    1. 挑战成功,会收获什么?
    2. 还有谁会获益?
    3. 想象成功后的样子

4. 为什么会容忍

  • ‘道德许可效应’,对补偿的渴望常常使我们堕落。我们很容易认为纵容自己是对美德的奖励,从而忘记目标,向诱惑屈服。
    仅仅是思考做一些好事,就可以让人产生(向欲望屈服)的冲动。

    我们通常相信本能,只有当需要解释自己的判断的时候,我们才会寻求逻辑。

    “道德许可”最糟糕的不是它可疑的逻辑而是诱使我们做出背离自己最大利益的事情。
    不要将事情定义为正确的事情,而是将事情定义为你能够达到某个目标的事。从道德的角度思考自己面临的意志力挑战时,我们就失去了自我判断能力。

  • 剖析:善与恶
    当意志力挑战成功的时候,你会不会告诉自己,你已经很“好”了?
    当屈服于拖延或者诱惑的时候,你会不会告诉自己你太“坏”了?
    你会不会已自己的善行为借口允许自己去做些违背你目标的事情?

  • 不要把支持目标实现的行为误以为是目标本身!!!

  • 错误的满足感
    前进一小步可能导致你后退两大步。
    人们习惯于将需要做的事情当成了自己已经付出的努力,会给我们带来错误的满足感。
    关注进步,让我们离目标越来越远。进步是完成目标的证据。应该清楚自己做了什么,盯紧自己的目标,为了实现目标,你要愿意付出更多。

  • 实现:取消许可,牢记理由
    记住自己为什么会拒绝诱惑?再次面临,回想当初为什么能拒绝诱惑?

  • 向明天赊账
    乐观精神总是让我们在当下放松自己,尤其是确信自己下次不会做出同样的选择。

  • 剖析:你是在向明天赊账吗?
    做决定时,注意是否有’未来再好好表现’的承诺。

  • 明天总会有时间做?
    如果我们预料到自己无法完成设定的目标,还不如在开始之前就认输。
    如果表现糟糕,却用对未来的乐观期待掩饰它,还不如一开始就不要设定这个目标。

  • 实验:明天和今天毫无区别
    当要改变某种行为,试着减少行为的变化性而不是减少行为本身。

  • 当罪恶看起来像美德
    许可陷阱:和最深切的欲望有关,我们都希望说服自己。我们想要的东西并没有那么坏,给诱惑我们的对象加以道德标准,好让我们放纵自己的时候毫无负罪感。
    光环效应:只要使你放纵的东西和使你觉得品德高尚的东西同时出现,就会产生光环效应。

  • 剖析:你正在被光环笼罩吗?
    会不会关注一个事物最有益的品质,而允许自己沉溺于它?

    当光环效应影响到意志力挑战时,需要找到最具体的衡量标准,来选择是否和最初的目标相同。

    我们之所以会奖励自己的良好行为,是因为我们内心深处觉得真正的自己想做坏事。这样看来每次自控都是惩罚,只有放纵自我才是奖励。
    要摆脱“道德许可”陷阱,那个变好的自己才是真正的自己,想按核心价值观生活的自己。

  • 剖析:你觉得自己是谁?
    面临考验的时候,想清楚哪一个是真实的你?

    不要将意志力挑战放在道德标准的框架中。如果只按照“正确”和“错误”来判断做过的事,而不是牢记真正想要的东西,会带来与目标想抵触的冲动。想做到始终如一,需要认同目标本身,而不是做善事时的光环。

    5. 欲望与幸福的混淆

  • 奖励的承诺
    受刺激的大脑区域奖励的不是快感,而是对快感的承诺。

  • “我想要”的神经生物学原理
    奖励系统:大脑发现获得奖励的机会 => 释放多巴胺 => 通知大脑其他部分
    大量的多巴胺并不能产生快乐的感觉,是一种激励,仿佛我们发现了如何得到快乐。
    多巴胺控制的是行动,而不是快乐。
    任何我们觉得会让自己高兴的东西都会刺激奖励系统。
    多巴胺劫持了注意力,大脑只会想着如何获得或者重复触发它。

  • 神经营销学
    当奖励的承诺释放多巴胺的时候,人更容易受到其他形式的诱惑。
    味觉,视觉,听觉的刺激下,分泌多巴胺,更容易让人们受到诱惑,而产生消费的行为。

  • 让多巴胺发挥作用
    试着将不喜欢的东西“多巴胺化”。

  • 实验:为了你的“我愿意”挑战分泌多巴胺
    什么事让你觉得不愉快,总是拖延着不做,能否将它和多巴胺联系在一起,从而促使自己去做?

  • 多巴胺的阴暗面
    带来的压力和快乐不分上下。因为多巴胺首要功能是让我们追求快乐,而不是让我们快乐。
    通常我们渴望的东西,既是快乐的源泉,也是压力的源泉。

  • 剖析:欲望和压力
    大部分人更关注对快乐的承诺,而不关注多巴胺刺激欲望时产生的不快乐。

    我们误把渴望的感觉当做了快乐的保证。
    奖励的承诺有很大的力量,他会让我们继续追求那些不会带给我们快乐的东西,会让我们消费那些不会带来满足感只会带来更多痛苦的东西。
    当我们注意到奖励的承诺不过是假象的时,魔咒就解开了。当我们把自己从错误的奖励承诺中解放出来时,我们常常发现,我们误以为的快乐源泉其实正是痛苦的根源开了。

    6. 情绪低落对自控力的作用

    7. 及时享乐

    8. 意志力的传染性

    9. “我不要”的局限性

flex布局

发表于 2017-02-14

注意点: flex布局下的,子元素的float,clear,vertical-align将会失效

Flex容器:display: flex 指定盒子为容器

Flex项目:flex容器下的元素

主轴main axis:默认水平方向

交叉轴cross axis:默认垂直方向

主轴起点main start/主轴起点main end

交叉轴起点cross start/交叉轴重点cross end

容器上的属性

  • flex-direction 主轴方向
    • row (默认)从左到右
    • row-reverse 从右到左
    • column 从上到下
    • Column 从下到上
  • flex-wrap 是否换行
    • Nowrap (默认) 不换行
    • wrap 换行/第一行在上
    • wrap-revers 换行/第一行在上
  • flex-flow 主轴和换行合并的简写
  • Justify-content 项目对齐方式
    • flex-start 左对齐
    • flex-end 右对齐
    • center 居中
    • Space-between 两端对齐,间隔均等
    • Space-around 项目两侧间隔相等
  • Align-items 项目交叉轴对齐方式
    • flex-start
    • flex-end
    • center
    • baseling 项目的第一行文字的基线
    • stretch
  • Align-content 轴的对齐方式(单轴不生效)
    • flex-start:与交叉轴的起点对齐。
    • flex-end:与交叉轴的终点对齐。
    • center:与交叉轴的中点对齐。
    • space-between:与交叉轴两端对齐,轴线之间的间隔平均分布。
    • space-around:每根轴线两侧的间隔都相等。所以,轴线之间的间隔比轴线与边框的间隔大一倍。
    • stretch(默认值):轴线占满整个交叉轴。

项目上的属性

  • 排列顺序
  • Flex-grow 项目放大比例
  • flex-shrink
  • ​

生命周期三种状态

发表于 2017-02-03

生命周期三种状态

安装

当创建组件的实例并将其插入DOM时,将调用这些方法:

  • constructor()
  • componentWillMount()
  • render()
  • componentDidMount()

更新

更新可以由props或state的更改引起。在重新渲染组件时调用这些方法:

  • componentWillReceiveProps()
  • shouldComponentUpdate()
  • componentWillUpdate()
  • render()
  • componentDidUpdate()

卸载

当从DOM中删除组件时,将调用此方法:

  • componentWillUnmount()

文章1:生命周期的hook的总结

  • 生命周期的执行时间
  • 可以执行的操作
  • 意义

文章2:生命周期的实际应用

  1. 一次渲染的生命周期,
  2. 改变state或者props的重新渲染的生命周期完整流程

未命名

发表于 2017-02-03

生命周期

整理生命周期的几个函数的触发时间,作用以及使用情景

  • 调用时间(触发时间)
  • 作用
  • 经常用来进行的操作
  • 执行完成后的结果

组件的生命周期

一个组件的生命周期主要分为三种状态,对于初学者,可以试着将组件的生命周期想象为一场舞台剧。

  • 安装/Mounting(登台)

    这个时期主要是组件的初始化,直到组件被插入到真实的DOM结构中去。(登场以及登场前的准备)

  • 更新/Updating(演出)

    当组件被插入到真实的DOM结构后,根据state和props的改变,组件将重新进行render。(随着剧情推动,舞台呈现的场景不断的变换)

  • 卸载/Unmounting(谢幕)

    组件从真实DOM中移除

    ​

Mounting

componentWillMount()

  • 触发时间:在组件

componentWillMount()在安装发生之前立即被调用。它在render()之前调用,因此在此方法中的设置状态不会触发重新呈现。避免在此方法中引入任何副作用或订阅。 这是在服务器渲染上调用的唯一的生命周期钩子。一般来说,我们建议使用constructor()。

这个方法在组件已经即将创建但是还没有创建的时候调用,在这里可以用setState修改state。但是react建议是在组件mouted以后调用setState函数,否则容易报警告。这点在介绍state的时候在详细分析。

componentDidMount()

Updating

componentWillReceiveProps()

shouldComponentUpdate()

componentWillUpdate()

componentDidUpdate()

Unmounting

componentWillUnmount()

git config 配置用户信息

发表于 2017-01-11

git config基本

git config是对git的一些配置,而配置项一般保存在配置文件中。

git 配置在实际使用中存在三个地方

  1. 系统
  2. 全局
  3. 本地

配置多个ssh

发表于 2017-01-10

刚到公司是没有再重新配置ssh,导致了自己的github和公司gitlab提交的混乱。

这种情况我们可以分情况配置ssh

  1. 分别生成gitlab和github的ssh-key
1
$ ssh-keygen -t rsa -C "youremail@yourcompany.com" -f ~/.ssh/gitlab-rsa

在~/.ssh/目录会生成gitlab-rsa私钥和gitlab-rsa.pub公钥。 我们将id-rsa.pub中的内容粘帖到公司gitlab服务器的SSH-key的配置中。

1
$ ssh-keygen -t rsa -C "youremail@your.com" -f ~/.ssh/github-rsa

在~/.ssh/目录会生成github-rsa私钥和github-rsa.pub公钥。 我们将github-rsa.pub中的内容粘帖到github服务器的SSH-key的配置中。

​

在创建ssh-key的时候会有提示

1
2
3
4
Enter passphrase (empty for no passphrase):
//输入密语,可以为空
Enter same passphrase again:
//再次输入确认
  1. 将密钥加入到ssh-agent

    ssh-agent是用于管理密钥,通过ssh-add命令将两个将密钥加入到ssh-agent中,SSH可以和ssh-agent通信获取密钥,这样就不需要手工输入密码了。

    1
    2
    $ ssh-add ~/.ssh/gitlab-rsa
    $ ssh-add ~/.ssh/github-rsa

    如果运行ssh-add命令,遇到“Could not open a connection to your authentication agent.”提示。

    需要ssh-agent启动bash,运行以下命令,然后再重新执行ssh-add命令

    1
    $ ssh-agent bash
  2. 创建并编辑config文件

    1
    2
    $ cd ~/.ssh/
    $ touch config

    在config中写入,并保存

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    # gitlab
    Host gitlab.com
    HostName gitlab.com
    PreferredAuthentications publickey
    IdentityFile ~/.ssh/gitlab-rsa
    # github
    Host github.com
    HostName github.com
    PreferredAuthentications publickey
    IdentityFile ~/.ssh/github-rsa
    # 配置文件参数
    # Host : Host可以看作是一个你要识别的模式,对识别的模式,进行配置对应的的主机名和ssh文件
    # HostName : 要登录主机的主机名
    # IdentityFile : 指明对应的identityFile路径
  3. 测试是否生效

    1
    $ ssh git@github.com

    出现以下提示即为成功

    1
    2
    3
    4
    5
    6
    The authenticity of host 'github.com (192.30.253.112)' can't be established.
    RSA key fingerprint is SHA256:xxxxxxxxxxxxxxxxxxxxx.
    Are you sure you want to continue connecting (yes/no)?
    //输入yes,按回车
    Warning: Permanently added 'github.com,192.30.253.112' (RSA) to the list of known hosts.
    Permission denied (publickey).
1
2
3
4
5
6
7
8
9
10
11
# flag-api
git remote remove origin
git remote add origin git@code.aliyun.com:546405040/flag-api.git
git push --set-upstream origin master #第一次可能需要
# xl
git remote remove origin
git remote add origin git@code.aliyun.com:546405040/xl.git
git push --set-upstream origin master #第一次可能需要

gitlab

Host gitlab.com
HostName gitlab.com
PreferredAuthentications publickey
IdentityFile ~/.ssh/id_rsa

github

Host github.com
HostName github.com
PreferredAuthentications publickey
IdentityFile ~/.ssh/github-rsa

zeno

Host 47.52.30.225
HostName 47.52.30.225
PreferredAuthentications publickey
IdentityFile ~/.ssh/zeno-rsa

#User git

阿里
Host code.aliyun.com
HostName code.aliyun.com
PreferredAuthentications publickey
IdentityFile ~/.ssh/gitali-rsa

origin git@47.52.30.225:xl.git

配置文件参数

Host : Host可以看作是一个你要识别的模式,对识别的模式,进行配置对应的的主机名和ssh文件

HostName : 要登录主机的主机名

User : 用户名

IdentityFile : 指明对应的identityFile路径

学习笔记——IEEE 802.3以太网络 Enthernet

发表于 2016-11-15

Enthernet Introduction介绍

历史

  • 1970开发
  • 1978年定义标准

特性

  • Connectionless 通讯不需要两个主机建立连接
  • Unreliable 不可靠(干扰,讯号冲撞,损毁,网络拥挤)
  • Ethernet’s MAC protocol: Carrier Sense Multiple Acess with Collision Detection(CSMA/CD)协调所有连接上的主机工作

Enthernet Topologies拓扑

  • BUS topology

    • 双向传输

    • 两端有终端器(防止信号反弹回来)

    • 有长度限制 (网段最长500公尺)

    • transceiver 可以传输可以接收

    • transceiver连接至网卡

    • 每个网段最多100哥收发器

    • 收发器电缆最长50公尺

    • Manchester Encoding

      • ####

Enthernet Frame Format 传输格式

Ethernet MAC Protocol — CSMA/CD 协议

802.3 Ethernet Standards 标准

未命名

发表于 2016-11-15
  • 首先定义学习的目标

高效学习的建议

  • Anki 帮助记忆

建议:

  • 快速获得反馈
    • 反反复复练习,每次都获得反馈可以很快的提升
  • 创造深的理解
    • 列出要学习的知识点:试图以讲给学生的方式讲出来
  • 高强度学习
    • 刻意练习
    • 广泛练习
  • 习惯的养成
    • 只有一个重要的坚持下去
  • 学习的动机
1234
Zeno Tian

Zeno Tian

38 日志
17 标签
GitHub
© 2017 Zeno Tian
由 Hexo 强力驱动
主题 - NexT.Mist