您好,登錄后才能下訂單哦!
本文小編為大家詳細介紹“React實時預覽react-live源碼分析”,內容詳細,步驟清晰,細節處理妥當,希望這篇“React實時預覽react-live源碼分析”文章能幫助大家解決疑惑,下面跟著小編的思路慢慢深入,一起來學習新知識吧。
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
能夠支持下述語法直接渲染:
直接寫一個匿名函數:
() => <h4>So functional. Much wow!</h4>;
直接寫 jsx
:
<h4>Hello World!</h4>
單 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實時預覽react-live源碼分析”文章已經介紹完畢,想要掌握這篇文章的知識點還需要大家自己動手實踐使用過才能領會,如果想了解更多相關內容的文章,歡迎關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。