React极简教程: Hello,World!

简介: React简史A declarative, efficient, and flexible JavaScript library for building user interfaces. https://facebook.github.io/react/一个声明式的,高效的,和用于构建用户界面的灵活的JavaScript库。

React简史

A declarative, efficient, and flexible JavaScript library for building user interfaces. https://facebook.github.io/react/

一个声明式的,高效的,和用于构建用户界面的灵活的JavaScript库。

声明式编程

编程语言的主要类型

Common programming paradigms include imperative which allows side effects, functional which disallows side effects, declarative which does not state the order in which operations execute (常见的编程语言类型包括允许有副作用的命令式编程,不允许副作用的函数式编程和不描述操作执行顺序的声明式编程)

A programming paradigm is a fundamental style of computer programming. There are four main paradigms: imperative, declarative, functional (which is considered a subset of the declarative paradigm) and object-oriented.
Declarative programming : is a programming paradigm that expresses the logic of a computation(What do) without describing its control flow(How do). Some well-known examples of declarative domain specific languages (DSLs) include CSS, regular expressions, and a subset of SQL (SELECT queries, for example) Many markup languages such as HTML, MXML, XAML, XSLT… are often declarative. The declarative programming try to blur the distinction between a program as a set of instructions and a program as an assertion about the desired answer.
Imperative programming : is a programming paradigm that describes computation in terms of statements that change a program state. The declarative programs can be dually viewed as programming commands or mathematical assertions.
Functional programming : is a programming paradigm that treats computation as the evaluation of mathematical functions and avoids state and mutable data. It emphasizes the application of functions, in contrast to the imperative programming style, which emphasizes changes in state. In a pure functional language, such as Haskell, all functions are without side effects, and state changes are only represented as functions that transform the state.
( 出处:维基百科)

编程语言主要有四种类型

声明式编程:专注于”做什么”而不是”如何去做”。在更高层面写代码,更关心的是目标,而不是底层算法实现的过程。 ex: css, 正则表达式,sql 语句,html, xml…

命令式编程(过程式编程) : 专注于”如何去做”,这样不管”做什么”,都会按照你的命令去做。解决某一问题的具体算法实现。

函数式编程:把运算过程尽量写成一系列嵌套的函数调用。 函数式编程强调没有”副作用”,意味着函数要保持独立,所有功能就是返回一个新的值,没有其他行为,尤其是不得修改外部变量的值。 所谓”副作用”(side effect),指的是函数内部与外部互动(最典型的情况,就是修改全局变量的值),产生运算以外的其他结果。

(英语:Declarative programming)是一种编程范型,与命令式编程相对立。声明式语言包括数据库查询语言(SQLXQuery),正则表达式,逻辑编程,函数式编程和组态管理系统。

声明式编程语言:prolog

特点:你只需向它提供一些事实(fact)和推论(inference),让它为你判断。它像一个手艺高超的糕点师,只要你说出你喜欢的蛋糕的特征,糕点师会帮你挑选原料并按照你提供的规则为你烤出糕点。

声明式编程语言:SQL

也许你还不能明白,但有一个地方,你也许已经用到了声明式编程,那就是SQL。
  你可以把 SQL 当做一个处理数据的声明式查询语言。完全用SQL写一个应用程序?这不可能。但如果是处理相互关联的数据集,它就显的无比强大了。
  像下面这样的查询语句:

SELECT * from dogs
INNER JOIN owners
WHERE dogs.owner_id = owners.id

如果我们用命令式编程方式实现这段逻辑:

//dogs = [{name: 'Fido', owner_id: 1}, {...}, ... ]
//owners = [{id: 1, name: 'Bob'}, {...}, ...] var dogsWithOwners = []
var dog, owner
for(var di=0; di < dogs.length; di++) {
  dog = dogs[di]
  for(var oi=0; oi < owners.length; oi++) {
    owner = owners[oi]
    if (owner && dog.owner_id == owner.id) {
      dogsWithOwners.push ({
        dog: dog,
        owner: owner
      })
    }
  }}
}

我可没说SQL是一种很容易懂的语言,也没说一眼就能把它们看明白,但基本上还是很整洁的。
  SQL代码不仅很短,不不仅容易读懂,它还有更大的优势。因为我们归纳抽离了how,我们就可以专注于what,让数据库来帮我们优化how。

声明式编程通过函数、推论规则或项重写(term-rewriting)规则,来描述变量之间的关系。它的语言运行器(编译器解释器)采用了一个固定的算法,以从这些关系产生结果。

声明式编程语言通常用作解决人工智能和约束满足问题。

命令式编程

java、c、c++、rubby等都属此类。其就像一本烹饪菜谱,你需要精确的告诉计算机如何去完成一项工作:列出原料购物清单,并描述烤蛋糕的详细步骤。

命令式编程:命令“机器”如何去做事情(how),这样不管你想要的是什么(what),它都会按照你的命令实现。
声明式编程:告诉“机器”你想要的是什么(what),让机器想出如何去做(how)。

声明式编程和命令式编程的代码例子
  
举个简单的例子,假设我们想让一个数组里的数值翻倍。
  我们用命令式编程风格实现,像下面这样:

var numbers = [1,2,3,4,5]
var doubled = []
for(var i = 0; i < numbers.length; i++) {
  var newNumber = numbers[i] * 2
  doubled.push (newNumber)
}
console.log (doubled) //=> [2,4,6,8,10]

我们直接遍历整个数组,取出每个元素,乘以二,然后把翻倍后的值放入新数组,每次都要操作这个双倍数组,直到计算完所有元素。
  而使用声明式编程方法,我们可以用 Array.map 函数,像下面这样:

var numbers = [1,2,3,4,5]
var doubled = numbers.map (function (n) {
  return n * 2
})
console.log (doubled) //=> [2,4,6,8,10]

map利用当前的数组创建了一个新数组,新数组里的每个元素都是经过了传入map的函数(这里是function (n) { return n*2 })的处理。
  map函数所做的事情是将直接遍历整个数组的过程归纳抽离出来,让我们专注于描述我们想要的是什么(what)。注意,我们传入map的是一个纯函数;它不具有任何副作用(不会改变外部状态),它只是接收一个数字,返回乘以二后的值。

在一些具有函数式编程特征的语言里,对于 list 数据类型的操作,还有一些其他常用的声明式的函数方法。例如,求一个list里所有值的和,命令式编程会这样做:

var numbers = [1,2,3,4,5]
var total = 0 for(var i = 0; i < numbers.length; i++) {
  total += numbers[i]
}
console.log (total) //=> 15

而在声明式编程方式里,我们使用reduce函数:

var numbers = [1,2,3,4,5]
var total = numbers.reduce (function (sum, n) {
  return sum + n
});
console.log (total) //=> 15

reduce函数利用传入的函数把一个list运算成一个值。它以这个函数为参数,数组里的每个元素都要经过它的处理。每一次调用,第一个参数(这里是sum)都是这个函数处理前一个值时返回的结果,而第二个参数(n)就是当前元素。这样下来,每此处理的新元素都会合计到sum中,最终我们得到的是整个数组的和。

同样,reduce函数归纳抽离了我们如何遍历数组和状态管理部分的实现,提供给我们一个通用的方式来把一个list合并成一个值。我们需要做的只是指明我们想要的是什么.

函数式编程

函数式编程的三大特性:

immutable data 不可变数据:像Clojure一样,默认上变量是不可变的,如果你要改变变量,你需要把变量copy出去修改。这样一来,可以让你的程序少很多Bug。因为,程序中的状态不好维护,在并发的时候更不好维护。(你可以试想一下如果你的程序有个复杂的状态,当以后别人改你代码的时候,是很容易出bug的,在并行中这样的问题就更多了)

first class functions:这个技术可以让你的函数就像变量一样来使用。也就是说,你的函数可以像变量一样被创建,修改,并当成变量一样传递,返回或是在函数中嵌套函数。这个有点像Javascript的Prototype(参看Javascript的面向对象编程

尾递归优化:我们知道递归的害处,那就是如果递归很深的话,stack受不了,并会导致性能大幅度下降。所以,我们使用尾递归优化技术——每次递归时都会重用stack,这样一来能够提升性能,当然,这需要语言或编译器的支持。Python就不支持。

函数式编程的几个技术

map & reduce :这个技术不用多说了,函数式编程最常见的技术就是对一个集合做Map和Reduce操作。这比起过程式的语言来说,在代码上要更容易阅读。(传统过程式的语言需要使用for/while循环,然后在各种变量中把数据倒过来倒过去的)这个很像C++中的STL中的foreach,find_if,count_if之流的函数的玩法。

pipeline:这个技术的意思是,把函数实例成一个一个的action,然后,把一组action放到一个数组或是列表中,然后把数据传给这个action list,数据就像一个pipeline一样顺序地被各个函数所操作,最终得到我们想要的结果。
recursing 递归 :递归最大的好处就简化代码,他可以把一个复杂的问题用很简单的代码描述出来。注意:递归的精髓是描述问题,而这正是函数式编程的精髓。

currying:把一个函数的多个参数分解成多个函数, 然后把函数多层封装起来,每层函数都返回一个函数去接收下一个参数这样,可以简化函数的多个参数。在C++中,这个很像STL中的bind_1st或是bind2nd。

higher order function 高阶函数:所谓高阶函数就是函数当参数,把传入的函数做一个封装,然后返回这个封装函数。现象上就是函数传进传出,就像面向对象对象满天飞一样。

还有函数式的一些好处:

parallelization 并行:所谓并行的意思就是在并行环境下,各个线程之间不需要同步或互斥。

lazy evaluation 惰性求值:这个需要编译器的支持。表达式不在它被绑定到变量之后就立即求值,而是在该值被取用的时候求值,也就是说,语句如
x:=expression; (把一个表达式的结果赋值给一个变量)明显的调用这个表达式被计算并把结果放置到 x 中,但是先不管实际在 x 中的是什么,直到通过后面的表达式中到 x 的引用而有了对它的值的需求的时候,而后面表达式自身的求值也可以被延迟,最终为了生成让外界看到的某个符号而计算这个快速增长的依赖树。

determinism 确定性:所谓确定性的意思就是像数学那样 f(x) = y ,这个函数无论在什么场景下,都会得到同样的结果,这个我们称之为函数的确定性。而不是像程序中的很多函数那样,同一个参数,却会在不同的场景下计算出不同的结果。所谓不同的场景的意思就是我们的函数会根据一些运行中的状态信息的不同而发生变化。

React安装

就像写普通的html/css/js代码一样,引入如下js即可:

<!-- React -->
<script src="https://cdn.bootcss.com/react/15.4.2/react.min.js"></script>
<script src="https://cdn.bootcss.com/react/15.4.2/react-dom.min.js"></script>
<script src="https://cdn.bootcss.com/babel-standalone/6.22.1/babel.min.js"></script>


Hello,World

直接上代码helloWorld.html


<!DOCTYPE html>
<html>
<head>
    <meta charset='utf-8'>

    <!-- jQuery 2.2.3 -->
    <script src="../public/plugins/jQuery/jquery-2.2.3.min.js"></script>

    <!-- Bootstrap 3.3.6 -->
    <script src="../public/bootstrap/js/bootstrap.min.js"></script>
    <!-- Bootstrap 3.3.6 -->
    <link rel="stylesheet" href="../public/bootstrap/css/bootstrap.min.css">

    <!-- BootstrapDialog -->
    <link href="../public/components/bootstrap3-dialog/bootstrap-dialog.min.css" rel="stylesheet" type="text/css"/>
    <script src="../public/components/bootstrap3-dialog/bootstrap-dialog.min.js"></script>


    <!-- React -->
    <script src="https://cdn.bootcss.com/react/15.4.2/react.min.js"></script>
    <script src="https://cdn.bootcss.com/react/15.4.2/react-dom.min.js"></script>
    <script src="https://cdn.bootcss.com/babel-standalone/6.22.1/babel.min.js"></script>
</head>

<body>

<div id="helloWorld"></div>

<script type="text/javascript">
    function sayHelloWorld() {
        BootstrapDialog.show({
            title: 'React Demo',
            message: 'Hello,World! 现在时间是:' + new Date(),
            type: BootstrapDialog.TYPE_DEFAULT,
            closable: false,
            cssClass: 'dialog_mar',
            buttons: [{
                label: '确认',
                cssClass: 'con_btn',
                action: function (dialogRef) {
                    dialogRef.close();
                    location.reload();
                }
            }, {
                label: '取消',
                action: function (dialogRef) {
                    dialogRef.close();
                }
            }]
        });

    }
</script>

<script type="text/babel">
    var HelloWorld = React.createClass({
        getInitialState: function () {
            return {};
        },
        sayHello: function () {
//            alert('Hello,World!');
            sayHelloWorld();


        },
        render: function () {

            var helloWorldStyle = {
                textAlign: 'center',
                padding: '4em'
            };

            var btnStyle = {
                padding: '4em',
                fontSize: '4em'
            };

            return (
                    <div style={helloWorldStyle}>
                        <button onClick={this.sayHello} style={btnStyle}>说: Hello,World!</button>
                    </div>
            );
        }
    });

    ReactDOM.render(<HelloWorld/>, document.getElementById('helloWorld'));

</script>


</body>
</html>



运行效果:

https://jason-chen-2017.github.io/Jason-Chen-2017/reactDemo/helloWorld.html

相关文章
|
3月前
|
前端开发 JavaScript 容器
第二章 简单实现Hello React案例
第二章 简单实现Hello React案例
|
4月前
|
前端开发 JavaScript API
中国农村大学生学习了这个【React教程】迎娶导师女儿,出任CEO走上人生巅峰
中国农村大学生学习了这个【React教程】迎娶导师女儿,出任CEO走上人生巅峰
34 0
|
10月前
|
JavaScript 前端开发 应用服务中间件
React全家桶建站教程-发布 #10
React全家桶建站教程-发布 #10
94 0
|
10月前
|
缓存 移动开发 JavaScript
React全家桶建站教程-Redux&Saga #7
React全家桶建站教程-Redux&Saga #7
63 0
|
10月前
|
前端开发
React全家桶建站教程-Router #6
React全家桶建站教程-Router #6
52 0
|
10月前
|
JavaScript 前端开发
React全家桶建站教程-Webpack #5
React全家桶建站教程-Webpack #5
73 0
|
10月前
|
前端开发
React全家桶建站教程-React&Ant #4
React全家桶建站教程-React&Ant #4
62 0
|
10月前
|
弹性计算 前端开发 应用服务中间件
React全家桶建站教程-Nginx #3
React全家桶建站教程-Nginx #3
92 0
|
10月前
|
开发框架 JavaScript 前端开发
React全家桶建站教程-Express #2
React全家桶建站教程-Express #2
90 0
|
10月前
|
缓存 JavaScript 前端开发