React極簡教程:Hello,World!

程式設計師詩人發表於2017-03-04

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


相關文章