成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

親手擼一個React(一):JSX與虛擬DOM

aaron / 1364人閱讀

摘要:前言的火熱程度已經(jīng)達到了個,本系列文章主要用簡單的代碼來實現(xiàn)一個,來了解虛擬算法以及和的設(shè)計。要想將虛擬轉(zhuǎn)成真實并渲染到頁面上,就需要調(diào)用,比如這段代碼轉(zhuǎn)換后的樣子這時,會將掛載到為的下,從而在頁面上顯示出來。

前言

react的火熱程度已經(jīng)達到了94.5k個start,本系列文章主要用簡單的代碼來實現(xiàn)一個react,來了解JSX、虛擬DOM、diff算法以及state和setState的設(shè)計。

提到react,當然少不了vue,vue的api設(shè)計十分簡單 上手也非常容易,但黑魔法很多,使用起來有點虛, 而react沒有過多的api,它的深度體現(xiàn)在設(shè)計思想上,使用react開發(fā)則讓人比較踏實、能拿捏的住,這也是我喜歡react的原因之一。

JSX

react怎么少的了JSX,JSX是什么,讓我來看個例子
現(xiàn)在有下面這段代碼:

const el = 

Hello Javascript

這樣的js代碼如果不經(jīng)過處理會報錯,jsx是語法糖,它讓這段代碼合法化,通過babel轉(zhuǎn)化后是這樣的:

const el = React.createElement(
    "h3",
    { className: "title" },
    "Hello Javascript"
)

這種例子官網(wǎng)首頁也有demo

準備開始

開始編碼之前,先介紹兩個東西:parcelbabel-plugin-transform-jsx,等會我們用parcel搭建一個開發(fā)工程,babel-plugin-transform-jsxbabel的一個插件,它可以將jsx語法轉(zhuǎn)成React.createElement(...)

下面我們開始

簡單的搭建

parcel這里就不介紹了,一句話概況就是為你生成一個零配置的開發(fā)環(huán)境。

yarn global add parcel-bundlernpm install -g parcel-bundler

新建項目文件夾,這里取名為simple-react

simple-react中執(zhí)行 yarn init -ynpm init -y 生成package.json

創(chuàng)建一個index.html

創(chuàng)建src文件夾 再在src下創(chuàng)建index.js 然后再index.html中引入index.js

如果你先麻煩,可以直接下載源碼修改。

以上步驟完可能不完整,最好參考parcel里的內(nèi)容。以上工作完成后,我們需要安裝babel-plugin-transform-jsx

npm insatll babel-plugin-transform-jsx --save-dev
或者
yarn add babel-plugin-transform-jsx --dev

然后添加.babelrc文件,并在該文件中加入下面這段代碼:

{
  "presets": ["env"],
  "plugins": [["transform-jsx", { "function": "React.createElement" }]]
}

上面代碼的意思是 使用transform-jsx插件,并配置為通過React.createElement方法來解析JSX,當然你也可以不用React.createElement和自定義方法,比如preact使用的h方法。

React.createElement()

現(xiàn)在我們在index.js里開始編碼。
首先寫入代碼:

const el = 

Hello Javascript

; console.log(el);

我們在什么都不寫的情況下,打印看看el是什么。

打印報錯:React沒有定義。 這是因為在.babelrc文件中,我們使用的這段代碼起了作用:

["transform-jsx", { "function": "React.createElement" }]

上面說過,它會通過React.createElement方法來轉(zhuǎn)譯JSX,那么我們就給出這個方法:
我們把剛才那段代碼改變一下:

const React = {
  createElement: function(...args) {
    return args[0];
  }
};

const el = 

Hello Javascript

; console.log(el);

上面代碼添加了一個React對象,并在其中添加一個createElement方法,現(xiàn)在再執(zhí)行一下看看打印出什么:

由打印結(jié)果可以看出,jsx在使用React.createElement方法轉(zhuǎn)譯時,createElement方法應(yīng)該是這樣的:

createElement({ elementName, attributes, children });

elementName: dom對象的標簽名 比如div、span等等

attributes: 當前dom對象的屬性集合 比如class、id等等

children: 所有子節(jié)點

現(xiàn)在我們改寫一下createElement方法,讓key的名稱簡單一點:

const React = {
  createElement: function({ elementName, attributes, children }) {
    return {
      tag: elementName,
      attrs: attributes,
      children
    };
  }
};

現(xiàn)在可以看到打印結(jié)果是:

我們再打印個復(fù)雜點的DOM結(jié)構(gòu):

const el = (
  
Hello JavaScript
); console.log(el);

和我們想要的結(jié)構(gòu)一樣。
其實上面打印出來的就是虛擬DOM,現(xiàn)在我們要做的就是如何把虛擬DOM轉(zhuǎn)成真正的DOM對象并顯示在瀏覽器上。

ReactDOM.render()

要想將虛擬dom轉(zhuǎn)成真實dom并渲染到頁面上,就需要調(diào)用ReactDOM.render,比如:

ReactDOM.render(

Hello World

, document.getElementById("root"));

這段代碼轉(zhuǎn)換后的樣子:

ReactDOM.render(
  React.createElement("h1", null, "Hello World"),
  document.getElementById("root")
);

這時,react會將

Hello World

掛載到id為root的dom下,從而在頁面上顯示出來。

現(xiàn)在我們實現(xiàn)render方法:

function render(vnode, container) {
  const dom = createDom(vnode); //將vnode轉(zhuǎn)成真實DOM
  container.appendChild(dom);
}

上面代碼中先調(diào)用createDom將虛擬dom轉(zhuǎn)成真實DOM然后掛載到container下。

我們來實現(xiàn)createDom方法:

function createDom(vnode) {
  if (vnode === undefined || vnode === null || typeof vnode === "boolean") {
    vnode = "";
  }

  if (typeof vnode === "string" || typeof vnode === "number") {
    return document.createTextNode(String(vnode));
  }

  const dom = document.createElement(vnode.tag);

    //設(shè)置屬性
  if (vnode.attrs) {
    for (let key in vnode.attrs) {
      const value = vnode.attrs[key];
      setAttribute(dom, key, value);
    }
  }
    //遞歸render子節(jié)點
  vnode.children.forEach(child => render(child, dom));
  return dom;
}

由于屬性的種類比較多,我們抽出一個setAttribute方法來設(shè)置屬性:

function setAttribute(dom, key, value) {
  //className
  if (key === "className") {
    dom.setAttribute("class", value);

    //事件
  } else if (/onw+/.test(key)) {
    key = key.toLowerCase();
    dom[key] = value || "";
    //style
  } else if (key === "style") {
    if (typeof value === "string") {
      dom.style.cssText = value || "";
    } else if (typeof value === "object") {
      // {width:"",height:20}
      for (let name in value) {
      //如果是數(shù)字可以忽略px
        dom.style[name] =
          typeof value[name] === "number" ? value[name] + "px" : value[name];
      }
    }

    //其他
  } else {
    dom.setAttribute(key, value);
  }
}

現(xiàn)在render方法已經(jīng)完整的實現(xiàn)了,我們將創(chuàng)建ReactDOM對象,將render方法掛上去:

const ReactDOM = {
  render: function(vnode, container) {
    container.innerHTML = "";
    render(vnode, container);
  }
};

這里在調(diào)用render之前加了一句container.innerHTML = "",就不解釋了,相信大家都明白。

那么萬事具備,我們來測試一下,直接上一個比較復(fù)雜的dom結(jié)構(gòu)并加上屬性:

const element = (
  
alert(1)} style={{ color: "red", fontSize: 30 }} > Hello javascript!
); ReactDOM.render(element, document.getElementById("root"));

打開頁面,是我們想要的結(jié)果:

再看看控制臺的dom:

很完美,這是我們想要的東西

后語

該demo代碼在這里喲~~

本文敘述了JSX和虛擬DOM,以及將虛擬DOM轉(zhuǎn)成真實DOM的過程,后面的文章會繼續(xù)敘述react中的組件、生命周期、diff算法和異步setState,敬請期待~

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

轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/94892.html

相關(guān)文章

  • 去哪兒網(wǎng)迷你React的研發(fā)心得

    摘要:市面上竟然擁有多個虛擬庫。虛擬庫,就是出來后的一種新式庫,以虛擬與算法為核心,屏蔽操作,操作數(shù)據(jù)即操作視圖。及其他虛擬庫已經(jīng)將虛擬的生成交由與處理了,因此不同點是,虛擬的結(jié)構(gòu)與算法。因此虛擬庫是分為兩大派系算法派與擬態(tài)派。 去哪兒網(wǎng)迷你React是年初立項的新作品,在這前,去哪兒網(wǎng)已經(jīng)深耕多年,擁有QRN(react-native的公司制定版),HY(基于React的hybird方案)...

    pekonchan 評論0 收藏0
  • 言不合造輪子--ReactTimePicker

    摘要:時間選擇的表盤其實有兩個,一個是小時的選擇,另一個則是分鐘的選擇。也就是說,第一步選擇小時,第二部選擇分鐘它是一個小時制的時間選擇器。而則用于處理拖拽事件,標記著當前是否處于被拖拽狀態(tài)。 本文的源碼全部位于github項目倉庫react-times,如果有差異請以github為準。最終線上DEMO可見react-times github page 文章記錄了一次創(chuàng)建獨立React組件...

    lifesimple 評論0 收藏0
  • 擁抱 JSX,它是偉大的嘗試

    摘要:是一個看起來像的語法擴展。有人覺得看起來太怪異了,但是我覺得是一個偉大的嘗試,是科學(xué)進步的表現(xiàn),我們不應(yīng)該對他有任何偏見。所以有一個口號,就是所以,的是一個偉大的嘗試,我們應(yīng)該擁抱。 原文: http://eyasweb.com/#/blog/detail/12 react 帶來了新的語法,JSX。是一個看起來像XML的JavaScript語法擴展。 有些同學(xué)因為不喜歡或不習(xí)慣JSX語...

    xorpay 評論0 收藏0
  • 擁抱 JSX,它是偉大的嘗試

    摘要:是一個看起來像的語法擴展。有人覺得看起來太怪異了,但是我覺得是一個偉大的嘗試,是科學(xué)進步的表現(xiàn),我們不應(yīng)該對他有任何偏見。所以有一個口號,就是所以,的是一個偉大的嘗試,我們應(yīng)該擁抱。 原文: http://eyasweb.com/#/blog/detail/12 react 帶來了新的語法,JSX。是一個看起來像XML的JavaScript語法擴展。 有些同學(xué)因為不喜歡或不習(xí)慣JSX語...

    blair 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<