简体   繁体   English

使用 React API 从 CDN 创建 DatePicker

[英]Creating a DatePicker from CDN with React API

I am importing some React modules from CDN (that's not a requirement, I've also tried with a local build, more in the final question about it):我正在从 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>

Then I have a script to build the React DatePicker component, this is the relevant snippet from it:然后我有一个脚本来构建 React DatePicker组件,这是其中的相关片段:

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

The error that I see from the JS Console is:我从 JS 控制台看到的错误是:

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

when the script call ReactDOM.render .当脚本调用ReactDOM.render

Is there a way to understand what is o ?有没有办法理解什么是o Maybe an import missing?也许缺少导入? ( Edit Well, looking at chrome debugger and comparing it to github , o is isValidDate , ie import isValidDate from "date-fns/isValid"; , hence the imports from date-fns are not working from CDN ) 编辑好吧,查看 chrome 调试器并将其与github进行比较, oisValidDate ,即import isValidDate from "date-fns/isValid"; ,因此从date-fns isValidDate import isValidDate from "date-fns/isValid";不能从 CDN 工作)

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?有没有办法 - 例如 - 我可以在本地npm run build所需的模块react-datepicker ,然后从我的脚本中调用 react API,如上所示? (a suggestion that I received was configuring my script as entry in webpack , but afaik React doesn't use webpack , though I see it is used in react-datepicker ). (我收到的一个建议是将我的脚本配置为webpack条目,但 afaik React 不使用webpack ,尽管我看到它在react-datepicker webpack使用)。

From React docs , I can read thatReact docs ,我可以读到

JSX is not a requirement for using React JSX 不是使用 React 的必要条件

so something like the above should be doable, in theory .所以理论上像上面这样的事情应该是可行的。

I've opened a question/issue on github react-datepicker repo (in the context of calling this component from WebSharper.React ).我已经在 github react-datepicker repo 上打开了一个问题/问题(在从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?有没有办法 - 例如 - 我可以在本地npm run build所需的模块react-datepicker ,然后从我的脚本中调用 react API,如上所示?

Yes, there is a well known solution !是的,有一个众所周知的解决方案

Write an index.js as follows编写一个 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 );
  }

build via npm and copy the static folder from the build of your by npm run build to the SPA folder of your proj通过npm构建并将静态文件夹从通过npm run build复制到您的项目的 SPA 文件夹中

copy the 3 script tags from the index.html in the build into the index.html template of your proj and <div id="root"></div> (of course you use a different id for your project app and there will be nothing to render here)将构建中的 index.html 中的 3 个脚本标记复制到您的 proj 和<div id="root"></div>的 index.html 模板中(当然,您为项目应用程序使用不同的 ID,这里没什么可渲染的)

in my case they are (they will be different for you)在我的情况下它们是(它们对你来说会有所不同)

<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>

Now go with现在去

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

in you SPA.js and enjoy any react component like this one from WebSharper.React !在您的 SPA.js 中,并享受来自 WebSharper.React 的任何像这样的反应组件

Btw I had to pass a JS date, not a Moment date here in the selected of props , I'm not sure why, anyway, this is not relevant to the problem.顺便说一句,我必须在selectedprops传递 JS 日期,而不是 Moment 日期,我不确定为什么,无论如何,这与问题无关。

FYI, this is the F# code from WebSharper project仅供参考,这是来自 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())]

Full open source project shared on github .在 github 上共享的完整开源项目。

I think that the main problem is that WebSharper scripts are not JavaScript modules .我认为主要问题是 WebSharper 脚本不是JavaScript 模块 In that case it should be immediate to import an external module or make the above SPA.js as the Webpack main entry.在这种情况下,应该立即导入外部模块或将上述SPA.js作为Webpack主条目。 In fact it is well known that there are differences between <script type=module> and <script>其实众所周知<script type=module><script>是有区别的

  • Module Script Execute in Strict Mode模块脚本在严格模式下执行
  • Module Script has its Own Scope模块脚本有自己的作用域
  • Module Script can Import other Javascript Modules模块脚本可以导入其他 Javascript 模块
  • Module Script has this as Undefined模块脚本将此作为未定义
  • Inline Module Script can have async Attribute内联模块脚本可以有 async 属性
  • Module Script is Always Deferred模块脚本总是被推迟

As confirmed by Adam Granicz indeed on WebSharper side:正如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应该就是这样,是的,@Jand42 和其他人一直在努力改变当前的输出以支持模块和更好的 TS 互操作性 - 这已经被列入议程多年,所以关闭它会是一个很好的进步

(In the meantime there are of course alternatives, eg flatpickr , which has bindings also for jQuery, instead of react-datepicker or pure React or F# Fable instead of WebSharper.React and so on) (与此同时,当然还有其他选择,例如flatpickr ,它也绑定了 jQuery,而不是react-datepicker或纯 React 或 F# Fable 而不是 WebSharper.React 等等)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM