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

資訊專欄INFORMATION COLUMN

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

aaron / 1362人閱讀

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

前言

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

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

JSX

react怎么少的了JSXJSX是什么,讓我來看個例子
現在有下面這段代碼:

const el = 

Hello Javascript

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

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

這種例子官網首頁也有demo

準備開始

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

下面我們開始

簡單的搭建

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

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

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

simple-react中執行 yarn init -ynpm init -y 生成package.json

創建一個index.html

創建src文件夾 再在src下創建index.js 然后再index.html中引入index.js

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

以上步驟完可能不完整,最好參考parcel里的內容。以上工作完成后,我們需要安裝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()

現在我們在index.js里開始編碼。
首先寫入代碼:

const el = 

Hello Javascript

; console.log(el);

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

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

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

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

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

const el = 

Hello Javascript

; console.log(el);

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

由打印結果可以看出,jsx在使用React.createElement方法轉譯時,createElement方法應該是這樣的:

createElement({ elementName, attributes, children });

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

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

children: 所有子節點

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

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

現在可以看到打印結果是:

我們再打印個復雜點的DOM結構:

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

和我們想要的結構一樣。
其實上面打印出來的就是虛擬DOM,現在我們要做的就是如何把虛擬DOM轉成真正的DOM對象并顯示在瀏覽器上。

ReactDOM.render()

要想將虛擬dom轉成真實dom并渲染到頁面上,就需要調用ReactDOM.render,比如:

ReactDOM.render(

Hello World

, document.getElementById("root"));

這段代碼轉換后的樣子:

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

這時,react會將

Hello World

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

現在我們實現render方法:

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

上面代碼中先調用createDom將虛擬dom轉成真實DOM然后掛載到container下。

我們來實現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);

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

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

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) {
      //如果是數字可以忽略px
        dom.style[name] =
          typeof value[name] === "number" ? value[name] + "px" : value[name];
      }
    }

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

現在render方法已經完整的實現了,我們將創建ReactDOM對象,將render方法掛上去:

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

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

那么萬事具備,我們來測試一下,直接上一個比較復雜的dom結構并加上屬性:

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

打開頁面,是我們想要的結果:

再看看控制臺的dom:

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

后語

該demo代碼在這里喲~~

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

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/94892.html

相關文章

  • 去哪兒網迷你React的研發心得

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

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

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

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

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

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

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

    blair 評論0 收藏0

發表評論

0條評論

aaron

|高級講師

TA的文章

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