zoukankan      html  css  js  c++  java
  • React 入门(5): 引入JSX 研究JSX的createElement实现

    安装依赖

    使用@babel/core

    babel从7.0 之后,包名升级为 @babel/core。 和 vue-cli 升级到 @vue/cli 一样, @babel是一个group标记, 该组织发布的包在一个子目录下:

    这样一来, 要查询官方包, 只需要执行npm search @babel就可以了.

    → 最新的babel引入JSX (推荐)

    npm i -S @babel/core @babel/preset-env @babel/preset-react babel-loader
    

    → 使用babel-core (即@babel/core<7.0.0 不推荐)

    npm i -S babel-core babel-preset-es2015 babel-preset-react babel-loader
    

    添加Webpack模块规则

    babel提供了js编译能力, 那自然是把js传递给bebel提供的loader模块编译, 没错, 我们有babel-loader, 并指定presets[]查询参数以启用相应的babel预设.

    // @babel/core 推荐
    { test: /.js$/, exclude: /node_modules/, loader: 'babel-loader?presets[]=@babel/env&presets[]=@babel/react' },
    // babel-core 不推荐
    { test: /.js$/, exclude: /node_modules/, loader: 'babel-loader?presets[]=es2015&presets[]=react' },
    

    Babel提案插件

    React的默认属性等功能最好使用类静态属性, 类共有字段, 类私有字段等ES提案, 这些提案不像类静态方法一样是ES6标准, 只是提案, 所以没有被预设.
    安装Babel插件以支持类静态属性:

    npm i -S @babel/plugin-proposal-class-properties
    

    安装完成后需要设置webpack模块规则:

    rules: [
        { test: /.css$/, use: ['style-loader', 'css-loader?modules'] },
        { test: /.(html|png|jpg|ico)$/, use: 'file-loader?context=src&name=[path][name].[ext]' },
        {
            test: /.js$/, exclude: /node_modules/, loader: {
                loader: 'babel-loader',
                options: {
                    presets: ['@babel/env', '@babel/react'], // 预设
                    plugins: ['@babel/plugin-proposal-class-properties'], // 插件
                }
            }
        }, // babel
    ],
    

    研究JSX的createElement实现

    JSX只是语法糖, 始终都会编译为JavaScript代码. 这也说明JSX只是可选的.

    function render() {
        return <App><button onClick={() => console.log(this)}>研究JAX</button></App>;
    }
    console.log(render);
    

    为什么这样做, 因为一个React标签代表一次createElement调用, 也就是返回的React对象, 因此要打印函数, 也可以是箭头函数:

    console.log(() => <div>组件</div>);
    console.log((() => <div>组件</div>).toString()); // toString()避免浏览器省略
    

    关于createElement函数

    createElement(el, props, [...children]) : ReactElement;
    

    el

    el 可以是一个:

    • ReactElement函数 → 即"函数式组件"
      函数执行后最终返回一个ReactElement元素, propschildren合并为第一个调用参数, (存在第二个参数, 推测是父组件的props或者状态).
    • Component子类 → 即"类组件"
      该类继承React.Component, 将创建一个该类的实例, 并调用render()函数.
    • 字符串
      必须是原生html标签.

    children

    children 可以是一个:

    • ReactElement对象
      通过调用createElement()函数生成. 有时也直接实例化Component对象并调用其render()函数(本质上还是调用createElement()函数).
    • 字符串
      相当于<span>标签.
    • 数组
      一个children参数也可以是上诉合法参数的数组. 避免了解构合并等繁琐操作. 不过每一个数组里的元素都要提供一个唯一的key属性, 否则有警告.

    页面不是组件

    页面不是组件, 不需要继承Component类, 所以可以导出一个返回ReactElement的函数:

    export default (props, ?) => (<div>App</div>); // 导出函数
    
    import App from './pages/App';
    ReactDOM.render(<StrictMode><App /></StrictMode>, /* container */ window.app);
    

    如果连参数也不需要, 那么可以直接导出ReactElement:

    export default (<div>App</div>); // 导出元素
    
    import App from './pages/App';
    ReactDOM.render(<StrictMode>{App}</StrictMode>, /* container */ window.app);
    // 等价于
    ReactDOM.render(<StrictMode children={App}></StrictMode>, /* container */ window.app);
    

    子组件<Child />{Child}的区别

    子组件有以下两种编写方式:

    <Father><Child /></Father>
    <Father>{Child}</Father>
    
    // 对应的js实现
    function whatsJSX() { return /*#__PURE__*/React.createElement(Father, null, /*#__PURE__*/React.createElement(Child, null)); }
    function whatsJSX2() { return /*#__PURE__*/React.createElement(Father, null, Child); }
    
  • 相关阅读:
    数组名作为左值和右值的区别
    指针与数组区别
    linux服务器开启免密登录
    mssql清空数据和添加主键约束语法
    链接服务器方式查视图导致索引失效的解决方法
    sqlserver2008r2 版本数据库迁移到2019版本导致查询效率慢的解决方法
    lnmp一键安装访问default目录可行,访问其它站点报404错误
    lPeer reports incompatible or unsupported protocol version.
    yum安装时出现:Cannot retrieve metalink for repository: epel. Please verify its path and try again
    Linux Centos7.4 下安装 LAMP环境及配置(php5.6,mysql5.7)
  • 原文地址:https://www.cnblogs.com/develon/p/13666642.html
Copyright © 2011-2022 走看看