成人无码视频,亚洲精品久久久久av无码,午夜精品久久久久久毛片,亚洲 中文字幕 日韩 无码

資訊專欄INFORMATION COLUMN

親手?jǐn)]一個(gè)React(一):JSX與虛擬DOM

aaron / 1416人閱讀

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

前言

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

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

JSX

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

const el = 

Hello Javascript

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

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

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

準(zhǔn)備開始

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

下面我們開始

簡單的搭建

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

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

新建項(xiàng)目文件夾,這里取名為simple-react

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

創(chuàng)建一個(gè)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,當(dāng)然你也可以不用React.createElement和自定義方法,比如preact使用的h方法。

React.createElement()

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

const el = 

Hello Javascript

; console.log(el);

我們?cè)谑裁炊疾粚懙那闆r下,打印看看el是什么。

打印報(bào)錯(cuò):React沒有定義。 這是因?yàn)樵?b>.babelrc文件中,我們使用的這段代碼起了作用:

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

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

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

const el = 

Hello Javascript

; console.log(el);

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

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

createElement({ elementName, attributes, children });

elementName: dom對(duì)象的標(biāo)簽名 比如div、span等等

attributes: 當(dāng)前dom對(duì)象的屬性集合 比如class、id等等

children: 所有子節(jié)點(diǎn)

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

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

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

我們?cè)俅蛴€(gè)復(fù)雜點(diǎn)的DOM結(jié)構(gòu):

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

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

ReactDOM.render()

要想將虛擬dom轉(zhuǎn)成真實(shí)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")
);

這時(shí),react會(huì)將

Hello World

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

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

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

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

我們來實(shí)現(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é)點(diǎn)
  vnode.children.forEach(child => render(child, dom));
  return dom;
}

由于屬性的種類比較多,我們抽出一個(gè)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)完整的實(shí)現(xiàn)了,我們將創(chuàng)建ReactDOM對(duì)象,將render方法掛上去:

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

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

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

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

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

再看看控制臺(tái)的dom:

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

后語

該demo代碼在這里喲~~

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

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

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

相關(guān)文章

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

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

    pekonchan 評(píng)論0 收藏0
  • 言不合造輪子--個(gè)ReactTimePicker

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

    lifesimple 評(píng)論0 收藏0
  • 擁抱 JSX,它是個(gè)偉大的嘗試

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

    xorpay 評(píng)論0 收藏0
  • 擁抱 JSX,它是個(gè)偉大的嘗試

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

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

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

0條評(píng)論

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