21日間の手書きのフロントエンドフレームワークday3に挑戦して、ページを実行します

どちらの角度でカットするのが適切かわからないので、この記事を読むのに3分、書くのに3時間かかるので、変更しました。長い間苦労した後、ようやく今日の内容を決めました。

以前にphodalのローコード関連の記事を読んだことがありますが、プロジェクトの複雑さは力のようなものであり、転送されるだけで、空から消えることはないという文があります。

この文は多くの場所に当てはまると思います。たとえば、フロントエンドフレームワークを手書きする目的は、手書きのネイティブWebプロジェクトの複雑さをフレームワークに移すことです。

したがって、フロントエンドフレームワークを作成するために、フロントエンド開発の元の開始点に戻り、フロントエンド開発について学習した最初のデモを思い出すことができます。

たとえば、単純なHelloWorldを記述します。

<!DOCTYPE html>
<html lang="en">
<body>
    <div id="malita">
        <span>loading...</span>
    </div>
    <script>
        const root = document.getElementById('malita');
        root.innerHTML = '<span>Hello Malita!</span>';
        root.addEventListener('click', (event) => {
            event.target.innerHTML = '<span>Hi!</span>';
        })
    </script>
</body>
</html>
复制代码

フロントエンドの基本を少し知っている学生は、上記のコードロジックを一目で確認できるはずです。つまり、ページに「Hello Malita!」が表示され、ユーザーがそれをクリックすると「Hi!」になります。

上記の要件は非常に単純ですが、フロントエンドの基盤がない学生でも、もう少し一目でそれを理解できますが、最新のフロントエンドフレームワークでよく言及されているMVCアーキテクチャを使用して分析する場合。

Hello Malita!およびHi!はデータであり、Modelレイヤーに保存されます;<span>ビューViewはレイヤーに保存されます;クリックイベントと値の変更はコントロールレイヤーに保存されControllerます;

上記のコードを逆アセンブルすると、次のコードセグメントが得られます。誇張すると、これはReactとVueのコアソースコードです。これは、メンバーシップを購入せずに見ることができるものではありません。(私は吹いています、私はVueを知りません)

<script>
        function Model() {
            this.text = 'Hello Malita!';
            this.setText = text => this.text = text;
        }

        function View(controller) {
            const self = this;
            self.root = document.getElementById('malita');
            self.root.addEventListener('click', controller.onClick)
            this.render = () => {
                const text = controller.getModel().text;
                self.root.innerHTML = `<span>${text}</span>`;
            }
        }

        function Controller(model) {
            const self = this;
            self.model = model;
            this.onClick = (event) => {
                self.model.setText('Hi!');
                // 数据驱动页面,页面应该根据 model 更改响应 render
                const text = controller.getModel().text;
                event.target.innerHTML = `<span>${text}</span>`;
            }
            this.getModel = () => {
                return self.model;
            }
        }
        const model = new Model();
        const controller = new Controller(model);
        const view = new View(controller);
        view.render();
    </script>
复制代码

Reactを使用して上記の機能を実現する方法を見てみましょう。

その後の開発を容易にするために(実際、私はcdnリンクをコピーするのが面倒です)、現在のプロジェクトのルートディレクトリにreactとreact-domをインストールします

npm i react react-dom
复制代码

次に、デモで紹介します

    <script src="../../node_modules/react/umd/react.development.js"></script>
    <script src="../../node_modules/react-dom/umd/react-dom.development.js"></script>
复制代码

次に、Reactの生の使用法を使用して、上記の機能を実現します

<body>
    <div id="malita">
        <span>loading...</span>
    </div>
    <script>
        const Hello = () => {
            const [text, setText] = React.useState('Hello Malita!');
            return React.createElement("span", {
                onClick: () => {
                    setText('Hi!');
                }
            }, text);
        };

        const root = ReactDOM.createRoot(document.getElementById('malita'));
        root.render(React.createElement(Hello));
    </script>
</body>
复制代码

基本的なReactの基盤がない場合は、このユースケースを上記のユースケースと比較して詳しく調べてください。

React開発に構文を使用createElementする際の最大の問題は、ネストのレベルがあると非常に複雑になることです。読みやすさが非常に悪い。

シンプルなど

<div><p>Hello<span>Malita!</span></p></div>
复制代码

次のコードを記述する必要があります。

React.createElement("div", null, React.createElement("p", null, "Hello", React.createElement("span", null, "Malita!")));

就相当于你在写 html 的时候,都不使用 html 的标签,而是全部使用 js 方法 document.createElement(tagName) 来编写整个页面。

所以为了更加便于书写和阅读,充分利用 html 和 js 的优势,我们进行 React 开发一般都会使用 jsx 语法。

依旧是上面的需求,我们引入 jsx,代码变得更直观了:

<body>
    <div id="malita">
        <span>loading...</span>
    </div>
    <script>
        const Hello = () => { 
            const [text, setText] = React.useState('Hello Malita!'); 
            return (<span onClick={()=> {
                setText('Hi!')
            }}> {text} </span>);
        }; 
        const root = ReactDOM.createRoot(document.getElementById('malita')); 
        root.render(React.createElement(Hello));
    </script>
</body>
复制代码

但是写完发现,浏览器是无法识别 jsx 语法的,所以我们要引入 babel 来将我们的 jsx 语法转换成 React 的原始语法。

其实 babel 的实现原理非常简单,就是通过将代码转换成抽象语法书 (AST),再转换成目标语法,记下来,这是面试题。

在项目中安装 babel-standalone

npm i babel-standalone
复制代码

然后在项目中引入,并且修改 script 的 type 为 text/babel

<head>
+ <script src="../../node_modules//babel-standalone/babel.min.js"></script>
</head>

<body>
    <div id="malita">
        <span>loading...</span>
    </div>
-    <script>
+    <script type="text/babel">
    </script>
</body>

复制代码

我测试的时候使用的是谷歌浏览器 V100 ,所以里面用到的 ES6 的一些语法,它都可以识别,后续我们也会使用 babel 将我们的 es6 代码转换成 es5。

到此我们就完成了让页面运行起来的所有尝试。

值得注意的是,这不是一个 React 的零基础入门教程,文章的用意在于讲清楚前端框架的部分运行原理和工作内容,你可以把这当作一篇需求文档来对待,因为我们会在后续的内容中,用更加科学合理的方式来实现它。

在这一个系列中,我会尽量讲明“为什么使用XXX”,它解了什么问题。

感谢阅读,如果你有其他的疑问,或者对这个系列书写的角度和切入点有其他的看法和建议的话,欢迎在评论区和我互动。

源码归档

おすすめ

転載: juejin.im/post/7085734601636708383