使用 React 从 CDN 创建 DatePicker API

Creating a DatePicker from CDN with React API

我正在从 CDN 导入一些 React 模块(这不是必需的,我也尝试过本地构建,更多关于它的最后一个问题):

<script crossorigin src="https://unpkg.com/react-onclickoutside@6.9.0/dist/react-onclickoutside.min.js"></script>
<script crossorigin src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.29.0/moment.min.js" integrity="sha512-Izh34nqeeR7/nwthfeE0SI3c8uhFSnqxV0sI9TvTcXiFJkMd6fB644O64BRq2P/LA/+7eRvCw4GmLsXksyTHBg==" crossorigin="anonymous"></script>
<script crossorigin src="https://unpkg.com/react-datepicker@3.1.3/dist/react-datepicker.min.js"></script>

然后我有一个构建 React DatePicker 组件的脚本,这是其中的相关片段:

 HelloWorld.Example=function()
 {
  var p,setCount,count,p,c,myDate,datePicker;
  p=React.useState(0);
  setCount=p[1];
  count=p[0];
  p=React.useState(new moment(new Date((c=Date.now(),DateUtil.DatePortion(c)))));
  myDate=p[0];
  datePicker=React.createElement(DatePicker.default,{
   selected:new moment(new Date()),
   onChange:p[1]
  });
  React.set_setCount(setCount);
  return React.createElement("div",null,datePicker,React.createElement("p",null,(Html.textf(function()
  {

我从 JS 控制台看到的错误是:

react-datepicker.min.js:1 Uncaught TypeError: o is not a function
    at Ee (react-datepicker.min.js:1)

当脚本调用时 ReactDOM.render.

有没有办法理解什么是 o ?也许缺少进口? (编辑 好吧,查看 chrome 调试器并将其与 github 进行比较,oisValidDate,即 import isValidDate from "date-fns/isValid"; ,因此来自 date-fns 的导入无法从 CDN )

有没有办法 - 例如 - 我可以在本地 npm run build 所需的模块 react-datepicker,然后从我的脚本中调用反应 API,如上所示? (我收到的一个建议是将我的脚本配置为 webpack 中的条目,但 afaik React 不使用 webpack,尽管我看到它是 react-datepicker 中的 used

来自React docs,我可以读到

JSX is not a requirement for using React

所以像上面这样的事情应该是可行的,理论上

我在 github react-datepicker 存储库上打开了一个 question/issue(在从 WebSharper.React 调用此组件的上下文中)。

我认为主要问题是 WebSharper 脚本不是 JavaScript modules. In that case it should be immediate to import an external module or make the above SPA.js as the Webpack main entry. In fact it is well known that there are differences between <script type=module><script>

  • 模块脚本在严格模式下执行
  • 模块脚本有自己的作用域
  • 模块脚本可以导入其他 Javascript 模块
  • 模块脚本将其设为未定义
  • 内联模块脚本可以有异步属性
  • 模块脚本总是延迟

作为 confirmed by Adam Granicz 确实在 WebSharper 方面:

that should be the way, yes, @Jand42 and others have been working on changing the current output to support modules and a better TS interoperability - this has been on the agenda for years, so closing it would be a good step forward

(与此同时,当然还有其他选择,例如 flatpickr,它也具有 jQuery 的绑定,而不是 react-datepicker 或纯 React 或 F# Fable 而不是 WebSharper.React 等等)

Is there a way such that - for example - I can locally npm run build the needed module, react-datepicker, and then call the react API from my script as shown above?

是的,有一个众所周知的

写一个index.js如下

import React from "react";
import DatePicker from 'react-datepicker'
import "react-datepicker/dist/react-datepicker.css";

export {ImportedComponent}

window.MyDatePicker = function MyDatePicker(props) {
    console.log("props from window.MyDatePicker", props)
    return React.createElement( DatePicker, props );
  }

通过 npm 构建并将静态文件夹从 npm run build 的构建复制到项目的 SPA 文件夹中

复制 index.html 中的 3 个脚本标签构建到项目的 index.html 模板中 和 <div id="root"></div> (当然你为你的项目应用程序使用了不同的 id 和 这里不会渲染任何东西)

在我的情况下是(它们对你来说会有所不同)

<div id="root"></div>
<script>!function(e){function t(t){for(var n,l,p=t[0],f=t[1],i=t[2],c=0,s=[];c<p.length;c++)l=p[c],Object.prototype.hasOwnProperty.call(o,l)&&o[l]&&s.push(o[l][0]),o[l]=0;for(n in f)Object.prototype.hasOwnProperty.call(f,n)&&(e[n]=f[n]);for(a&&a(t);s.length;)s.shift()();return u.push.apply(u,i||[]),r()}function r(){for(var e,t=0;t<u.length;t++){for(var r=u[t],n=!0,p=1;p<r.length;p++){var f=r[p];0!==o[f]&&(n=!1)}n&&(u.splice(t--,1),e=l(l.s=r[0]))}return e}var n={},o={1:0},u=[];function l(t){if(n[t])return n[t].exports;var r=n[t]={i:t,l:!1,exports:{}};return e[t].call(r.exports,r,r.exports,l),r.l=!0,r.exports}l.m=e,l.c=n,l.d=function(e,t,r){l.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},l.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},l.t=function(e,t){if(1&t&&(e=l(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(l.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var n in e)l.d(r,n,function(t){return e[t]}.bind(null,n));return r},l.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return l.d(t,"a",t),t},l.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},l.p="/";var p=this.webpackJsonpcontent_npm=this.webpackJsonpcontent_npm||[],f=p.push.bind(p);p.push=t,p=p.slice();for(var i=0;i<p.length;i++)t(p[i]);var a=f;r()}([])</script>
<script src="/static/js/2.a6e4c224.chunk.js"></script>
<script src="/static/js/main.b075c560.chunk.js"></script>

现在开始

datePicker=React.createElement(window.MyDatePicker,{
   selected:myDate,
   onChange:p[1],
   showTimeSelect: true,
  });

在你 SPA.js 和 享受来自 WebSharper.React!

的任何 React 组件

顺便说一句,我必须传递一个 JS 日期,而不是 propsselected 中的 Moment 日期,我不确定为什么,反正这与问题无关。

仅供参考,这是来自 WebSharper 项目的 F# 代码

let myDate, setMyDate = WrapReact.UseState (DateTime.Today.JS)
let importDatePicker = JS.Eval("window.MyDatePicker") :?> React.Class 
let propDP = 
                {
                    selected = myDate 
                    onChange = setMyDate
                    showTimeSelect = true
                }
let datePicker =
    React.CreateElement( importDatePicker, propDP)
WrapReact.setCount <- setCount
div [] [
    
    datePicker
    p [] [Html.textf "You selected %s date %s time" (myDate.ToDateString()) (myDate.ToTimeString())]

完整的开源项目shared on github