国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

學(xué)習(xí)React系列1-React-tutorial全解析

SnaiLiu / 997人閱讀

摘要:例子全解析近些時(shí)間一直在關(guān)注,關(guān)于如何學(xué)習(xí)可以參照鏈接的文章自行制定計(jì)劃。千里之行,始于足下。此外,輸出的內(nèi)容要解析為,而在默認(rèn)情況下,基于預(yù)防攻擊的考慮,對(duì)輸出的內(nèi)容是不解析為的。

React-tutorial例子全解析

Talk is cheap,Show me the code

近些時(shí)間一直在關(guān)注React,關(guān)于如何學(xué)習(xí)React可以參照鏈接的文章自行制定計(jì)劃。千里之行,始于足下。本文是React官方的教程上的一個(gè)例子,通過(guò)詳細(xì)地學(xué)習(xí),從中收獲不少,特此做了筆記,與大家共享交流進(jìn)步。

起步

下載例子,然后進(jìn)行解壓

由于采用的node環(huán)境,因此下載解壓之后,只需在所在目錄運(yùn)行

npm install
node server.js

采用默認(rèn)端口設(shè)置,只需打開瀏覽器,訪問(wèn)http://localhost:3000/

目錄結(jié)構(gòu)說(shuō)明

react-tutorial

--node_modules
    --body-parser:express中間件,用于接收和解析json數(shù)據(jù)
    --express:express框架
--public
    --css
        --base.css:基本樣式文件
    --scripts
        -- example.js:React應(yīng)用js文件
    index.html:基本的HTML結(jié)構(gòu)
--.editorconfig:用于在不同的編輯器中統(tǒng)一編輯風(fēng)格(文件編碼)的配置文件
--.gitignore:git相關(guān)配置文件
--app.json:web app的相關(guān)信息
--comments.json:上傳的評(píng)論數(shù)據(jù)
--LICENSE:項(xiàng)目代碼使用協(xié)議
--package.json:項(xiàng)目所依賴的包,npm install的安裝包的配置文件
--README.md:項(xiàng)目說(shuō)明書,里面有使用說(shuō)明
--requirements.txt:不清楚
--server.js:服務(wù)器端的js代碼
App功能

此項(xiàng)目構(gòu)建了一個(gè)簡(jiǎn)單的應(yīng)用,如圖所示

服務(wù)器端

服務(wù)器端的功能還是相對(duì)簡(jiǎn)單的,通過(guò)代碼注釋的形式來(lái)分析

導(dǎo)入了依賴的模塊

var fs = require("fs");  //讀寫文件
var path = require("path"); //路徑
var express = require("express"); //express框架
var bodyParser = require("body-parser"); //中間件

生成app,并且進(jìn)行配置

//獲取comments.json文件的路徑
var COMMENTS_FILE = path.join(__dirname, "comments.json");

//設(shè)置端口
app.set("port", (process.env.PORT || 3000));

//設(shè)置靜態(tài)文件的文件目錄路徑
app.use("/", express.static(path.join(__dirname, "public")));
//啟用bodyParser中間件接收請(qǐng)求,并且接收并解析json數(shù)據(jù)
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: true}));

設(shè)置響應(yīng)頭部信息

app.use(function(req, res, next) {
    //允許跨域 CORS
    res.setHeader("Access-Control-Allow-Origin", "*");
    //緩存設(shè)置
    res.setHeader("Cache-Control", "no-cache");
    next();
});

設(shè)置get請(qǐng)求url對(duì)應(yīng)的處理函數(shù)(獲取評(píng)論json數(shù)據(jù))

app.get("/api/comments", function(req, res) {
    //讀取comments.json文件,并且解析為json數(shù)據(jù)
    fs.readFile(COMMENTS_FILE, function(err, data) {
        if (err) {
          console.error(err);
          process.exit(1);
        }
        //讀取成功后,返回
        res.json(JSON.parse(data));
    });
});

設(shè)置post請(qǐng)求url對(duì)應(yīng)的處理函數(shù)(提交評(píng)論數(shù)據(jù))

app.post("/api/comments", function(req, res) {
    //先讀取comments.json文件
    fs.readFile(COMMENTS_FILE, function(err, data) {
        if (err) {
          console.error(err);
          process.exit(1);
        }
        //將文件內(nèi)容解析為json數(shù)據(jù)
        var comments = JSON.parse(data);
        //獲取新評(píng)論
        var newComment = {
          id: Date.now(),
          author: req.body.author,
          text: req.body.text,
        };
        //添加json數(shù)組中
        comments.push(newComment);
        //將json數(shù)據(jù)寫回到comments.json文件中,并且返回全部的評(píng)論數(shù)據(jù)
         fs.writeFile(COMMENTS_FILE, JSON.stringify(comments, null, 4), function(err) {
              if (err) {
                console.error(err);
                process.exit(1);
              }
              res.json(comments);
        });
    });
});

啟動(dòng),監(jiān)聽端口

app.listen(app.get("port"), function() {
  console.log("Server started: http://localhost:" + app.get("port") + "/");
});

web端

web端核心在于example.js文件,結(jié)合官網(wǎng)的資料,我們對(duì)這個(gè)應(yīng)用進(jìn)行分析,學(xué)習(xí)如何構(gòu)建一個(gè)簡(jiǎn)單的react應(yīng)用。

組件結(jié)構(gòu)

React踐行了Web Components的理念,依照組件化的開發(fā)方式,我們來(lái)分析這個(gè)應(yīng)用的組件結(jié)構(gòu)(如圖所示):

即是:

-- CommentBox
    -- CommentList
        -- Comment
    -- CommentForm

組件之間的關(guān)系圖為:

組件Comment

如上述的結(jié)構(gòu)圖,我們從最底層開始編寫組件Comment,這個(gè)組件需要做兩件事情

接收上層組件CommentList傳遞的數(shù)據(jù),動(dòng)態(tài)渲染虛擬DOM節(jié)點(diǎn),則從props中讀取數(shù)據(jù)

//評(píng)論人
{this.props.author}
//評(píng)論的內(nèi)容
{this.props.children}

由于評(píng)論是支持MarkDown語(yǔ)法的,因此需要使用第三放庫(kù)marked對(duì)用戶輸入的內(nèi)容進(jìn)行處理。

var rawMarkup = marked(this.props.children.toString(), {sanitize: true});

此外,輸出的內(nèi)容要解析為HTML,而在默認(rèn)情況下,基于預(yù)防XSS攻擊的考慮,React對(duì)輸出的內(nèi)容是不解析為HTML的。此時(shí),需要利用到特殊的屬性dangerouslySetInnerHTML,要將內(nèi)容放到一個(gè)對(duì)象的_html屬性中,然后將這個(gè)對(duì)象賦值給dangerouslySetInnerHTML屬性

var html = {_html:"輸出的html內(nèi)容"};

var Comment = React.createClass({
    rawMarkup : function() {
        var rawMarkup =  marked(this.props.children.toString(),{sanitize:true});
        return {_html : rawMarkup}; //React的規(guī)則,會(huì)讀取這個(gè)對(duì)象的_html內(nèi)容,
    },
    render : function() {
        return (
            

{this.props.author}

); } });
組件CommentList

組件CommentList需要做的就是接收上一層組件CommentBox傳遞過(guò)來(lái)的數(shù)據(jù),然后根據(jù)數(shù)據(jù)生成多個(gè)子組件Comment

var CommentList = React.createClass({
    render : function() {
        var commentNodes = this.props.data.map(function(comment){
            return (
                
                    {comment.text}
                
            );
        });
        return (
            
{commentNodes}
); } })

在生成子組件Comment時(shí),將每個(gè)子組件的key屬性設(shè)置為comment.id,這是因?yàn)?b>key是一個(gè)可選的唯一標(biāo)識(shí)符,通過(guò)它可以給組件設(shè)置一個(gè)獨(dú)一無(wú)二的鍵,并確保它在一個(gè)渲染周期中保持一致,使得React能夠更加智能地決定應(yīng)該重用一個(gè)組件,還是銷毀并重新創(chuàng)建一個(gè)組件,進(jìn)而提升渲染性能。

組件CommentForm

組件CommentForm需要做的就是兩件事情

管理自身的狀態(tài)this.state(即表單中輸入的評(píng)論人和評(píng)論內(nèi)容)

當(dāng)表單輸入發(fā)生變化時(shí)

當(dāng)表單提交時(shí)

當(dāng)submit事件觸發(fā)時(shí),調(diào)用上一層組件CommentBox的事件處理函數(shù),改變組件CommentBox的狀態(tài)。

var CommentForm = React.createClass({
    getInitialState : function() {
        //設(shè)置初始狀態(tài),
        return {author:"",text:""};
    },
    handleAuthorChange : function(e) {
        this.setState({
            author : e.target.value
        });
    },
    handleTextChange : function(e) {
        this.setState({
            text : e.target.value
        });
    },
    handleSubmit : function(e) {
        e.preventDefault();
        var author = this.state.author.trim();
        var text = this.state.text.trim();
        if(!text || !author){ //為空驗(yàn)證
            return;
        }
        //觸發(fā)評(píng)論提交事件,改變父組件的狀態(tài)
        this.props.onCommentSubmit({author:author,text:text});
        //改變自身的狀態(tài)
        this.setState({author:"",text:""});
    }
});

在這里有一個(gè)值得注意的點(diǎn),那就是抽象的自定義事件commentSubmit和真實(shí)的事件submit之間的聯(lián)系,這是一個(gè)相當(dāng)實(shí)用的技巧,在接下來(lái)的章節(jié)可以看到是如何實(shí)現(xiàn)的。

組件CommentBox

作為整個(gè)應(yīng)用的頂層組件,CommentBox需要做的事情有:

從服務(wù)器端請(qǐng)求已有的評(píng)論數(shù)據(jù)

將新的評(píng)論數(shù)據(jù)上傳到服務(wù)器

管理自身的狀態(tài),根據(jù)狀態(tài)對(duì)視圖進(jìn)行渲染(狀態(tài)改變的示意圖如下)

var CommentBox = React.createClass({
    getInitialState : function(){
        return {data : []};
    },
    loadCommentsFromServer : function() {
        //使用了jQuery的Ajax
        $.ajax({
            url : this.props.url,
            dataType : "json",
            cache : false,
            success : function(data) {
                this.setState({data:data});
            }.bind(this),
            error : function(xhr,status,err){
                console.err(this.props.url,status,err.toString());
            }.bind(this)
        });
    },
    componentDidMount : function() {
        /*
        這個(gè)方法屬于React組件生命周期方法,在render方法成功調(diào)用并且真實(shí)的DOM
        已經(jīng)渲染之后,調(diào)用此方法,這個(gè)方法發(fā)送json數(shù)據(jù)請(qǐng)求,并且設(shè)置一個(gè)定時(shí)器
        ,每隔一段時(shí)間就向服務(wù)器請(qǐng)求數(shù)據(jù)
        */
        this.loadCommentsFromServer();
        setInterval(this.loadCommentsFromServer,this.props.pollInterval);
    },
    handleCommentSubmit : function(comment) {
        /*
        這個(gè)方法也是比較有意思:
        1. 自定義了一個(gè)commentSubmit事件,并且此方法作為該事件的處理函數(shù)。
        2. 此方法是在子組件CommentForm的submit事件處理函數(shù)中調(diào)用
        */
        var comments = this.state.data;
        comment.id = Date.now();
        var newComments = comments.concat([comment]);
        //改變自身狀態(tài)
        this.setState({data:newComments});
        $.ajax({
            url : this.props.url,
            dataType: "json",
            type : "POST",
            data : comment,
            success : function(data) {
                this.setState({data:data});
            }.bind(this),
            error : function(xhr,status,err) {
                //還原數(shù)據(jù)
                this.setState({data:comments});
                console.err(this.props.url,status,err.toString());
            }.bind(this)
        });
    },
    render : function() {
        return (
            

Comments

); } });

最后,只需將組件CommentBox掛載到真實(shí)的DOM節(jié)點(diǎn)上,就可以看到效果了

ReactDOM.render(
    ,
    document.getElementById("content")
);

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/79605.html

相關(guān)文章

  • JavaScript - 收藏集 - 掘金

    摘要:插件開發(fā)前端掘金作者原文地址譯者插件是為應(yīng)用添加全局功能的一種強(qiáng)大而且簡(jiǎn)單的方式。提供了與使用掌控異步前端掘金教你使用在行代碼內(nèi)優(yōu)雅的實(shí)現(xiàn)文件分片斷點(diǎn)續(xù)傳。 Vue.js 插件開發(fā) - 前端 - 掘金作者:Joshua Bemenderfer原文地址: creating-custom-plugins譯者:jeneser Vue.js插件是為應(yīng)用添加全局功能的一種強(qiáng)大而且簡(jiǎn)單的方式。插....

    izhuhaodev 評(píng)論0 收藏0
  • React 和 ES6 工作流之 Webpack的使用(第六部分)

    摘要:在上面的列表中,是自解釋型的。我們將使用后者。調(diào)整文件的內(nèi)容到這一步,這個(gè)應(yīng)用就具備熱刷新的功能。下一步,更新文件中的到現(xiàn)在為止,如果你在控制臺(tái)運(yùn)行壓縮文件將被創(chuàng)建并且放在路徑下面。 這是React和ECMAScript2015系列文章的最后一篇,我們將繼續(xù)探索React 和 Webpack的使用。 下面是所有系列文章章節(jié)的鏈接: React 、 ES6 - 介紹(第一部分) Rea...

    Mr_houzi 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<