如何使用react作为组件库而不是应用程序

时间:2017-06-13 12:42:05

标签: reactjs asp.net-mvc-4 webpack

我试图学习反应,并在现有项目中介绍它。因此,我想在一些有意义的地方使用反应,而不是在任何地方使用它。

问题是我无法理解的切入点概念。我更喜欢:

ReactDOM.render(
    <MyComponent/>,
    document.getElementById("componentExample")
);

cshtml附近<div id='componentExample'></div>内,而不是在单独的jsx内。我知道我无法在jsx中使用cshtml语法,但如果我写的话

<script src="@Url.Content("~/Scripts/dist/bundle.js")"></script>
<script>
    ReactDOM.render(
        React.createElement(MyComponent, {}, null), document.getElementById("componentExample")
    );
</script>

这不起作用,因为MyComponent未定义。它包含在我的bundle.js中(我必须将其添加为入口点),但它属于某些webpack内容的范围,并且不会公开。

这样做的正确方法是什么?

我的目标是为我的应用程序编写一些更适合的组件,并在这里和那里使用它,而不必完全进入基于反应的架构。

我的设置为webpack + babel polyfill + typescript + react,此内容位于ASP.NET MVC

我的webpack.config.js是:

var config = {
    entry: ['babel-polyfill', "./SiteScripts/React/index.tsx", "./SiteScripts/React/Components/MyComponent.tsx"],
    output: {
        filename: "./Scripts/dist/bundle.js",
    },

    // Enable sourcemaps for debugging webpack's output.
    devtool: "source-map",

    resolve: {
        // Add '.ts' and '.tsx' as resolvable extensions.
        extensions: [".webpack.js", ".web.js", ".ts", ".tsx", ".js"]
    },

    module: {
        rules: [
            // All output '.js' files will have any sourcemaps re-processed by 'source-map-loader'.
            {
                enforce: 'pre',
                test: /\.js$/,
                loader: "source-map-loader"
            },

            // All files with a '.ts' or '.tsx' extension will be handled by 'ts-loader'.
            {
                test: /\.tsx?$/, loaders: ['babel-loader', "ts-loader"], exclude: /node_modules/
            }
        ]
    },

    plugins : []
}

if (process.env.NODE_ENV === "production") {
    config.devtool = "cheap-module-source-map";
}


module.exports = config;

这也与问题有关(关于架构的问题):我想让我的bundle.js更小 - 现在是30k线。可能是因为我试图以错误的方式使用react

1 个答案:

答案 0 :(得分:0)

我终于找到了问题。我有一些错误(并没有完全理解webpack背后的整个理论),答案是我在问题中给出的代码,因此我没有任何答案。

首先我必须捆绑一个库,以便导出其中定义的内容(webpack.config.js):

 entry: ['babel-polyfill', "./SiteScripts/React/index.tsx"],
 output: {
        filename: "./Scripts/dist/bundle.js",
        libraryTarget: "var",
        library: "WebPack"
    },

这将使index.tsx中定义的类型/变量(我认为仅从条目列表中获取最后一个文件)和exported - 可通过WebPack.<name>

获取

我需要导出我的组件。我已经这样做了 - 但可能有更好的方法(index.tsx):

import { MyComponent} from "./Components/mycomponent";
export var myComponent = MyComponent;

我还需要确保所有子组件都是模块。这意味着在任何地方都使用import,并为所有元素,道具和州添加关键字export

之后我能够从:

渲染我的组件
<script src="@Url.Content("~/Scripts/dist/bundle.js")"></script>
<script>
    ReactDOM.render(
        React.createElement(WebPack.myComponent,
            {
                PropA = 2, PropB = "3"
            }, null),
        document.getElementById("componentExample")
    );
</script>

如果我这样做,还有一件事需要注意:<script src="@...行在我的结果html中不会发生多次(这很可能是因为我使用嵌入在单个页面中的许多组件) 。我使用这个javascript函数来确保我只加载bundle.js一次:

function loadJsOnce(url, whenFinish) {
    if (!window.loadedScripts) {
        window.loadedScripts = {};
    }

    if (!window.loadedScripts[url]) {
        var script = document.createElement('script');
        //script.async = true; // remove this if you don't want the script to be async
        script.src = url;
        script.onload = function() {
            whenFinish();
        }
        document.getElementsByTagName('head')[0].appendChild(script);

        window.loadedScripts[url] = true;
    } else {
        whenFinish();
    }
}

url我指定了bundle.js的路径,在whenFinish函数中,我放了一个调用ReactDOM.render(...内容的函数