<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
react-live
是一個 react
的實時編輯器,可直接編輯 react
程式碼,並實時預覽。可以看下官方的預覽圖:
src ├── components │ ├── Editor │ │ └── index.js │ └── Live │ ├── LiveContext.js │ ├── LiveEditor.js │ ├── LiveError.js │ ├── LivePreview.js │ ├── LiveProvider.js │ └── LiveProvider.test.js ├── constants │ └── theme.js ├── hoc │ └── withLive.js ├── index.js └── utils ├── test │ ├── errorBoundary.test.js │ ├── renderer.js │ └── transpile.test.js └── transpile ├── errorBoundary.js ├── evalCode.js ├── index.js └── transform.js
先看下匯出內容,包括:
Editor
:編輯器LiveProvider
:實時編輯環境的 Provider
,Context.Provider
LiveEditor
:實時編輯上下文的編輯器LiveError
:實時編輯上下文的報錯LivePreview
:實時編輯上下文的預覽LiveContext
:實時編輯的 Context
withLive
:實時編輯上下文的 HOC
檔案結構和元件拆分一目瞭然。
先看下 Provider
,它提供了以下內容:
element
:實時編輯輸出的元素error
:當前的報錯資訊code
:當前編輯的程式碼language
:程式碼語言theme
:程式碼編輯器主題disabled
:是否禁用onError
:報錯的回撥onChange
:程式碼編輯時的回撥Provider
用來收集程式碼變更,然後通過 transpileAsync
將程式碼編譯生成元件範例:
function transpileAsync(newCode) { const errorCallback = error => { setState({ error: error.toString(), element: undefined }); }; try { const transformResult = transformCode ? transformCode(newCode) : newCode; return Promise.resolve(transformResult) .then(transformedCode => { const renderElement = element => setState({ error: undefined, element }); // Transpilation arguments const input = { code: transformedCode, scope }; if (noInline) { setState({ error: undefined, element: null }); // Reset output for async (no inline) evaluation renderElementAsync(input, renderElement, errorCallback); } else { renderElement(generateElement(input, errorCallback)); } }) .catch(errorCallback); } catch (e) { errorCallback(e); return Promise.resolve(); } }
renderElementAsync
可以先無視,主要是用於 noInline
模式下呼叫 render
進行渲染,邏輯與非 noInline
模式下類似。
實時預覽的核心部分就在這裡了,它會將程式碼先進行編譯,然後執行程式碼,取得返回值。
const generateElement = ({ code = '', scope = {} }, errorCallback) => { // NOTE: Remove trailing semicolon to get an actual expression. const codeTrimmed = code.trim().replace(/;$/, ''); // NOTE: Workaround for classes and arrow functions. const transformed = transform(`return (${codeTrimmed})`).trim(); return errorBoundary(evalCode(transformed, { React, ...scope }), errorCallback); };
程式碼如上,它會先去掉頭尾空白,然後去掉結尾的分號,這一步是為了下一步的 return
拼接能夠正常返回。通過 return
拼接讓 react-live
能夠支援下述語法直接渲染:
直接寫一個匿名函數:
() => <h3>So functional. Much wow!</h3>;
直接寫 jsx
:
<h3>Hello World!</h3>
單 class
元件:
class Comp extends React.Component { render() { return <center>component</center>; } }
不過也導致了一定的學習成本,如果寫多個函數,多個元件,巢狀等情況下會讓人覺得語法很奇怪。
transform
就是將程式碼通過 sucrase
進行轉譯,處理 jsx
、class
這些語法,可以理解為通過 babel
轉譯。
早期的 react-live
通過 buble
進行轉譯,能夠支援 jsx
註釋,現在由於 sucrase
不支援 jsx
註釋,所以新版無法使用 jsx
註釋來控制 jsx
渲染引擎。
/** @jsx mdx */ // 新版上述註釋會失效
隨後將轉譯的程式碼通過 evalCode
轉換為 React element
,此處會將 scope
和 React
傳入 evalCode
中。
const evalCode = (code, scope) => { const scopeKeys = Object.keys(scope); const scopeValues = scopeKeys.map(key => scope[key]); return new Function(...scopeKeys, code)(...scopeValues); };
evalCode
中使用 new Function
來建構函式,scope
就是在這裡作為引數進行注入。如果對 new Function
不理解的可以看我之前一篇關於 JS
沙箱的文章。
errorBoundary
則是一個簡單的 HOC
,用來捕獲生成的元件執行時的錯誤資訊,通過 errorCallback
丟擲。
const errorBoundary = (Element, errorCallback) => { return class ErrorBoundary extends Component { componentDidCatch(error) { errorCallback(error); } render() { return typeof Element === 'function' ? <Element /> : React.isValidElement(Element) ? Element : null; } }; };
上面就是 react-live
能夠實時預覽的核心程式碼了。下面再看下其它幾個元件,都比較簡單。
LivePreview
會接受 Provider
中的 Element
,將其渲染。
LiveError
接受 Provider
中的 error
進行渲染。
LiveEditor
則是接收 Provider
的 code
、language
、theme
、disabled
、onChange
,提供編輯功能。
它的編輯器則是通過 useEditable
編輯,Prism
進行程式碼高亮。
上述便是 react-live
的核心程式碼,內容並不多,通過 sucrase
實時編譯程式碼,然後通過 new Function
建構函式注入 scope
來生成 element
實現實時預覽,設計上通過拆離 Editor
、Error
、Preview
三部分,可以讓使用者自由組合元件的位置、樣式。
以上就是React實時預覽react-live原始碼解析的詳細內容,更多關於react live實時預覽的資料請關注it145.com其它相關文章!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45