Uncaught TypeError: t.$el.prepend is not a functionindex.vue 里使用 <picker>来选取日期
在Chrome 44 里测试
显示picker之后关闭它
此时console里就出现了这个错误.
发生错误的文件为:webpack:///./node_modules/@dcloudio/uni-h5/dist/index.umd.min.js?1c31
发生错误的代码行:
_close: function() { var t = this; this.visible = !1, setTimeout((function() { var e = t.$refs.picker; e.remove(), t.$el.prepend(e), e.style.display = "none" } ), 260) }
@Babel来转换试试从源码HBuilderX\Bin\plugins\uniapp-cli\node_modules\@dcloudio\vue-cli-plugin-uni\lib\h5\index.js得知
useBuiltIns === ‘entry‘ ? `import ‘@babel/polyfill‘
从@babel/polyfill · Babel 中文网 得知
polyfill = import "core-js/stable";+import "regenerator-runtime/runtime";
从项目运行时调试可知引用的类型为@babel/core-js
查询`"HBuilderX\Bin\plugins\uniapp-cli\package.json"`可知当前版本为
"core-js": {
"version": "2.6.1",
在线搜索 zloirock/core-js: Standard Library 关键字prepend
没有任何匹配结果
结论: @babel/core-js无论新3旧0版本都不包含prepend的转换
可能是因为它是实验性特性功能?
uniapp-cli的browserslist兼容性配置
- Android 4.4.4 不支持
- Chrome 53 不支持
- 实验性功能
"HBuilderX\Bin\plugins\uniapp-cli\package.json"
参考: [解决方案5:[√有效的 最终采用的方案]](#解决方案5:[√有效的 最终采用的方案])
"browserslist": [ "Chrome >= 53" ] "browserslist": [ "Android >= 4" ]
无论怎么修改都无法解决问题.
大胆假设:难道是@babel版本太老的问题? 结论:不是的.
@financial-times/js-features-analyser源码寻找原因在[实验方案3](#实验方案3 - 研究Polyfill.io - create-polyfill-service-url源码寻找原因) 基础上一步步追溯源头发现是入口文件里在调用generatePolyfillURL 关键函数
async function generatePolyfillURL(features = [], supportedBrowsers = [])
"node_modules\create-polyfill-service-url\index.js"
然后关键features 参数内容由@financial-times/js-features-analyser组件提供
它是
@babel/core的插件Create a bundle which targets the syntax level you support (ES3/5/2017/2019) and then pass that bundle through this tool
在其源码目录可见其支持的各种类型
node_modules\create-polyfill-serv ice-url\node_modules\@financial-times\js-features-analyser\src
- built-in-definitions.js
- features.js
- globals.js
- instanceMethods.js
- staticMethods.js
结论就是这个组件根本不支持检测prepend关键字
灵光一闪:是否可以通过polyfill-library获取所有支持的特性,来代替js-features-analyser里的特性
node_modules\create-polyfill-service-url\node_modules\polyfill-library\polyfills\__dist\Element.prototype.prepend{ "aliases": ["default-3.4", "default-3.5", "default-3.6", "default"], "dependencies": ["document", "Element", "_mutation"], "spec": "http://dom.spec.whatwg.org/#dom-parentnode-prepend", "browsers": { "android": "<5", "bb": "*", "chrome": "<54", "edge": "<17", "edge_mob": "<17", "firefox": "<49", "ios_chr": "*", "ios_saf": "<10", "ie": "6 - *", "ie_mob": "10 - *", "opera": "<39", "op_mini": "*", "safari": "<10", "firefox_mob": "<49", "samsung_mob": "<6" }, "detectSource": "\"Element\"in self&&\"prepend\"in Element.prototype\n", "baseDir": "Element/prototype/prepend", "hasTests": true, "isTestable": true, "isPublic": true, "size": 123 }思路:
获取所有
polyfill-library支持的特性想办法检测"项目源码"里是否有用到上面的特性
- 办法1: 参考
js-features-analyser的方式优点: 项目用到啥就检测啥
缺点: 怕检测不准确
- 办法2: 读取所有特性配置文件里的
browsers,然后根据项目配置的浏览器兼容性来筛选需要用到的所有特性集合优点: 一次性将最低版本不兼容性的特性全弄出来.
缺点: 返回的数据可能有些大
caniuse-apireturns browsers which support some specific feature.Fyrd/caniuse: Raw browser/feature support data from caniuse.com
然后拼接成URL
然后自己部署polyfill-service - npm 在线服务
防止官方CDN网址失效
- 在@Babel编译后的基础上再检测,会更加的精简.
Polyfill.io - create-polyfill-service-url源码寻找原因进入其所在目录找到入口文件
node_modules\create-polyfill-service-url\index.js
发现代码很短,且用到了browserslist
const browsersListConfig = browserslist.loadConfig({ path: process.cwd() })
在实验方案1的开始前,在all.js脚本所在目录增加package.json
{ "browserslist": [ "Android >= 4", "ios >= 8" ] }
然后再按照实验方案1开始执行结果报错了
android 4.0.0 supports document
ios_saf 7.0.0 supports document
android 80.0.0 supports Promise
android 4.4.3 does not support Promise
android 80.0.0 does not support WeakSet
android 80.0.0 supports Set
android 4.4.3 does not support Set
Failed to parse the JavaScript from xxx because an error occured:
TypeError: Cannot read property ‘browsers‘ of undefined
根据爆出错误的堆栈信息,将源码修复以下
"\node_modules\create-polyfill-service-url\src\index.js"
generatePolyfillURL函数里
async function generatePolyfillURL(features = [], supportedBrowsers = [])
- 增加以下代码
if (supportedBrowsers.length > 0) { for (const feature of featuresInPolyfillLibrary) { const featureConfig = await polyfillLibrary.describePolyfill(feature); +if(!featureConfig) { + console.error( "not support the feature: ", feature ); + continue; +} const browsersWithoutFeature = featureConfig.browsers;
重新运行就不再报错了.
结果生成的URL特性里还是没有 没有 检测到prepend关键字!!!
有效方案1 + 实验方案1使用有效方案1的思路
将URL替换为实验方案1里得到的URL
实验结果:失败: polyfill.min.js文件加载8秒后失败
对比分析后发现失败原因是"无法解析cdn.polyfill.io的对应IP地址"
然后将其修改为polyfill.io再次实验
最后实验结果:失败
- 成功的下载到了
polyfill.min.js文件- 结果关闭Picker时还是爆出同样的异常
结论就是:Polyfill.io - create-polyfill-service-url 功能没有检测到.
Polyfill.io - create-polyfill-service-url分析看看将发布后的几个.js文件使用uglify-js 合并为一个all.js文件
此时在该文件里搜索
prepend关键字,能正常匹配到.
使用 Polyfill.io - create-polyfill-service-url 功能检测.JS文件
"D:\Program Files\Node.JS\node-v12.16.1-win-x64\create-polyfill-service-url.cmd" analyse --file all.js >r.md
最终得到了哪些函数特性需要转换
https://cdn.polyfill.io/v3/polyfill.min.js?features=Array.from,Array.of,Array.prototype.copyWithin,Array.prototype.entries,Array.prototype.fill,Array.prototype.find,Array.prototype.findIndex,Array.prototype.includes,Array.prototype.keys,Array.prototype.values,ArrayBuffer,console,CustomEvent,DataView,document,es5,Event,getComputedStyle,JSON,localStorage,Map,Math.acosh,Math.asinh,Math.atanh,Math.expm1,Math.fround,Math.imul,Math.log1p,Math.sign,Math.sinh,modernizr:es6string,MutationObserver,Number.parseFloat,Number.parseInt,Object.assign,Object.getOwnPropertySymbols,Object.is,Object.isExtensible,Object.isFrozen,Object.preventExtensions,Object.setPrototypeOf,Object.values,Promise,Promise.prototype.finally,Reflect,Reflect.defineProperty,Reflect.ownKeys,RegExp.prototype.flags,requestAnimationFrame,Set,setImmediate,String.fromCodePoint,Symbol,Symbol.iterator,Symbol.toStringTag,Uint16Array,Uint8ClampedArray,WeakMap,WeakSet,XMLHttpRequest
结果居然 没有 检测到prepend关键字!!!
Polyfill.io - url-builder直接选择prepend关键字打开Polyfill.io - url-builder 网站 通过筛选prepend关键字将匹配的都勾选上得到以下URL
https://polyfill.io/v3/polyfill.min.js?features=document%2CElement.prototype.prepend%2CDocumentFragment.prototype.prepend
然后在发布后的index.html文件里chunk-vendors.??.js脚本之前增加以上脚本引用
<div id=app></div> <script src=https://polyfill.io/v3/polyfill.min.js?features=document%2CElement.prototype.prepend%2CDocumentFragment.prototype.prepend></script> <script src=/H5/js/chunk-vendors.6a015935.js></script> <script src=/H5/js/index.07e4de0f.js></script>
然后在Chrome 44 版本上打开网页 - 选择时间Picker - 再关闭
√成功解决问题.
- browserslist能够把上面近似于人类语言的配置,转换成一组浏览器集合。
- Browserslist的浏览器数据来源就是这个caniuse-lite,而它是caniuse-db库的精简版本
- 每当增加一个新特性时,都要对以上浏览器列表以及对应版本列表进行实测,特性的测试可使用以下两个官方推荐的网站https://www.browserstack.com 和 http://saucelabs.com。
- Android 4.4.4 不支持
- Chrome 53 不支持
javascript - Error with method ParentNode.append() transpiling ES6 with Babel & Webpack - Stack Overflow javascript - Error with method ParentNode.append() transpiling ES6 with Babel & Webpack - Stack Overflow
Babel is a JavaScript compiler. It polyfills the JS language features. But
appendis a DOM feature so it can‘t be polyfilled by babel. You could use ember-cli-polyfill-io to polyfill the DOM.Reference:
(1) ParentNode.append polyfill is missing
(2) What babel-polyfill doesn‘t include
List of missing polyfills:
JSONis missing only in IE7String#normalizeis missing due to its rare usage and large size. Alternative polyfill: unormProxycan‘t be polyfilledwindow.fetchis not part of ECMAScript, but a web standard. While core-js does include some web standards,fetchis currently not one of them. Alternative polyfill: github fetchIntlis missing because of its large size. Alternative polyfill: Intl.js- DOM polyfills. For example
element.closest. What is included however are iterable DOM collectionsat this moment DOM polyfills are not in the
core-jsscope.2017
- ``. Instead, use bundlers like
webpackorrollup
ParentNode.prepend() - Web APIs | MDN
- You can polyfill the
prepend()method if it‘s not available- Chrome 54 以上版本
Element.prototype.prepend
DocumentFragment.prototype.prepend
Supported Browsers
- Internet Explorer 8
- Chrome 29
- Android 4.3
UNI-APP相关笔记 - `Uncaught TypeError: t.$el.prepend is not a function`
原文:https://www.cnblogs.com/AsionTang/p/13084175.html