React.js入門筆記(再續):評論框的實現

来源:http://www.cnblogs.com/djtao/archive/2016/12/18/6195148.html
-Advertisement-
Play Games

本案例來自React.js中文官網對應內容。 一. 運行環境 二. 組件架構 App下有兩個子組件 (評論列表)和 (評論區),其中 下又有一個子組件 (評論) Comment包括一個h2的評論人名稱,一個span的評論內容,獲取數據之後,Comment組件以數組的形式傳入CommentList。 ...


本案例來自React.js中文官網對應內容。

一. 運行環境

<link rel="stylesheet" type="text/css" href="css/css.css"/>
  <!-- 核心 -->
  <script src="js/react.js"></script>
  <!-- 載入dom方法 -->
  <script src="js/react-dom.js"></script>
  <!-- 將 JSX 語法轉為 JavaScript 語法 -->
  <script src="js/browser.min.js"></script>
  <!-- jquery -->
  <script type="text/javascript" src="js/jquery-1.11.3.js"></script>
  <!--markdown渲染引擎-->
   <script type="text/javascript" src="js/remarkable.min.js"></script>
  <!-- 自身的javascript代碼 -->
  <script type="text/javascript" src="js/js.js"></script>
</head>

二. 組件架構

App下有兩個子組件CommentList(評論列表)和CommentForm(評論區),其中CommentList下又有一個子組件Comment(評論)

- App
  - CommentList
    - Comment
  - CommentForm

Comment包括一個h2的評論人名稱,一個span的評論內容,獲取數據之後,Comment組件以數組的形式傳入CommentList。

三. 流動數據

接下來就是把這5個組件寫出來。

// 最底層的組件Comment,隸屬於CommentList
        var Comment=React.createClass({
            render:function(){
                return (

                );
            }
        });

        // 中層對象,包括CommentList和CommentForm
        var CommentList=React.createClass({
            render:function(){
                return (

                );
            }
        });

        var CommentForm=React.createClass({
            render:function(){
                return (

                );
            }
        });

        // 最高層對象App,包括兩個中層組件
        var App=React.createClass({
            render:function(){
                return (

                );
            }
        });

        // 渲染模塊
        ReactDOM.render(
            <App/>,
            document.getElementById('example')
        );

數據通過props傳入App,可以在html文件根目錄下創建一個“json.json”文件:放入以下內容:

[
  {"id": 1, "author": "小明", "text": "小明摸摸大"},
  {"id": 2, "author": "小紅", "text": "小紅萌萌噠"}
]

所以我只要給App傳遞一個url即可。然後在文檔插入之後執行jQuery的getJSON方法:最後在存入到App的state中。每次更新state,對會造成變化。
既然state可以實時更新,那麼不如設置一個定時器,每隔2s執行一次數據刷新。刷新間隔由App的props.timer傳入。
目前的組件變成了這樣

// 最底層的組件Comment,隸屬於CommentList
        var Comment=React.createClass({
            render:function(){
                return (
                    <li>
                        <h2>{this.props.author}</h2>
                        <span>{this.props.text}</span>
                    </li>
                );
            }
        });
        //
        // 中層對象,包括CommentList和CommentForm
        var CommentForm=React.createClass({
            render:function(){
                //console.log(this.props)
                return (
                    <div></div>
                );
            }
        });

        var CommentList=React.createClass({
            render:function(){
                var arr=[];

                this.props.data.map(function(item){
                    //console.log(item.author)
                    var content=
                    (
                        <Comment
                        author={item.author}
                        text={item.text}
                        key={item.id}/>

                    );
                    arr.push(content);
                });
                console.log(arr)
                return (
                    <ul>{arr}</ul>
                );
            }
        });

        // 最高層對象App,包括兩個中層組件
        var App=React.createClass({
            getInitialState:function(){
                return {
                    data:[]
                };
            },
            loadServer:function(){
                var _this=this;
                $.getJSON(this.props.url,function(data){
                    _this.setState({
                        data:data
                    })
                });
            },
            componentDidMount:function(){
                console.log(this.props.timer)
                var _this=this;
                setInterval(function(){
                    _this.loadServer();
                },_this.props.timer)
            },
            render:function(){
                //console.log(this.state)
                return (
                    <div>
                        <h1>當前評論</h1>
                        <CommentList data={this.state.data}/>
                        <CommentForm/>
                    </div>
                );
            }
        });

        // 渲染模塊
        ReactDOM.render(
            <App url="json.json" timer={2000}/>,
            document.getElementById('example')
        );

數據就流動起來了。如果你修改了伺服器,定時器會在2s後重新更新所得到的數據。

四. markdown語法

這部分主要是調用remarkable插件,渲染你看到的數據。而渲染自然是在底層的Comment組件上完成。
所以我把Comment組件改成這樣:

// 最底層的組件Comment,隸屬於CommentList
        var Comment=React.createClass({
            render:function(){
                var md=new Remarkable();//調用插件
                var commentContent=md.render(this.props.text.toString());//渲染獲得的字元串!
                return (
                    <li>
                        <h2>{this.props.author}</h2>
                        <span>{commentContent}</span>
                    </li>
                );
            }
        });

結果就搞笑了。純文本在渲染引擎渲染之後變成了帶P標簽的內容。

解決方案:再此需要一個官方定義的props——

dangerouslySetInnerHTML

實現方法如下:

// 最底層的組件Comment,隸屬於CommentList
        var Comment=React.createClass({
            getContent:function(){
                var md=new Remarkable();//調用插件
                var commentContent=md.render(this.props.text.toString());//渲染獲得的字元串!
                return ({
                    __html:commentContent
                });//註意是兩個下劃線!
            },
            render:function(){

                return (
                    <li>
                        <h2>{this.props.author}</h2>
                        <span dangerouslySetInnerHTML={this.getContent()}/>
                    </li>
                );
            }
        });

五.添加新評論

到目前為止一切看起來還算簡單。現在需要加新的評論。
CommentForm添加的是一個新的表單。裡面包含了評論的大名,評論內容,還有提交按鈕。

var CommentForm=React.createClass({
            render:function(){
                //console.log(this.props)
                return (
                    <form>
                        <input type="text" placeholder="你的大名"/><br/>
                        <textarea type="text" placeholder="評論內容"></textarea><br/>
                        <button type="submit">提交</button>
                    </form>
                );
            }
        });

在實現這個組件的時候,需要考慮它的狀態。文本框的內容顯然是狀態。所以用一個state來保存它的狀態。輸入一次就保存一次並返回到文本框的value之中。

var CommentForm=React.createClass({
            getInitialState:function(){
                return ({
                    author:"",
                    text:""
                });
            },//初始化狀態
            authorChange:function(e){
                this.setState({
                    author:e.target.value
                });
            },
            textChange:function(e){
                this.setState({
                    text:e.target.value
                })
            },
            render:function(){
                //console.log(this.props)
                return (
                    <form>
                        <input
                          type="text"
                          placeholder="你的大名"
                          value={this.state.author}
                          onChange={this.authorChange}/><br/>
                        <textarea type="text"
                          placeholder="評論內容"
                          value={this.state.text}
                          onChange={this.textChange}></textarea><br/>
                        <button type="submit">提交</button>
                    </form>
                );
            }
        });

組件已經變得很長很長,但是基本上也不需要想什麼。

提交表單

提交表單做三件事,onSubmit在form標簽上。

  • 阻止跳轉(e.preventDefault)
  • 清空form的內容
  • 返回到伺服器並刷新列表
<form onSubmit={this.submit}>...

submit函數:

...
submit:function(e){
                e.preventDefault();
                // 接下來格式化獲取內容!註意去掉評論頭尾的空格。
                var authorStr=this.state.author.trim();
                var textStr=this.state.text.trim();
                if(!textStr||!authorStr){
                    alert('你有地方忘了填!');
                    return false;
                }//簡單的表單校驗

                this.setState({
                    author:'',
                    text:''
                });//清空表單內容

            },
            ...

這就實現了前兩步,但是提交到伺服器並刷新好像用前端的方法無法實現。
我們之前做了每隔兩秒鐘刷新一次,所以每次都要拿數據,在這個案例中不現實。
所以為了不涉及太多無關知識,把定時器拿掉。

先不理它,還是做回調函數,把狀態反饋到App:並刷新App的state:
返回的callback應該包括評論人名字,評論內容,說白了就是把這個對象扔進去作為參數。
那麼id值呢?就用一個Data對象給他生成吧!(Date.now())

// 最底層的組件Comment,隸屬於CommentList
        var Comment=React.createClass({
            getContent:function(){
                var md=new Remarkable();//調用插件
                var commentContent=md.render(this.props.text.toString());//渲染獲得的字元串!
                return ({
                    __html:commentContent
                });//註意是兩個下劃線!
            },
            render:function(){
                return (
                    <li>
                        <h2>{this.props.author}</h2>
                        <span dangerouslySetInnerHTML={this.getContent()}/>
                    </li>
                );
            }
        });
        //
        // 中層對象,包括CommentList和CommentForm
        var CommentForm=React.createClass({
            getInitialState:function(){
                return ({
                    author:"",
                    text:""
                });
            },//初始化狀態
            authorChange:function(e){
                this.setState({
                    author:e.target.value,
                });

            },
            textChange:function(e){
                this.setState({
                    text:e.target.value,
                })

            },
            submit:function(e){
                e.preventDefault();
                // 接下來格式化獲取內容!註意去掉評論頭尾的空格。
                var authorStr=this.state.author.trim();

                var textStr=this.state.text.trim();
                if(!textStr||!authorStr){
                    alert('你有地方忘了填!');
                    return false;
                }//簡單的表單校驗
                this.props.callback({
                    "author":authorStr,
                    "text":textStr
                });// 提交到伺服器!
                this.setState({
                    author:'',
                    text:''
                });//清空表單內容

            },
            render:function(){
                //console.log(this.props)
                return (
                    <form onSubmit={this.submit}>
                        <input
                          type="text"
                          placeholder="你的大名"
                          value={this.state.author}
                          onChange={this.authorChange}/><br/>
                        <textarea type="text"
                          placeholder="評論內容"
                          value={this.state.text}
                          onChange={this.textChange}></textarea><br/>
                        <button type="submit">提交</button>
                    </form>
                );
            }
        });

        var CommentList=React.createClass({
            render:function(){
                var arr=[];

                this.props.data.map(function(item){

                    var content=
                    (
                        <Comment
                        author={item.author}
                        text={item.text}
                        key={item.id}/>

                    );
                    arr.push(content);
                });

                return (
                    <ul>{arr}</ul>
                );
            }
        });

        // 最高層對象App,包括兩個中層組件
        var App=React.createClass({
            getInitialState:function(){
                return {
                    data:[]
                };
            },
            loadServer:function(){
                var _this=this;
                $.getJSON(this.props.url,function(data){
                    _this.setState({
                        data:data
                    })
                });
            },
            componentDidMount:function(){
                this.loadServer();
                // 伺服器環境設置
                // var _this=this;
                // setInterval(function(){
                //     _this.loadServer();
                // },_this.props.timer)
            },
            refreshComment:function(comment) {
                console.log(comment)//假設已經提交了
                comment.id=Date.now()//給他一個id值!
                var newComments=this.state.data.concat([comment]);//把它橋接起來!
                console.log(newComments)
                // 接下來再獲取一次。

                // 伺服器環境下可以這樣做
                // $.ajax({
                //   url: this.props.url,
                //   dataType: 'json',
                //   type: 'POST',
                //   data: comment,
                //   success: function(data) {
                //     //console.log(data)
                //     this.setState({data: data});
                //   }.bind(this),
                //   error: function(xhr, status, err) {
                //     console.error(this.props.url, status, err.toString());
                //   }.bind(this)
                // });

                //非伺服器環境設置一個新狀態就可以了。
                this.setState({
                    data:newComments
                })
           },
            render:function(){
                //console.log(this.state)
                return (
                    <div>
                        <h1>當前評論</h1>
                        <CommentList data={this.state.data}/>
                        <CommentForm callback={this.refreshComment}/>
                    </div>
                );
            }
        });

        // 渲染模塊
        ReactDOM.render(
            <App url="json.json" timer={2000}/>,
            document.getElementById('example')
        );

效果支持簡單的markdown語法:




您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 通過簡單的示例代碼,短暫地回顧了jQuery的Deferred使用後,我們一起來看看jQuery是怎麼實現Deferred,當然解讀jQuery源代碼的版本是大於1.8的。 ...
  • 本文記錄了我在項目中用過的一些JavaScript小功能,有需要的可以參考下;如有不足之處,還望眾位同行指正。 ...
  • 一、什麼是Vue? Vue.js(讀音 /vjuː/, 類似於 view) 是一套構建用戶界面的 漸進式框架。與其他重量級框架不同的是,Vue 採用自底向上增量開發的設計。Vue 的核心庫只關註視圖層,並且非常容易學習,非常容易與其它庫或已有項目整合。另一方面,Vue 完全有能力驅動採用單文件組件和 ...
  • 項目中ajax交互成功前總會需要給用戶提醒,比如請稍候、正在載入中等等,那個等待的動圖以前項目中用的是gif,在移動端畫質很渣,有毛邊,於是在新項目中用css3展示載入中的動畫效果。 js放在項目公用里,樣式放到公用樣式里,調用的時候tipLoading(type,top,left),在ajax交互 ...
  • 下載 "mysql 5.7.msi" 安裝 雙擊mysql.msi,按照提示安裝。 安裝之後需要註意的問題( 重點 ) 設置mysql環境環境變數(讓mysql在cmd中的任何路徑下就可以被調用) 1. 滑鼠右擊電腦,點擊屬性 2. 選擇高級系統變數設置,點擊環境變數 3. 在系統變數裡面選擇PA ...
  • 1、先引入jquery.js 2、接著引入luhmCheck.js //銀行卡號Luhm校驗 3、看下麵的案例: 下麵是js 測試卡號: 1、6222600810010710887 2、6225881414207430 ...
  • 引言 提到前端往往很多人的映像就是入門簡單,HTML、CSS加一起一個星期基本上就能大概上手,JS難一點但也能很快寫一些簡單的小效果,在網上隨便一搜索各種特效代碼隨意用,一個新手前端也能在很短的時間里寫出炫酷的頁面效果,然而入門簡單並不意味著前端這碗飯很好吃,做慣了切圖、佈局、扣特效的前端新同學在向 ...
  • 直接插入排序演算法(Straight Insertion Sort),是排序演算法中簡單的一種演算法,基本思想如下: 將一個記錄插入到已排序好的有序表中,從而得到一個新,記錄數增1的有序表。即:先將序列的第1個記錄看成是一個有序的子序列,然後從第2個記錄逐個進行插入,直至整個序列有序為止。 要點:設立哨兵 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...