关于uniapp:UniApp微信小程序解决苹果手机上方刘海屏遮挡的方法

大家好,我是你们的好敌人咕噜铁蛋!明天我要和大家分享一种解决苹果手机上方刘海屏遮挡的办法,特地实用于UniApp开发的微信小程序。如果你在开发过程中遇到了这个问题,无妨跟着我一起来看看如何解决吧!苹果手机的刘海屏设计给用户带来了更大的视觉享受,但对于开发者来说,它也带来了一些布局上的挑战,尤其是在微信小程序开发中。因而,咱们须要寻找一种办法来确保应用程序在苹果手机上可能失常显示,不被刘海屏遮挡。上面是解决的步骤: 理解苹果手机的刘海屏尺寸苹果手机的刘海屏通常有肯定的高度,咱们须要理解具体的尺寸以便进行布局调整。目前,iPhone X、iPhone XS、iPhone XR等机型都采纳了相似的刘海屏设计,其高度约为30px左右。应用CSS适配刘海屏在UniApp开发中,咱们能够应用CSS的safe-area-inset-top属性来适配刘海屏。这个属性能够获取到刘海屏的平安区域高度,并将布局进行调整,以确保内容不被刘海屏遮挡。在须要适配刘海屏的组件或页面中,能够增加以下款式代码: .selector { padding-top: constant(safe-area-inset-top); /* 兼容 iOS 12.0-12.1 */ padding-top: env(safe-area-inset-top); /* 兼容 iOS 11.0-11.4 */}通过应用这些款式,咱们能够在刘海屏手机上设置顶部内边距,以防止内容被刘海遮挡。 思考底部平安区域除了顶部的刘海屏之外,苹果手机还有底部的平安区域,通常用于虚构Home按钮。为了确保应用程序的内容不被底部平安区域遮挡,咱们也能够应用相似的CSS款式来适配,具体代码如下: .selector { padding-bottom: constant(safe-area-inset-bottom); /* 兼容 iOS 12.0-12.1 */ padding-bottom: env(safe-area-inset-bottom); /* 兼容 iOS 11.0-11.4 */}通过增加这些款式,咱们能够设置底部的内边距,以防止内容被底部平安区域遮挡。 测试和调整在实现以上步骤后,咱们须要在理论设施上进行测试,确保应用程序在苹果手机上的显示成果合乎预期。如果依然存在布局问题,能够依据具体情况进行调整,尝试不同的款式或布局办法。通过理解苹果手机刘海屏的尺寸,应用CSS的safe-area-inset-top和safe-area-inset-bottom属性,咱们能够很好地解决UniApp微信小程序在苹果手机上方刘海屏遮挡的问题。这种适配办法简单易行,可能确保应用程序的失常显示,晋升用户体验。心愿这篇文章对你有所帮忙。如果你有其余对于UniApp开发或者苹果手机刘海屏适配的问题,欢送在评论区留言,咱们一起交流学习吧!感激大家的浏览,咱们下期再见!

February 28, 2024 · 1 min · jiezi

关于uniapp:客户管理crm系统软件源码CRM小程序源码php版带uniapp

 客户治理crm系统软件源码是一种为企业设计的数字工具,用于无效地组织、监控和保护无关现有和潜在客户的数据。该软件集中了来自各种潜在客户、流量、流动和收买起源的数据,并创立了记录和配置文件。该软件具备残缺客户数据库的存储库,涉众能够应用它来治理长期客户合同和关系。 局部源码:index_css.css body{ background-color: #EEEEEE;}.nav{ width: 100%; background-color: #fff; color:#3EABFF}.nav-div{ width:63%;margin: 20px auto}.body{ width: 80%; display: flex; justify-content: center; align-items: center; margin: 30px auto;}.footer{ width: 63%; margin: 30px auto; text-align: justify;}.footer h4{ margin-bottom: 0; color: black;}.footer p{ font-size: 14px;}blockquote{ margin: 0; border-left: .2rem solid #3EABFF; padding: .2em}.category button{ margin:0px 5px 5px; width: 70px;}.tel{ height:30px; text-align: right;}.tel h2,.tel h5{ display : inline;}.btn-primary-cus { color: #007bff; background-color: transparent; border-color: #007bff; box-shadow: none;}.btn-primary-cus:hover { color: #fff; background-color: #007bff; border-color: #007bff;}.btn-primary-full{ color: #fff; background-color: #007bff; border-color: #007bff;}.btn-primary-full:hover { color: #fff; background-color: #000dff; border-color: #007bff;}.nav-div h4{ font-size: 2.5rem;}.bg-white { background-color: #fff; color: #1f2d3d!important;}.p-3 { padding: 1rem!important;}.text-muted{ color:#5e5e5e;} 客户治理crm系统软件源码(CRM) 是一套集成的、数据驱动的软件解决方案,可帮忙治理、跟踪和存储与公司以后和潜在客户相干的信息。通过将这些信息保留在集中式零碎中,业务团队能够在须要时取得所需的见解。 如果没有集成 CRM 解决方案的反对,您的公司可能会错失增长机会并失去潜在支出,因为它没有优化经营流程或充分利用客户关系和销售线索。 客户治理crm系统软件源码装置过程 以下是客户治理crm系统软件源码装置过程的个别步骤: 1. 下载源码:从文章结尾处下载客户治理crm系统软件源码。 2. 装置本地开发环境:确保你的计算机上曾经装置了PHP、MySQL和Apache等必要的开发环境。 3. 创立数据库:应用MySQL或其余数据库管理工具创立一个新的数据库。 4. 配置数据库连贯:找到源码中的数据库配置文件(通常是config.php或database.php),依据你的数据库设置,批改连贯字符串、用户名和明码等参数。 5. 导入数据库构造:将源码中的数据库构造文件(通常是.sql文件)导入到你创立的数据库中,能够应用phpMyAdmin或MySQL命令行工具来执行导入操作。 6. 配置网站根目录:将源码中的所有文件复制到你的Web服务器的根目录下。 7. 设置文件权限:确保源码中的相干文件和目录(如上传目录、缓存目录)具备适当的写入权限。 8. 配置网站拜访门路:依据你的服务器环境,配置域名、虚拟主机或子目录的拜访门路。 9. 测试装置:在浏览器中拜访你设置的网站地址,如果一切正常,你应该可能看到CRM零碎的登录界面。 10. 初始化零碎设置:首次登录零碎时,你可能须要进行一些根本的配置,如设置管理员账号、公司信息等。 11. 装置实现:实现上述步骤后,你应该曾经胜利装置了客户治理crm系统软件源码,能够开始应用零碎了。 客户治理crm系统软件源码有什么作用? 不久前,公司通过电子表格、电子邮件、地址簿和其余孤立的、通常基于纸质的 CRM 解决方案来跟踪客户相干数据。不足集成和自动化妨碍了团队外部和团队之间的人员疾速查找和共享最新信息,从而升高了他们创立营销流动、寻求新销售线索和服务客户的能力。 到了明天,CRM 零碎主动收集无关现有和潜在客户的大量信息。这些数据包含电子邮件地址、电话号码、公司网站、社交媒体帖子、购买历史记录以及服务和反对票证。接下来,零碎会集成数据并生成综合档案,以便与适当的团队共享。 CRM 零碎还与其余业务工具连贯,包含在线聊天和文档共享应用程序。此外,它们还具备内置的商业智能和人工智能 (AI) 性能,可减速治理工作并提供可行的见解。 换句话说,古代CRM 工具使销售、营销、商务、现场服务和客户服务团队可能立刻理解并拜访对倒退、改善和保留客户关系至关重要的所有。 您能够通过以下形式应用 CRM 性能来使您的公司受害: 通过销售漏斗监控每个机会以取得更好的销售。CRM 解决方案有助于跟踪潜在客户相干数据并提供见解,因而销售和营销团队能够放弃东倒西歪,理解每个潜在客户在销售流程中的地位,并理解每个机会的负责人。 应用销售监控来获取实时绩效数据。将销售数据链接到您的 CRM 解决方案中,以提供即时、精确的销售状况。通过实时查看您的管道,您将理解任何放缓和瓶颈,或者您的团队是否博得了重大交易。 通过洞察生成来布局您的下一步。应用人工智能和内置智能来专一于最重要的事件,以确定最重要的优先事项以及您的团队如何充分利用他们的工夫和精力。例如,销售团队能够确定哪些潜在客户已筹备好移交,哪些须要跟进。 通过自动化优化工作流程。通过工作自动化构建销售报价、收集客户反馈并发送电子邮件流动,这有助于简化营销、销售和客户服务。因而,有助于打消重复性工作,以便您的团队能够专一于高影响力的流动。 跟踪客户互动以取得更大影响。CRM 解决方案包含利用客户行为和外表优化机会的性能,以帮忙您更好地理解各个客户接触点的参与度。 跨多个平台连贯以实现卓越的客户参加。无论是通过实时聊天、电话、电子邮件还是社交互动,CRM 解决方案都能够帮忙您与客户保持联系,帮忙建设信赖和忠诚度,从而吸引客户成为回头客。 麻利成长并取得竞争劣势。基于高度平安的平台构建的可扩大、集成的 CRM 解决方案有助于满足您的业务和市场一直变动的需要。疾速启动新的营销、电子商务和其余动作,并对消费者需要和市场情况做出疾速响应。 为什么施行客户治理crm系统软件源码? 当您定义 CRM 策略并评估客户关系治理解决方案时,请寻找可能提供每个客户关系的残缺视图的解决方案。您还须要一个解决方案来收集每个客户接触点的相干数据、剖析数据并智能地出现见解。 借助 CRM 零碎,您的公司能够帮忙增强沟通并确保客户旅程每个阶段的卓越体验,如下所述: 辨认并吸引适合的客户。预测性洞察和数据驱动的买家行为可帮忙您学习如何辨认、定位和吸引正确的潜在客户,而后将其转化为客户。 改善客户互动。通过对客户的全面理解,销售团队的每个成员都将理解客户的历史记录、购买模式以及任何具体数据,这些数据将帮忙您的团队为每个客户提供最周到的服务。 跟踪整个客户旅程的进度。理解客户在整个销售生命周期中的地位有助于您定位流动和机会以取得最高的参与度。 进步团队生产力。进步可见性和简化流程有助于进步生产力,帮忙您的团队专一于最重要的事件。 客户治理crm系统软件源码如何帮忙您的公司? 各种规模的公司都能够从 CRM 软件中受害。对于寻求倒退的小型企业,CRM 有助于实现业务流程自动化,使员工可能专一于更高价值的流动。对于企业来说,CRM 甚至能够帮忙简化和改善最简单的客户互动。 认真理解 CRM 零碎如何帮忙您的各个业务团队受害。 营销团队 改善客户的旅程。凭借生成多渠道营销流动的能力、通过有针对性的买家体验培养销售就绪的潜在客户以及使您的团队与布局和实时跟踪工具保持一致,您可能提出可能引起客户共鸣的精心策划的营销策略。 当您通过定制的数据分析仪表板深刻理解您的品牌名誉和市场时,您能够优先思考对您的业务最重要的潜在客户,并依据有针对性的自动化流程后果推动的见解和业务决策疾速适应。 销售团队 使卖家可能与客户互动,真正理解他们的需要,并无效博得更多交易。随着业务的增长,通过有针对性的销售策略寻找适合的潜在客户和客户变得更加容易,从而为您的管道下一步制订胜利的行动计划。 通过嵌入式洞察构建更理智的销售策略有助于造就关系、进步生产力、减速销售业绩并利用现代化且适应性强的平台进行翻新。通过应用能够掂量过来和当初当先指标的人工智能性能,您能够从始至终跟踪客户关系,并通过上下文提醒主动执行销售,从而提供个性化体验并随时随地与买家的旅程保持一致。 客户服务团队 为客户提供轻松的全渠道体验。通过应用服务机器人,您的客户服务团队将领有可能提供价值并进步每次交互参与度的工具。通过提供个性化服务,代理商能够应用相干的上下文数据进行追加销售或穿插销售,并依据反馈、考察和社交凝听,依据实时服务趋势优化其资源。 通过提供全渠道反对的疏导式智能服务,客户能够轻松地与客服人员分割并疾速解决问题,从而取得一流的客户体验。 ...

February 28, 2024 · 1 min · jiezi

关于uni-app:解决uniapp-vue3-nvue中使用pinia页面空白问题让你的应用更稳定

嗨,各位小伙伴们,我是你们的好盆友咕噜铁蛋!随着Vue3和nvue在uni-app中的广泛应用,应用pinia作为状态管理工具曾经成为了不少开发者的首选。然而,在理论开发过程中,咱们有时会遇到一个奇怪的问题:在应用pinia后,nvue页面会呈现空白的状况。明天,我将和大家分享如何解决uni-app vue3 nvue中应用pinia页面空白问题,让你的利用更加稳固!一、问题剖析在应用pinia后,咱们有时候会发现nvue页面呈现了空白,这可能是因为pinia与nvue的兼容性问题导致的。在nvue中,咱们须要通过Vue.use()来装置pinia插件,然而在Vue3中,这种形式并不实用。所以当咱们在nvue页面中应用pinia时,可能会呈现一些兼容性问题,导致页面无奈失常显示。二、解决方案为了解决这个问题,咱们须要依照以下步骤进行操作: 装置vuex-composition-helpers插件为了在nvue中应用pinia,咱们能够应用vuex-composition-helpers插件进行状态治理,这个插件能够帮忙咱们在Vue3的composition API中应用Vuex。咱们能够通过npm install vuex-composition-helpers命令来装置这个插件。在nvue页面中应用vuex-composition-helpers装置完vuex-composition-helpers后,咱们能够在nvue页面中应用这个插件来进行状态治理。首先,在nvue页面中导入pinia和vuex-composition-helpers: import { defineComponent } from "vue"import pinia from "@/store/pinia"import { useStore } from "vuex-composition-helpers"而后,在组件中应用useStore()办法来获取store实例,并且通过computed属性来获取须要应用的状态: export default defineComponent({ setup() { const store = useStore(pinia) const count = computed(() => store.state.count) return { count } }})这样,咱们就能够在nvue中失常应用pinia进行状态治理了。 应用pageLifetimes监听页面生命周期在nvue中,咱们须要应用pageLifetimes来监听页面的生命周期,以确保在页面渲染时正确获取到状态。在页面的onReady办法中,咱们能够通过setData()办法来更新页面数据。 export default defineComponent({ pageLifetimes: { show() { this.setData({ count: useStore(pinia).state.count }) } }, setup() { return {} }})通过以上步骤,咱们能够解决uni-app vue3 nvue中应用pinia页面空白问题,让你的利用更加稳固。如果你遇到了其余技术问题,或者有其余须要帮忙的中央,欢送在评论区留言,咱们一起交流学习吧!感激大家的浏览,咱们下期再见!

February 26, 2024 · 1 min · jiezi

关于uniapp:最新uniapp打包IOS详细步骤让你的APP在苹果设备上飞起来

嗨,各位敬爱的小伙伴们,我是你们好敌人咕噜铁蛋!在挪动利用开发的路线上,想要让本人的APP在iOS设施上失常运行并顺利上架App Store,就必须把握uni-app在iOS平台上的打包步骤。明天,我将为大家具体介绍最新的uni-app打包iOS的步骤,让你的APP在苹果设施上飞起来!一、筹备工作在开始打包之前,咱们须要先实现一些筹备工作。确保你曾经装置好Xcode,并且在uni-app我的项目中配置了正确的利用信息(如AppID、Bundle Identifier等),以及实现了必要的iOS开发者证书和形容文件的配置。二、生成签名密钥首先,咱们须要在uni-app我的项目中生成签名密钥。关上HBuilderX,在我的项目根目录下找到manifest.json文件,抉择“编译模式”为“生产模式”,而后点击“发行”-“原生App-生成打包资源”来生成签名密钥。三、配置打包参数接下来,咱们须要在HBuilderX中配置打包参数。抉择“发行”-“原生App-本地打包配置”来设置相干的打包参数,包含Xcode门路、开发者证书、形容文件等。四、执行打包命令实现以上步骤后,在HBuilderX中抉择“发行”-“原生App-发行到iOS平台”,期待打包过程实现。期间可能须要输出开发者证书明码等信息,依照提醒操作即可。五、在Xcode中进行调试打包实现后,咱们能够在Xcode中关上生成的.xcworkspace文件,连贯iOS设施进行调试测试。确保利用在真机上失常运行,并查看是否有异样问题须要修复。六、提交App Store审核最初一步是将打包好的利用提交到App Store进行审核。在Xcode中抉择“Product”-“Archive”,而后上传至App Store Connect进行审核流程,期待苹果官网审核通过后,你的APP就能够在App Store上线啦!通过以上具体步骤,置信大家曾经把握了uni-app在iOS平台上的打包流程。心愿这篇文章可能帮忙到正在进行iOS利用开发的小伙伴们,让你的APP在苹果设施上腾飞起来!如果你有任何问题或者想分享教训,欢送在评论区留言,咱们一起学习提高吧!感激大家的浏览,咱们下期再见!

February 25, 2024 · 1 min · jiezi

关于uniapp:unibest-uniapp-vue3-模板-UI-框架选型

背景unibest 作为最好的 uniapp 开发模板,那 UI 框架 的抉择也是要认真斟酌的。 unibest 作为 uniapp + vue3 + ts 的我的项目,天然也要抉择满足 vue3 的 UI库,所以像 vue2 时代的 uview 就不思考在内了。然而在 uview 的根底上衍生进去的反对 vue3 的 uview 系 的 ui框架 还有不少,而且热度很高。 再来说说官网保护的 uni-ui,反对全端,而且有类型提醒,目前曾经内置到 unibest 了,如果用户的确用不到外面的组件也能够删除,缩小包体积。 TIPS: uni-ui 自身是 js 开发的,然而官网提供了齐备的类型提醒( by @uni-helper/uni-ui-types)所以看起来就像是 ts 开发的一样,开发体验很好。所有的组件都有提醒,很不便,很贴心。UI 框架通过搜查了一番,目前加入比照的 UI 框架有: uview-plus (uveiw 系) - 文档地址uv-ui (uveiw 系) - 文档地址Wot Design Uni (wot 系) - 文档地址TuniaoUI (图鸟系) - 文档地址还有 2 个 UI 框架也很优良,然而局部组件开源收费,局部组件免费: ...

February 21, 2024 · 1 min · jiezi

关于uni-app:UniApp中打开蓝牙所需哪些权限

<article class=“article fmt article-content”><p>Hello,各位同学们新年好呀,咱们又见面了!我是咕噜铁蛋!随着挪动利用的遍及,蓝牙技术正变得越来越重要。在UniApp中,关上蓝牙性能为咱们提供了更多便当和翻新的可能性。然而,很多人可能不分明在UniApp中关上蓝牙须要哪些权限。明天铁蛋将带你深刻摸索这个问题,帮忙你理解UniApp中关上蓝牙所需的权限。<br/>蓝牙技术作为一种短距离无线通信技术,曾经广泛应用于各种设施中,包含智能手机、智能手表、蓝牙耳机等。在UniApp中,通过关上蓝牙性能,咱们能够实现更多乏味的性能,如蓝牙音频传输、蓝牙设施连贯等。然而,为了保障用户的隐衷和数据安全,UniApp在关上蓝牙时须要获取一些权限。<br/>一、UniApp中关上蓝牙的权限列表<br/>以下是UniApp中关上蓝牙所需的权限列表:</p><ol><li>蓝牙权限<br/>为了可能失常应用蓝牙性能,UniApp须要获取蓝牙权限。蓝牙权限容许UniApp扫描、连贯和通信蓝牙设施。用户在应用UniApp时,须要受权利用获取蓝牙权限。</li><li>定位权限<br/>在某些状况下,为了可能失常应用蓝牙性能,UniApp还须要获取定位权限。定位权限能够帮忙UniApp确定设施的地位信息,从而更好地进行蓝牙设施的扫描和连贯。用户在应用UniApp时,须要受权利用获取定位权限。</li><li>存储权限<br/>UniApp中关上蓝牙可能波及到数据的读取和存储操作,因而须要获取存储权限。存储权限容许UniApp拜访设施上的文件和文件夹,以便进行数据的读取和存储。用户在应用UniApp时,须要受权利用获取存储权限。</li><li>网络权限<br/>在UniApp中关上蓝牙时,可能须要通过网络连接获取一些额定的数据或者进行蓝牙设施的互联互通。因而,UniApp须要获取网络权限。网络权限容许UniApp进行网络通信,包含数据的发送和接管。用户在应用UniApp时,须要受权利用获取网络权限。<br/>以上是UniApp中关上蓝牙所需的次要权限列表,具体权限可能会依据不同的UniApp版本和性能有所差别。<br/>二、权限的正当应用<br/>在获取这些权限时,开发者须要留神权限的正当应用和隐衷爱护。以下是一些倡议:</li><li>仅获取必要权限:开发者在设计利用时,应仅获取必要的权限,并对权限的应用进行正当限度。防止滥用权限,以爱护用户的隐衷和数据安全。</li><li>明确告知用户:在利用中,开发者应清晰明确地告知用户须要获取哪些权限,并解释为什么须要这些权限。用户应该可能明确为什么他们须要受权利用获取这些权限。</li><li>受权治理:开发者应提供权限治理性能,使用户可能自主抉择是否受权利用获取某些权限。用户应具备撤销权限受权的权力。</li><li>数据安全爱护:开发者在应用蓝牙性能时,须要留神用户数据的平安爱护。采取适当的安全措施,确保用户的数据不被歹意利用或泄露。<br/>咱们理解到在UniApp中关上蓝牙所需的权限包含蓝牙权限、定位权限、存储权限和网络权限。这些权限的正当应用能够为用户带来更好的体验,同时也须要开发者增强隐衷爱护和数据安全。心愿通过明天铁蛋的分享,大家可能更好地了解UniApp中关上蓝牙所需的权限,并在利用开发中正当应用这些权限,为用户提供更好的服务。</li></ol></article>

February 20, 2024 · 1 min · jiezi

关于uniapp:uniapp项目实践总结二十四安卓平台-APP-打包教程

导语:当你的利用程序开发实现后,在上架安卓利用商店之前,须要进行打包操作,上面简略介绍一下打包办法。目录筹备工作配置我的项目生成证书打包配置筹备工作在打包之前,请保障你的 uniapp 应用程序编译到安卓手机模拟器的 App 是能够失常运行的,APP 打包分为安卓和 ios 两个平台,上面简略介绍一下安卓的打包办法,因为本地打包问题较多,操作比较复杂,这里就省略了,本次次要介绍在线打包的办法。 配置我的项目次要是在manifest.json进行配置;关上文件后增加以下几个内容。 根本信息利用名称、形容、版本名称、版本号; 图标配置上传你的利用图标,倡议1024*1024,而后主动生成所有图标并替换; 启动界面应用原生隐衷政策提示框,这个很重要,勾选后会主动生成配置文件androidPrivacy.json,示例如下: 依据你本人的理论状况填写对应的内容和地址。 { "version": "1.0.0", "prompt": "template", "title": "服务协定和隐衷政策", "message": " 请你务必审慎浏览、充沛了解“服务协定”和“隐衷政策”各条款,包含但不限于:为了更好的向你提供服务,咱们须要收集你的设施标识、操作日志等信息用于剖析、优化利用性能。<br/> 你可浏览<a href=\"\">《服务协定》</a>和<a href=\"\">《隐衷政策》</a>理解详细信息。如果你批准,请点击上面按钮开始承受咱们的服务。", "buttonAccept": "批准并承受", "buttonRefuse": "暂不批准", "hrefLoader": "system|default", "backToExit": "false", "second": { "title": "确认提醒", "message": " 进入利用前,你需先批准<a href=\"\">《服务协定》</a>和<a href=\"\">《隐衷政策》</a>,否则将退出利用。", "buttonAccept": "批准并持续", "buttonRefuse": "退出利用" }, "disagreeMode": { "support": false, "loadNativePlugins": false, "visitorEntry": true, "showAlways": false }, "styles": { "backgroundColor": "#00FF00", "borderRadius": "5px", "title": { "color": "#ff00ff" }, "buttonAccept": { "color": "#ffff00" }, "buttonRefuse": { "color": "#00ffff" }, "buttonVisitor": { "color": "#00ffff" } }}模块配置这块依据你本人的须要进行打勾抉择。比方我用到的是扫码,分享就勾选就好了;如果遇到领取,登录或分享,还须要到对应平台申请利用 ID 和通用链接。 ...

September 26, 2023 · 2 min · jiezi

关于uniapp:uniapp项目实践总结二十三网页和小程序应用打包教程

导语:当你的利用程序开发实现后,在公布到互联网之前,须要进行打包操作,包含网页端、小程序端的打包。目录筹备工作网页打包小程序打包筹备工作在打包之前,请保障你的 uniapp 应用程序编译到网页、小程序是能够失常运行的。 网页打包编写好利用之后,如需打包到 web 平台,能够选中以后我的项目根目录: 在顶部菜单栏找到发行菜单点击后;找到网站-PC Web 或手机 H5(仅实用于 uni-app)子菜单;点击当前增加网站题目和域名;点击发行即可开始打包;打包当前在{{根目录}}\unpackage\dist\build\h5目录下生成,依据你本人的须要上传服务器部署网站。 小程序打包编写好利用之后,如需打包到微信小程序平台,能够选中以后我的项目根目录: 在顶部菜单栏找到发行菜单点击后;找到你要打包的小程序,比方小程序-微信(仅实用于 uni-app)子菜单;点击当前增加小程序题目和小程序 AppId点击发行即可开始打包。打包当前在{{根目录}}\unpackage\dist\build\mp-weixin目录下生成,依据你本人的须要关上微信开发者工具,导入我的项目,点击右上角的上传按钮提交微信审核。 最初以上就是利用打包到网页、小程序的次要内容,有不足之处,请多多斧正。

September 26, 2023 · 1 min · jiezi

关于uniapp:uniapp项目实践总结二十二分包优化和游客模式

导语:这篇次要介绍利用分包和游客模式相干的内容。目录利用分包游客模式利用分包微信对于小程序的打包压缩后的代码体积是有限度的,网页和 APP 也能够实用分包性能,因而须要进行分包增加以及分包优化。 分包增加在pages.json文件中增加分包的信息。例如:有一个名叫user的分包,外面有一个文件是index.vue,那么分包配置就是: { "pages": [ { "path": "pages/index/index", "style": { "navigationBarTitleText": "首页" } } ], "subPackages": [ { "root": "user", "pages": [ { "path": "index", "style": { "navigationBarTitleText": "分包首页" } } ] } ]}配置实现后该文件的拜访地址就是/user/index,其中的user是在根目录下寄存的。 分包优化增加配置分包优化的办法是在manifest.json文件中对应的平台增加以下配置: 例如:mp-weixin平台下增加分包优化。 { "mp-weixin": { "optimization": { "subPackages": true } }}注意事项目前只反对mp-weixin、mp-qq、mp-baidu、mp-toutiao、mp-kuaishou的分包优化;分包目录内搁置的动态资源不会被打包到主包中,也不可在主包中应用;当某个 js 仅被一个分包援用时,该 js 会被打包到该分包内,否则仍打到主包(即被主包援用,或被超过 1 个分包援用);若某个自定义组件仅被一个分包援用时,且未放入到分包内,编译时会输入提示信息;微信小程序目前微信小程序分包大小有以下限度: 整个小程序所有分包大小不超过 20M;单个分包/主包大小不能超过 2M;游客模式在一些平台,比方微信小程序和苹果 ios 利用商店,上架的利用肯定要提供游客模式才能够进行审核通过。 如何实现游客模式呢,上面就来简略实现一下。 服务端配置能够通过动静配置来关上或敞开游客模式。 例如:默认开启游客模式。 { "vistor": true}客户端配置客户端依据服务端的配置来设置是否开启游客模式。 逻辑剖析开启游客模式后,启动利用就应该能够进入到应用程序的主页面,而后能够随便旅行和应用,当遇到须要登录能力拜访的中央,再跳转到登录页面;敞开游客模式后,启动利用后须要先登录账号,而后才能够拜访利用内的页面或者应用利用提供的服务和性能;设置缓存启动利用获取服务端配置后能够设置缓存数据: // 接口获取到的数据let config = { vistor: true,};// 存入本地uni.setStorage("vistor", config.vistor);获取缓存在要拜访的页面触发须要登录能力应用的性能之前,先判断是否开启了游客模式,如开启再提醒并跳转登录。 ...

September 25, 2023 · 1 min · jiezi

关于uniapp:uniapp项目实践总结二十URLScheme-协议知识总结

导语:在日常开发过程中,咱们常常能够碰到很多的调起某个利用,关上唤醒某个 APP,链式启动 App 等场景,背地就波及到了 URLScheme 协定的相干常识,上面就简略介绍一下。目录简介常见 URL Scheme跳转办法实战演练案例展现简介URL Scheme是一个能够让 APP 之间相互跳转的协定,每个 APP 都有本人的 URL Scheme,如果存在雷同的 URL Scheme,会先跳转先装置的 APP,前面装置的会被笼罩掉。 协定格局[scheme]://[host][:port]/[/path]?[query] scheme:协定名称,由开发人员自定义host:域名port:端口path:页面门路query:申请参数例如淘宝:taobao:// 设施判断// 游览器标识const ua = navigator.userAgent.toLowerCase();// 是否微信内const isWeixin = ua.indexOf("micromessenger") !== -1;// 是否android终端const isAndroid = /(Android)/i.test(ua);// 是否ios终端const isIOS = /(iPhone|iPad|iPod|iOS|Mac)/i.test(ua);常见 URL Scheme利用市场market 谷歌利用商店tmast 利用宝mimarket 小米samsungapps 三星huawei 华为oppomarket oppovivomarket vivoitms-apps ios电商taobao 淘宝tmall 天猫jdlogin 京东pinduoduo 拼多多kaola 网易考拉yanxuan 网易严选vipshop 唯品会suning 苏宁mishopv1 小米商城wireless1688 阿里巴巴社交、社区weibo 微博zhihu 知乎xhsdiscover 小红书momochat 陌陌blued bluedmqzone QQ 空间mqq QQtantanapp 探探huputiyu 虎扑com.baidu.tieba 贴吧tianya 天涯社区douban 豆瓣jike 即刻短视频snssdk1128 抖音snssdk1112 火山snssdk32 西瓜视频gifshow 快手视频/直播tenvideo 腾讯视频youku 优酷bilibili B 站imgotv 芒果 TVqiyi-iphone 爱奇艺hanju 韩剧 TVdouyutv 斗鱼yykiwi 虎牙图片解决mtxx.open 美图秀秀faceu faceu 国内ulike 轻颜国内资讯snssdk141 今日头条newsapp 网易新闻qqnews 腾讯新闻iting 喜马拉雅weread 微信读书jianshu 简书igetApp 失去kuaikan 快看漫画财经sinanews 新浪财经amihexin 同花顺炒股音乐orpheus 网易云音乐qqmusic qq 音乐kugouURL 酷狗qmkege 全民 K 歌changba 唱吧工具iosamap 高德地图baidumap 百度地图baiduyun 百度网盘rm434209233MojiWeather 墨迹天气办公wxwork 企业微信dingtalk 钉钉生存imeituan 美团dianping 点评cainiao 菜鸟裹裹wbmain 58 同城mihome 米家美食佳饮xcfapp 下厨房sbuxcn 星巴克中国meituanwaimai 美团外卖静止衰弱fb370547106731052 小米静止meetyou.linggan 美柚babytree 宝宝树keep keep旅行CtripWireless 携程diditaxi 滴滴taobaotravel 飞猪travelguide 马蜂窝游戏tencent1104466820 王者光荣tencent100689805 天天爱打消tencent382 QQ 斗地主跳转办法应用程序相互跳转办法以下是 uniapp 跳转利用的关上通用办法。 ...

September 22, 2023 · 2 min · jiezi

关于uniapp:uniapp项目实践总结十九版本更新和热更新实现方法

导语:当一个 APP 利用开发实现当前,就要上架利用商店,但有时候批改一些小问题或者推出一些流动,又不想频繁地提交利用商店审核,那么就能够应用利用内更新性能来进行利用的版本升级更新或热更新,上面就介绍一下实现的办法。目录筹备工作原理剖析实战演练案例展现筹备工作在/pages/index文件夹上面新建一个version.vue的组件;依照后面文章所说的页面构造,编写好预约的页面;原理剖析上面是利用更新的原理总结。 安装包版本更新通过uni.getSystemInfoSync办法的appVersion属性获取到利用以后安装包版本号;通过申请版本更新接口获取线上的安装包版本号;比拟两个安装包版本号的大小,如果统一不更新,如果不统一,线上大于以后更新版本,线上小于以后不更新;资源包版本更新通过uni.getStorage获取本地资源包版本号,如不存在,则通过uni.setStorage设置默认版本号;通过申请版本更新接口获取线上的资源包版本号;比拟两个资源包版本号的大小,如果统一不更新,如果不统一,线上大于以后更新版本,线上小于以后不更新;实战演练模板应用比拟版本号<view class="version-box"> <view class="version-item"> 版本1: <input class="version-item-ipt" type="text" placeholder="请输出版本1" v-model="versionInfo.v1" /> </view> <view class="version-item"> 版本2: <input class="version-item-ipt" type="text" placeholder="请输出版本2" v-model="versionInfo.v2" /> </view> <view class="version-item"> <button class="version-item-btn" type="primary" size="mini" @click="compareVersion('test')"> 比拟版本 </button> </view> <view class="version-item" v-show="versionInfo.text"> <text>比拟后果:</text> <text class="version-item-txt">{{ versionInfo.text }}</text> </view></view>获取线上版本<!-- #ifdef APP-PLUS --><view class="version-box"> <view class="version-item"> <button class="version-item-btn" type="primary" size="mini" @click="getVersion"> 获取版本 </button> </view> <view class="version-item"> 以后版本: {{ checkInfo.current }} </view> <view class="version-item"> 线上版本: {{ checkInfo.online }} </view> <view class="version-item"> 以后资源包版本: {{ checkInfo.currentSource }} </view> <view class="version-item"> 线上资源包版本: {{ checkInfo.onlineSource }} </view></view><!-- #endif -->检测更新<!-- #ifdef APP-PLUS --><view class="version-box"> <view class="version-item"> <button class="version-item-btn" type="primary" size="mini" @click="checkUpdate"> 检测更新 </button> </view> <view class="version-item" v-show="checkInfo.showProgress"> <progress :percent="checkInfo.currentProgress" show-info :stroke-width="8" active-color="#24afd6" /> </view></view><!-- #endif -->款式编写.version-box { padding: 10rpx; .version-item { display: flex; justify-content: flex-start; align-items: center; margin-bottom: 20rpx; padding: 0 10rpx; .version-item-ipt { margin-left: 20rpx; padding: 10rpx; border: 3rpx solid $e; font-size: 27rpx; } .version-item-btn { margin: 0; } .version-item-txt { color: $mainColor; } .uni-progress { width: 100%; } }}脚本应用定义数据比拟版本信息const versionInfo = reactive({ v1: "", // 版本1 v2: "", // 版本2 text: "", // 检测后果});检测版本信息const checkInfo = reactive({ current: "0.0.0", // 以后版本 online: "0.0.0", // 线上版本 currentSource: 0, // 以后资源包 onlineSource: 0, // 线上资源包 result: "", // 检测后果 data: null, // 在线信息 type: "", // 装置类型 showProgress: false, // 显示进度条 currentProgress: 0, // 以后进度 downloader: null, // 下载定时器});办法调用模仿版本更新数据应用之前介绍的动态服务器搁置版本更新配置文件,格局如下: ...

September 20, 2023 · 4 min · jiezi

关于uniapp:uniapp项目实践总结十八自定义多列瀑布流组件

导语:有时候展现图片等内容,会遇到图片高度不统一的状况,这时候就不能应用等高双列或多列展现了,这时候会用到瀑布流的页面布局,上面就一起探讨一下瀑布流的实现办法。目录筹备工作原理剖析实战演练案例展现筹备工作在pages/index文件夹上面新建一个waterfall.vue的组件;依照后面文章所说的页面构造,编写好预约的瀑布流案例页面;在网上找几张收费的图片素材;原理剖析次要是依据图片的高度主动比拟每列的总高度,依据uni.getImageInfo获取到图片高度,而后哪列低,就给哪列补充图片,直至图片列表循环结束。 实战演练模板应用上面就是循环列和图片。 <view class="waterfall-page"> <view class="waterfall-page-column" v-for="(item, index) in waterfall.columnList" :key="index" ref="column" > <view class="waterfall-page-item" v-for="(pItem, pIndex) in item" :key="pIndex" > <image class="waterfall-page-img" :src="pItem" mode="widthFix"></image> </view> </view></view>款式编写.waterfall-page { display: flex; align-items: flex-start; .waterfall-page-column { box-sizing: border-box; flex: 1; padding: 0 10rpx; width: 0; .waterfall-page-item { margin-bottom: 10rpx; .waterfall-page-img { display: inline-block; width: 100%; } } }}脚本应用定义数据// 瀑布流信息const waterfall = reactive({ // 图片列表 imgList: [ "/static/image/waterfall/pic-01.jpg", "/static/image/waterfall/pic-07.jpg", "/static/image/waterfall/pic-03.jpg", "/static/image/waterfall/pic-07.jpg", "/static/image/waterfall/pic-05.jpg", "/static/image/waterfall/pic-07.jpg", "/static/image/waterfall/pic-01.jpg", "/static/image/waterfall/pic-03.jpg", "/static/image/waterfall/pic-07.jpg", ], columnList: [], // 每列图片 columnHeight: [], // 每列图片高度 columnCount: 2, // 总列数});初始化数据// 初始化数据function initData() { for (var i = 0; i < waterfall.columnCount; i++) { waterfall.columnList.push([]); waterfall.columnHeight.push(0); }}计算方法// 设置瀑布流布局async function setWaterfallLayout() { for (var i = 0; i < waterfall.imgList.length; i++) { let item = waterfall.imgList[i]; try { let imgInfo = await uni.getImageInfo({ src: item, }), h = imgInfo.height; for (let j = 0; j < waterfall.columnCount - 1; j++) { let prevIndex = j, nextIndex = j + 1; if ( waterfall.columnHeight[prevIndex] <= waterfall.columnHeight[nextIndex] ) { waterfall.columnList[prevIndex].push(item); waterfall.columnHeight[prevIndex] += h; } else { waterfall.columnList[nextIndex].push(item); waterfall.columnHeight[nextIndex] += h; } } } catch (error) { console.log(error); } }}案例展现h5 端成果小程序端成果APP 端成果最初以上就是自定义多列瀑布流组件的次要内容,有不足之处,请多多斧正。 ...

September 19, 2023 · 1 min · jiezi

关于uni-app:踩坑日记uniapp相机抽帧相机被多次初始化问题

缘起:最近频繁接到应用咱们AI运行辨认插件用户的反馈,局部机型在uni中抽几帧后,就不再帧的了。开始认为又是小程序的API兼容的问题(确有机型呈现过抽帧兼容性问题),前面越来越多的反馈在原生下无问题,只有采纳uni-app计划的有问题...一、先看抽帧简略代码上面是小程序做AI静止辨认的第一步,摄像头帧数据采集的精简代码版段,大抵流程是:在摄像头初始化实现后,初始化一个CameraFrameListener、进行抽帧,并依据抽取的帧图像大小,调整Camera组件大小与帧图大小同比缩放(宽全为全屏、高自适应)。 为什么要同比缩放的起因,请见咱们的系列分享:【一步步开发AI静止小程序】四、小程序如何抽帧<template> <view class="container"> <camera id="preview" class="preview" :style="videoStyles" flash="off" :device-position="deviceKey" resolution="high" frame-size="low" @initdone="onCameraReady"> </camera> </view></template><script> export default { data() { return { deviceKey: "back", previewWidth: 480, previewHeight: 640, previewRate: 1, frameWidth: 480, frameHeight: 640 }; }, computed: { videoStyles() { const style = `width:${this.previewWidth}px;height:${this.previewHeight}px;`; return style; } }, methods: { autoFitPreview(width, height) { const sifno = uni.getSystemInfoSync(); let rate = sifno.windowWidth / width; this.previewWidth = width * rate; this.previewHeight = height * rate; this.previewRate = rate; this.frameWidth = width; this.frameHeight = height; }, initCamera(){ //避免重初始化 if(this.listener) return; const that = this; const context = wx.createCameraContext(); const listener = context.onCameraFrame((frame) => { //当帧图像大小发生变化时,从新调整摄像头代码 if(that.frameWidth != frame.width) that.autoFitPreview(frame.width, frame.height); console.log(frame.data instanceof ArrayBuffer, frame.width, frame.height) }); listener.start(); }, onCameraReady(e) { this.autoFitPreview(480, 640); this.initCamera(); }, onStart(){ this.listener.start(); }, onStop(){ this.listener.stop(); } } }</script>二、BUG复现在确认原生小程序抽帧无问题后,咱们偿试了问题复现,通过屡次测试,发现在uni下,Camera组件会屡次触发initdone事件,进一步测试后发现,只有动静扭转camera的style高、宽,便会触发从新初始化。 ...

September 19, 2023 · 1 min · jiezi

关于uniapp:uniapp项目实践总结十七实现滚动触底加载

导语:在日测的开发过程中,常常会碰到页面须要渲染大量数据的状况,这时候就须要用到滚动加载性能,上面总结一下办法。目录原理剖析实战演练案例展现原理剖析应用@scrolltolower事件来监听滚动到底部,而后加载下一页的数据。 实战演练模板页面<scroll-view :scroll-y="true" class="block-main block-two-level block-pad" @scrolltolower="scrollBottom"> <view class="scroll-ls" v-for="(item, index) in scrollInfo.list" :key="index"> {{ item }} </view> <uni-load-more v-if="scrollInfo.list.length" :status="scrollInfo.loading"></uni-load-more></scroll-view>款式编写.scroll-ls { margin-top: 20rpx; padding: 50rpx 0; text-align: center; background: $f8;}脚本应用定义数据// 滚动列表const scrollInfo = reactive({ originList: [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, ], list: [], pageInfo: { page: 1, size: 8, pages: 0, }, loading: "more",});办法调用// 滚动到底部function scrollBottom() { console.log("滚动到底部!"); if (scrollInfo.pageInfo.page < scrollInfo.pageInfo.pages) { scrollInfo.pageInfo.page++; scrollInfo.loading = "loading"; getList(); } else { scrollInfo.loading = "noMore"; }}获取列表// 获取列表function getList() { if (scrollInfo.pageInfo.page <= 1) { show.value = true; } let data = proxy.$apis.utils.splitData(scrollInfo.originList, 8); scrollInfo.pageInfo.pages = data.pages; setTimeout(() => { if (scrollInfo.pageInfo.page <= 1) { scrollInfo.list = data.list[scrollInfo.pageInfo.page - 1]; setTimeout(() => { show.value = false; }, 500); } else { scrollInfo.list = [...scrollInfo.list, ...data.list[scrollInfo.pageInfo.page - 1]]; } scrollInfo.loading = scrollInfo.pageInfo.page < scrollInfo.pageInfo.pages ? "more" : "noMore"; }, 1000);}案例展现h5 端成果小程序端成果APP 端成果最初以上就是实现滚动触底加载的次要内容,有不足之处,请多多斧正。 ...

September 18, 2023 · 1 min · jiezi

关于uniapp:uniapp项目实践总结十四封装存储和路由方法

导语:在日常 APP 开发过程中,常常要用到数据的存储、获取和删除等操作以及页面导航之间的跳转,为此,封装了一个两个简略的办法来对立调用。目录原理剖析办法实现实战演练案例展现原理剖析次要是以下 API。 uni.setStorage:保留数据到本地缓存中;uni.getStorage:获取保留的缓存数据;uni.removeStorage:移除保留的数据缓存;uni.clearStorage:清空保留的缓存数据;uni.navigate{type}:跳转页面;以下办法存于根目录下的scripts文件夹下的utils.js文件中。 办法实现接下来一一阐明如何实现数据缓存操作和路由跳转的封装。 数据缓存这里是应用一个办法,通过传入不同的类型和参数来实现。 参数如下: type: 类型,包含设置,获取,删除,清空;isSync: 是否异步;key: 键名;val: 值;// 存储数据async function storeage(options) { try { let defultOptions = { type: options.type, isSync: options.isSync || false, key: options.key, data: options.val, }; let params = { ...options, ...defultOptions }; console.log("数据缓存参数:", params); let { type, isSync, key, data } = params; let result = null, types = { set: uni[`setStorage${isSync ? "Sync" : ""}`], get: uni[`getStorage${isSync ? "Sync" : ""}`], del: uni[`removeStorage${isSync ? "Sync" : ""}`], clear: uni[`clearStorage${isSync ? "Sync" : ""}`], }; if (type == "set") { if (isSync) { result = await types[type](key, data); } else { result = await types[type]({ key, data, }); } } if (["get", "del"].includes(type)) { let param = isSync ? key : { key }; result = await types[type](param); } if (type == "clear") { result = await types[type](); } return { code: 1, data: result, }; } catch (e) { return { code: 2, data: e, }; }}路由操作这里是把罕用的路由办法装进一个办法外面了,不便调用。 ...

September 9, 2023 · 2 min · jiezi

关于uniapp:uniapp项目实践总结十二封装通用请求上传以及下载方法

导语:在日常开发过程中,前端常常要和后端进行接口联调,获取并且渲染数据到页面中,接下来就总结一下 uniapp 中获取申请、文件下载和上传的一些办法。目录原理剖析办法实现实战演练案例展现原理剖析次要是应用uni.request办法来发送申请,uni.downloadFile办法来下载文件,uni.uploadFile办法来上传文件。 以下办法存于根目录下的scripts文件夹下的http.js文件中。 办法实现接下来一一阐明如何实现数据申请、文件下载以及文件的上传的办法封装。 数据申请这个办法要接管一些参数,和现有默认参数合并,而后传给申请 API,获取数据后应用try...catch来解决胜利和失败。 这里要引入一些文件,包含申请的域名和地址,以及一些通用办法,就先省略了,接口能够到网上找一下公共的,或者本人应用 node 搭建一个繁难的接口服务器。 // 网络申请async function request(options) { let isHttp = options.url.indexOf("http") > -1; let url = isHttp ? options.url : `${urls.baseUrl}${options.url}`; let defultOptions = { url, method: options.method || "get", data: options.data || null, timeout: options.timeout || 30000, dataType: options.dataType || "json", header: options.header || { "Content-Type": "application/json", }, sslVerify: options.sslVerify || false, }; let params = { ...options, ...defultOptions }; console.log("申请参数:", params); try { let result = await uni.request(params); if (result.statusCode === 200) { return result.data; } else { return { code: 102, msg: "get_fail", data: { info: result.errMsg, }, }; } return result; } catch (e) { return { code: 101, msg: "get_fail", data: { info: e, }, }; }}文件下载这个就和申请一样,只不过 API 不一样,看一下内容。 ...

September 7, 2023 · 3 min · jiezi

关于uni-app:环信uniappdemo-升级改造计划单人多人音视频通话三

前序文章: 环信 uni-app Demo降级革新打算——Vue2迁徙到Vue3(一) 环信即时通讯SDK集成——环信 uni-app-demo 降级革新打算——整体代码重构优化(二) 概述在将声网 uni-app 音视频插件正式集成进入环信的 uni-app-demo 中,标记着本次降级革新至此根本告一段落。在第三期的降级革新中,次要工作为在 Demo 层造成一个较为容易拆分的无关音视频相干组件,力求第一:代码是否可读、第二:能够对参考源码的同学提供实例、第三:可能不便在脱离其余 IM 性能时,实现对音视频性能的复用。 同时也棘手针对 emChat 组件进行小范畴重构,解决了 uni-app 在 App 以及小程序端,软键盘弹起音讯列表不滚动以及软键盘遮挡性能栏问题。 上面我将尽可能详细描述一下本次针对音视频性能、以及音讯列表重写的心路历程。 性能背景以及目标有越来越多的用户在 IM 性能实现中未免向相似微信聊天的性能靠齐,除了日常 IM 性能中,也离不开音视频通话性能,因而须要在环信uni-app-demo中减少实现音视频通话的示例代码,可能对想要实现音视频性能的用户造成可参考的 demo 代码,以及可复用的音视频功能模块组件。 前置筹备确认实现性能范畴 接听呼叫(单聊一对一、群组多人音视频通话)且只反对 uni-app 原生端应用。浏览声网音视频 uni-app 端相干文档,相熟大抵流程以及相熟局部外围 API,跑通示例 Demo。相熟环信其余端PCWeb端、安卓、iOS端callKit 信令交互相干逻辑,确保实现 uni-app 所实现的音视频性能可能与其余端 Demo 进行互通。理解nvue组件相干语法布局款式等与vue的差别,推拉流视频容器仅反对在nvue组件中进行应用。实际见真章Tip:以下展现代码因篇幅所限,均做了不同水平的删减保留了外围逻辑展现,具体代码文末会给出源码地址。step1:在我的项目中集成音视频相干插件Agora(声网)Demo 示例中有两个插件是必须要进行集成的,别离为Native原生插件,Js插件。Agora-Demo 示例插件下载地址以及性能简介详见下方提供的链接。 Quick-start-demoAgora 原生插件地址Agora JS 插件地址具体插件的导入形式就不在本篇中具体介绍,上方插件下载地址中有提到插件导入形式,能够进行参阅。 特地留神:Agora-Uni-App JS 插件导入之后会在目录下生成一个package.json文件,这个文件会与通过 npm 导入的easemob-websdk的package.json重合,因而 Demo 中只保留了easemob-demo的package.json step2: 设计搭建 emCallKit(音视频组件)逻辑构造主体大抵构造如下: graph TDCallKit --> emCallkitemCallkit --> callKitManageemCallkit --> configemCallkit --> contantsemCallkit --> storesemCallkit --> utilsemCallkit --> index.jsCallKit --> emCallkitPagesemCallkitPages --> alertScreen.vueemCallkitPages --> inviteMembers.vueemCallkitPages --> multiCall.nvueemCallkitPages --> singleCall.nvue其中components/emCallKit次要为外围 emCallKit 逻辑层代码,callKitManage文件中次要蕴含对外公布订阅频道内工夫逻辑代码,以及频道内信令发送代码。config声网 AppId 配置。contants文件夹音视频频道内常量、stores频道内外围逻辑在此,利用 pinia 进行频道内状态治理。utils工具办法,index.jsemCallkit 入口文件,该文件内挂载信令监听初始化频道内 IM Client。 ...

September 7, 2023 · 8 min · jiezi

关于uniapp:uniapp项目实践总结四安装和使用一个插件市场的插件

这篇文章次要介绍如何装置和应用一个插件市场的插件的办法。目录查找插件装置插件应用插件查找插件关上插件市场:https://ext.dcloud.net.cn/ 例如咱们我的项目中要用到富文本渲染的内容,能够查找一下富文本; 在后果页能够选一款适宜本人的插件,我感觉mp-html这个插件挺好的; mp-html 插件地址 装置插件点击右侧装置按钮下载插件并导入 HBuilderX; 下载结束后你会发现你的根目录多出一个文件夹uni_modules,这个专门用于寄存下载的插件。 这个文件夹下的插件能够间接应用,不须要引入全局或者部分组件。 应用插件装置胜利后开始应用插件。 编写一段 js 变量并赋值;data () { return { mdStr: `<h2>Hello</h2><p style="color: #f00;font-size: 20rpx;">我是富文本!</p>`, }}应用富文本插件渲染内容;<mp-html :content="mdStr" />上面是预览图: 最初以上就是如何装置和应用一个插件市场的插件的次要内容,如有不足之处,请多多斧正。

August 31, 2023 · 1 min · jiezi

关于uni-app:IoTOSApp移动端-v010-免费开源-商用

IoTOS-App v0.1.0后端程序为 https://gitee.com/chinaiot/iotos 一款高效实用 IoTCard 治理 & 经营零碎 - 挪动端。IoTOS 挪动端;基于RuoYi-App 开发 适配国际化多语言 UI 应用 uView ,集成 J-IM(t-io 网络框架 谭聊原型外围)<div class="shields-wrapper"> <img alt="GitHub license" src="https://img.shields.io/github/license/IoTCard/iotos-app?style=flat-square&logo=github&color=616ae5"> <a target="\_blank" class="shields-wrapper-image" href='https://github.com/IoTCard/iotos-app'><img alt="GitHub stars" src="https://img.shields.io/github/stars/IoTCard/iotos-app?style=flat-square&logo=github&color=616ae5"></a> <a target="\_blank" class="shields-wrapper-image" href='https://github.com/IoTCard/iotos-app'><img alt="GitHub forks" src="https://img.shields.io/github/forks/IoTCard/iotos-app?style=flat-square&logo=github&color=616ae5"></a> <img src='https://gitee.com/chinaiot/iotos-app/badge/star.svg?theme=dark' alt='star'></img> <img src='https://gitee.com/chinaiot/iotos-app/badge/fork.svg?theme=dark' alt='fork'></img> </div> 一、 对于 IoTOS-App1.1 介绍IoTOS-App 挪动解决方案,采纳uniapp框架,一份代码多终端适配,同时反对APP、小程序、H5!实现了与IoTO、IoTOS-IM完满对接的挪动解决方案!目前曾经实现登录、国内语言切换、工作台、编辑材料、头像批改、明码批改、常见问题、对于咱们等根底性能。 配套后端代码仓库地址[IoTOS](https://gitee.com/chinaiot/iotos) 。中间件网络框架[IoTOS-IM](https://gitee.com/chinaiot/iotos-im) 。利用框架基于[uniapp](https://uniapp.dcloud.net.cn),反对小程序、H5、Android和IOS。前端组件采纳[uView](https://gitee.com/umicro/uView),全端兼容的高性能UI框架。1.2 性能介绍目前已实现性能后盾零碎告诉 用户登录后通过 IoTOS-IM 及时下发 布告 与告诉实现国际化语言二、演示安装包'apk' 目录下 [iotos-app\_v0.1.0.apk](/apk/iotos-app\_v0.1.0.apk) 【安卓版本】三、后盾演示地址开源演示地址:[http://demo.iotos.top/](http://demo.iotos.top/) 默认账号密码:iotos,iotos.top 四、分割咱们如果你想退出咱们的开源交换群、有任何 IoTOS 产品上的想法、意见或倡议,或商务上的单干需要,请扫码增加 IoTOS 我的项目作者,退出群聊: 微信 微信公众号 五、我的项目展现登录页 工作台 我的 语言切换 登录布告与告诉

July 9, 2023 · 1 min · jiezi

关于uniapp:uniappmarkdown渲染解析md转html及代码高亮

明天给大家分享一个在uniapp我的项目中用到的markdown语法解析插件uaMarkdown。 如下图:编译至H5+小程序+App端成果。 应用markdown-it和highlight.js封装组件。 // 引入markdown-it和highlight.js插件import MarkdownIt from '@/plugins/markdown-it.min.js'import hljs from '@/plugins/highlight/highlight.min.js'// import '@/plugins/highlight/github-dark.min.css'import '@/plugins/highlight/atom-one-light.css'import parseHtml from '@/plugins/html-parser.js' 初始markdown组件const markdown = MarkdownIt({ html: true, highlight: function(str, lang) { let preCode = "" try { preCode = hljs.highlightAuto(str).value } catch (err) { preCode = markdown.utils.escapeHtml(str); } // 自定义行号 const lines = preCode.split(/\n/).slice(0, -1) let html = lines.map((item, index) => { // 去掉空行 if( item == ''){ return '' } return '<li><span class="line-num" data-line="' + (index + 1) + '"></span>' + item +'</li>' }).join('') html = '<ol style="padding: 0px 30px;">' + html + '</ol>' // 代码复制 copyCode.push(str) let htmlCode = `<div class="markdown-wrap">` // #ifndef MP-WEIXIN htmlCode += `<div style="color: #aaa;text-align: right;font-size: 12px;padding:8px;">` htmlCode += `${lang}<a class="copy-btn" code-data-index="${copyCode.length - 1}" style="margin-left: 8px;">复制代码</a>` htmlCode += `</div>` // #endif htmlCode += `<pre class="hljs" style="padding:0 8px;margin-bottom:5px;overflow: auto;border-radius: 5px;"><code>${html}</code></pre>`; htmlCode += '</div>' return htmlCode }}) ...

July 2, 2023 · 1 min · jiezi

关于uniapp:uniapp自定义跨端标题头相关说明

需要咱们在自定义题目的时候,须要计算的值次要包含状态栏和标题栏的高度,具体如下: 状态栏这个比拟好计算,间接调用办法即可: ztlHeight = uni.getSystemInfoSync().statusBarHeight;标题栏对于小程序而言,思考到左边有个 胶囊 ,所以计算的时候依照如下准则: 胶囊 + 2 * (胶囊顶部到顶的间隔 - 状态栏的高)而对于H5或者APP这种没有胶囊的,间接写死一个适合的值即可。由此,最终代码如下: // #ifndef APP-PLUS || H5btlHeight = (uni.getMenuButtonBoundingClientRect().top - ztlHeight) * 2 + uni.getMenuButtonBoundingClientRect().height;// #endif// #ifdef APP-PLUS || H5btlHeight = uni.upx2px(80);// #endif

July 1, 2023 · 1 min · jiezi

关于uniapp:uniapp开发app使用wangeditor富文本编辑器进行编辑查看

wangeditor是后盾比拟罕用的一个富文本编辑器,官网链接:https://www.wangeditor.com/ 留神:兼容支流的 PC 浏览器,如 Chrome Firefox Safari Edge 等。暂不反对挪动端编辑(反对挪动端查看)。不再反对 IE 浏览器。 我的需要,可能在挪动端编辑、查看,并且可能联动后盾。我在网上找了很多挪动端的富文本编辑器,都不合乎我的需要,最初应用了webview的形式去实现wagneditor4版本。 具体实现代码如下:index.vue文件代码 <template> <view class="initiateContract"> <div class="headerTip" :style="'margin-top:' + height + 'px;'"> <div class="title"> <div class="txt">{{ contractDetails.title }}</div> <div class="status"> <u-tag v-if="contractDetails.flow_status === '1'" :text="contractDetails.flow_status_name" type="info" size="mini" plain></u-tag> <u-tag v-if="contractDetails.flow_status === '2'" :text="contractDetails.flow_status_name" type="warning" size="mini" plain></u-tag> <u-tag v-if="contractDetails.flow_status === '3'" :text="contractDetails.flow_status_name" type="warning" size="mini" plain></u-tag> <u-tag v-if="contractDetails.flow_status === '5'" :text="contractDetails.flow_status_name" type="success" size="mini" plain></u-tag> </div> </div> <div class="info">留神:合同签订区的代码英文,如company_sign、demand_sign、aunt_sign等英文代码请勿删除</div> </div> <view class="html-box"> <web-view :src="'../../../hybrid/html/viewContract/index.html?data=' + obj" @message="getMessage" ref="wv"></web-view> </view> <view class="footer" v-if="isKeyboard === false"> <view class="box"> <view class="item" v-if="contractDetails.flow_status == '1'" @click="saveContract"> <view class="btn"> <u-button type="primary" :key="1" :plain="true" text="保留合同"></u-button> </view> </view> <view class="item"> <view class="btn"> <u-button type="primary" :key="2" text="分享预览"></u-button> </view> </view> <view class="item" v-if="contractDetails.flow_status == '1'" @click="openConfirmSigning"> <view class="btn"> <u-button type="primary" :key="3" text="开始签约"></u-button> </view> </view> <view class="item" v-if="contractDetails.flow_status !== '1'"> <view class="btn"> <u-button :disabled="true" :key="4" type="success" text="签约中"></u-button> </view> </view> </view> </view> </view></template><script> import cluesHttp from '@/api/client/index.js' var wv export default { name: "electronContractEdit", data() { return { dianzi_hetong_id: '', form: { id: '0', hetong_id: '', muban_id: '', }, contractDetails: {}, contractContent: '', currentWebview: null, shareImgInfo: {}, isKeyboard: false, contentHtml: '', } }, onLoad() { const vm = this; uni.$on('to-parent', (data) => { switch( data.type ){ case '1': uni.setClipboardData({ data: this.shareImgInfo.result.tips, success: function () { uni.showToast({ icon: 'none', title: '链接已复制' }) } }); break; case '2': break; } }); // 获取上个页面传来的参数 const self = this const eventChannel = this.getOpenerEventChannel(); eventChannel.on('getInitiateContractParams', function(res) { _this.contractDetails = res _this.dianzi_hetong_id = res.id self.currentWebview = self.$scope.$getAppWebview().children()[0] self.currentWebview.evalJS(`getParams(${JSON.stringify(res)})`) }) }, onReady() { // #ifdef APP-PLUS var currentWebview = this.$scope.$getAppWebview() setTimeout(function() { wv = currentWebview.children()[0] wv.setStyle({ top: uni.getStorageSync('navbarHeight') + 84, bottom: 71, width: uni.getSystemInfoSync['screenWidth'] }) }, 100); // 键盘升起,避免遮挡编辑器内容 uni.onKeyboardHeightChange((res) => { if(this.isKeyboard === true) { this.isKeyboard = false wv.setStyle({ top: uni.getStorageSync('navbarHeight') + 84, bottom: 71, width: uni.getSystemInfoSync['screenWidth'] }) } else { this.isKeyboard = true wv.setStyle({ top: uni.getStorageSync('navbarHeight') + 84, bottom: res.height, width: uni.getSystemInfoSync['screenWidth'] }) } }) // #endif }, methods: { back() { uni.navigateBack() }, saveContract() { const self = this; self.currentWebview.evalJS("uniEvent('saveContract')"); //app向html发送数据 }, openConfirmSigning() { let params = { form: { dianzi_hetong_id: this.dianzi_hetong_id, } } uni.showModal({ title: '开始签约', content: '发动签约后,合同内容不能再次批改,同时会耗费一份合同的使用量,是否开始签约?', complete: (res) => { if(res.confirm === true) { cluesHttp.startElectronContractSigning(params).then(res => { uni.showToast({ icon: 'none', title: '签约胜利' }) }) } } }) }, getMessage(e) { if(e.detail.data[0].msg === 'saveContract') { //保留合同 let params = { form: { title: this.contractDetails.title, id: this.dianzi_hetong_id, content: e.detail.data[0].content } } cluesHttp.saveElectronContractDetail(params).then(res => { uni.showToast({ icon: 'none', title: '保留胜利' }) }) } }, }, beforeDestroy() { uni.$off('to-parent') uni.offKeyboardHeightChange() }, }</script><style lang="scss" scoped> .initiateContract { .header { display: flex; align-items: center; justify-content: space-between; padding: 10px 20px 10px; .left { display: flex; align-items: center; justify-content: flex-start; } .title { text-align: center; } .right { height: 34px; opacity: 0; text-align: right; display: flex; align-items: center; justify-content: flex-end; } .item { // width: 30%; } } .headerTip { background-color: #ffedd1; z-index: 999; padding: 10px; font-size: 12px; .title { color: #f9ae3d; display: flex; justify-content: space-between; align-items: center; padding-bottom: 10px; border-bottom: 1px solid #ececec; } .info { word-break: break-all; } } .footer { position: fixed; bottom: 0px; left: 0px; right: 0px; z-index: 9999; padding: 10px 0 20px; background: #fff; border-top: 1px solid #f3f3f3; .box { display: flex; justify-content: space-around; align-items: center; .item { .btn { margin: 0 auto; } } } } }</style>/hybrid/html/viewContract/index.html文件代码 ...

June 27, 2023 · 4 min · jiezi

关于uniapp:uniapp开发appwebview与app相互通信

一、app向webview发送数据(传参),在index.vue页面 1、通过url传参<view class="html-box"> <web-view :src="'../../../hybrid/html/viewContract/index.html?data=' + obj" @message="getMessage" ref="wv"></web-view></view>2、通过evalJS("uniEvent(`${params}`)")data() { return { currentWebview: null, obj: null } },onLoad() { const self = this; self.currentWebview = self.$scope.$getAppWebview().children()[0] //传递大量数据 self.currentWebview.evalJS(`getParams(${JSON.stringify(res)})`)},methods: { saveContract() {//app通过事件向html发送数据 const self = this; self.currentWebview.evalJS("uniEvent('saveContract')"); },}二、webview接管app发来的数据(传参),在/hybrid/html/viewContract/index.html页面 1、通过url接管参数<script type="text/javascript"> console.log('接管url参数', decodeURIComponent(location.href.split('data=')[1]))</script>2、通过evalJS定义的办法接管参数<script type="text/javascript"> let dianziHetong = null; window.getParams = (data) => { console.log("webview外部:", data) dianziHetong = data console.log(dianziHetong) } window.uniEvent = function(data) { console.log('app发来的数据', data) }</script>三、webview向app发送数据(传参),在/hybrid/html/viewContract/index.html页面 1、通过uni.postMessage()<script src="../js/uni-webview.js"></script><script type="text/javascript"> document.addEventListener('UniAppJSBridgeReady', function() { uni.postMessage({ data: { msg: 'saveContract', content: editor.txt.html() } }); })</script>四、app接管webview发来的数据(传参),在index.vue页面 ...

June 27, 2023 · 1 min · jiezi

关于uniapp:uniapp开发app使用subNVue原生子窗体

首先须要在pages.json中配置 { "path": "pages/client/initiateElectronContract/index", "style": { "navigationBarTextStyle": "white", "navigationBarTitleText": "编辑电子合同", "navigationBarBackgroundColor": "#00bdbd", "backgroundColor": "#00bdbd", "navigationStyle": "custom", "app-plus": { "subNVues": [ { "id": "initiateContractShare", // 惟一标识 "type": "popup", "path": "pages/client/initiateElectronContract/subNVue/share", "style": { "position": "absolute", "bottom": "0", "left": "0", "right": "0", "width": "100%", "height": "200px" } }, { "id": "tips", "type": "popup", "path": "pages/client/initiateElectronContract/subNVue/popup" } ] } } },popup.nvue文件 <template> <view class="page"> <view class="shares"> <view class="title">开始签约</view> <view class="content"> <text class="tip">发动签约后,合同内容不能再次批改,同时会耗费一份合同的使用量,是否开始签约?</text> </view> <view class="operation"> <view class="cancel btn" @click="cancel"> <text class="txt canceltxt">勾销</text> </view> <view class="confirm btn" @click="confirm"> <text class="txt confirmtxt">确定</text> </view> </view> <view class="close" @click="cancel"> <image src="../../../../static/close.png" style="width: 20px;height: 20px;" alt="close" /> </view> </view> </view></template><script> export default { data() { return { }; }, created() { const vm = this; // 接管信息的页面 // uni.$on('from-parent', (data) => { // uni.showToast({ // title: data.type + ', ' + data.content // }) // switch (data.type) { // case '1': // break; // case '2': // break; // case '3': // break; // // .... // } // }); }, beforeDestroy() { // 页面销毁之前 移除监听器 // uni.$off('from-parent'); }, methods: { cancel() { // 获取以后 subNVues 原生子窗体的实例。 const subNVue = uni.getCurrentSubNVue(); // 子窗体暗藏 subNVue.hide(); }, confirm() { // 获取以后 subNVues 原生子窗体的实例。 const subNVue = uni.getCurrentSubNVue(); // 向父窗体传递参数 uni.$emit('to-parent', { type: '3', content: content }); // 子窗体暗藏 // 可自定义 暗藏动画成果,工夫 // subNVue.hide(); }, } }</script><style> /* 分享弹窗 */ .shares { height: 300px; font-size: 20upx!important; padding: 10px; } .title { width: 300px; display: flex; text-align: center; justify-content: center; } .tip { font-size: 16px; padding: 20px 0 10px; } .operation { display: flex; flex-direction: row; justify-content: center; align-items: center; } .btn { display: flex; justify-content: center; align-items: center; color: #606266; padding: 10px 30px; } .txt { display: flex; justify-content: center; align-items: center; font-size: 16px; } .close { position: absolute; top: 10px; right: 10px; }</style>index.vue文件 ...

June 26, 2023 · 3 min · jiezi

关于uniapp:uniapp打包使用高德地图

应用uni.chooseLocation()下方的搜寻始终显示加载中造成这样的起因是因为没有配置key、权限等起因造成的。 一、创立高德地图key这里须要获取SHA1、须要先装置jdk工具,因为咱们须要用到SHA1、SHA256、MD5目前最新版的jdk曾经不反对MD5了,仅反对sha1,sha256两种签名。分享一下能够获取MD5的旧版本jdk 下载链接: https://pan.baidu.com/s/1DIXpmcxHmZVKlnWE6qgIxg 提取码: 7en8 复制这段内容后关上百度网盘手机App,操作更不便哦 二、创立证书1、关上电脑上的cmd命令提示符工具,先进入jdk装置目录 2、应用命令生成证书命令参考:https://ask.dcloud.net.cn/article/35777应用keytool -genkey命令生成证书:keytool -genkey -alias kytest -keyalg RSA -keysize 2048 -validity 36500 -keystore kytest.keystore kytest是证书别名,可批改为本人想设置的字符,倡议应用英文字母和数字kytest.keystore是证书文件名称,可批改为本人想设置的文件名称,也能够指定残缺文件门路36500是证书的有效期,示意100年有效期,单位天,倡议工夫设置长一点,防止证书过期 3、按提醒持续操作、证书已生成 4、查看证书应用命令:keytool -list -v -keystore test.keystore 三、高德地图中填写SHA1 四、docloud开发者后盾配置平台信息 五、uniapp打包配置高德地图key 六、uniapp打包配置权限 七、uniapp打包增加证书 八、打包胜利后就能够应用了

June 26, 2023 · 1 min · jiezi

关于uniapp:uniapp解决uview10-uupload组件使用beforeupload属性限制图片比例问题

前言因我的项目上应用了uniapp,并且应用uview1.0作为ui框架,然而应用过程中发现u-upload组件的before-upload属性有bug,顺便记录下来分享给大家,心愿可能帮忙到大家。 操作u-upload组件的before-upload属性我限度了上传图片大小,然而它还是显示上传胜利了,于是网上搜寻解决方案,并且批改了u-upload组件的源码才彻底解决。 1、批改u-upload组件源码 ...let flag = false// 执行before-upload钩子if(this.beforeUpload && typeof(this.beforeUpload) === 'function') {// 执行回调,同时传入索引和文件列表当作参数// 在微信,支付宝等环境(H5失常),会导致父组件定义的customBack()函数体中的this变成子组件的this// 通过bind()办法,绑定父组件的this,让this.customBack()的this为父组件的上下文// 因为upload组件可能会被嵌套在其余组件内,比方u-form,这时this.$parent其实为u-form的this,// 非页面的this,所以这里须要往上历遍,始终寻找到最顶端的$parent,这里用了this.$u.$parent.call(this)// 明确意思即可,无需纠结this.$u.$parent.call(this)的细节let beforeResponse = this.beforeUpload.bind(this.$u.$parent.call(this))(index, this.lists);// 判断是否返回了promiseif (!!beforeResponse && typeof beforeResponse.then === 'function') { await beforeResponse.then(res => { // promise返回胜利,不进行动作,持续上传 }).catch(err => { flag = true this.lists.splice(index, 1); this.$forceUpdate(); // 进入catch回调的话,持续下一张 return this.uploadFile(index + 1); }) // promise 或 async 返回 false,或进入 catch 回调,持续下一张;否则不进行动作,持续上传} else if(beforeResponse === false) { // 如果返回false,持续下一张图片的上传 return this.uploadFile(index + 1);} else { // 此处为返回"true"的情景,这里不写代码,就跳过此处,继续执行以后的上传逻辑}}// 查看上传地址if (!this.action) { this.showToast('请配置上传地址', true); return;}// 如果在beforeUpload中被回绝,则不往后执行if(flag) return false大家能够参考我的代码进行批改 ...

June 19, 2023 · 1 min · jiezi

关于uni-app:uniapp-h5-端在-jenkins-构建报错

h5 端在本地 dev 以及 build 都没问题,在 jenkins 上报错报错一找不到依赖包 解决:将本地 node_modules 压缩后放在服务器上相应文件解压。 这里还有另一个问题就是服务器上 node 版本太低了, 前面降级之后还是存在依赖包找不到问题 报错二cross-env: Permission denied 上面代码是我从网上截取的,不过问题都是一样。应该是由手动在服务器上增加的 node_modules引起。 解决 // 执行如下命令 在执行打包命令npm rebuild该报错信息相干文章连贯 sh: 1: cross-env: Permission deniednpm ERR! code ELIFECYCLEnpm ERR! errno 126npm ERR! @ development: `cross-env NODE_ENV=development node_modules/webpack/bin/webpack.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js`npm ERR! Exit status 126npm ERR! npm ERR! Failed at the @ development script.npm ERR! This is probably not a problem with npm. There is likely additional logging output above.npm ERR! A complete log of this run can be found in:npm ERR! /home/shanmaseen/.npm/_logs/2019-02-22T16_32_08_191Z-debug.lognpm ERR! code ELIFECYCLEnpm ERR! errno 126npm ERR! @ dev: `npm run development`npm ERR! Exit status 126npm ERR! npm ERR! Failed at the @ dev script.npm ERR! This is probably not a problem with npm. There is likely additional logging output above.npm ERR! A complete log of this run can be found in:npm ERR! /home/shanmaseen/.npm/_logs/2019-02-22T16_32_08_241Z-debug.log因为是手动增加的 node_modules 在 jenkins 上配置构建命令时 不须要再进行 install 间接执行 rebuild 在进行 build ...

June 9, 2023 · 1 min · jiezi

关于uniapp:发布了新插件基于editor创作的富文本编辑器

因为我的项目须要@谁来看的性能,所以依据官网editor二次封装了一个富文本编辑器,想着可能你们心愿本人定义编辑器按钮,所以把按钮组件提出来了,你能够自在更换,想着你可能更心愿基于api本人设计编辑器,所以把性能都给你封装到Class Edit类了,你只需new Edit,外面丰盛的api就都是你的了。 上面是插件介绍:插件地址:https://ext.dcloud.net.cn/plugin?name=lsj-edit 创作不易,若能帮到你请不要手软点亮5颗星~应用组件前必读此组件是对editor组件二次封装,减少了相似微信的@谁来看 和 相似微博的插入#话题等性能如心愿插入话题或@后光标不指向最初而指向话题前面,须要在editor组件源码退出一段代码,须要能够加Q群发你为了不便大家更换按钮控件,我将控制器按钮和编辑器画布拆分成了两个组件你齐全能够自定义编辑器,所有性能都封装到了edit类,不便各位调用,查看Edit具体文档因为比拟懒,只测试了H5和App端,其余端懒得测了,如果遇到问题能够群里Q我划重点!!!如果你心愿自定义编辑器,Edit类实例的办法和事件机制你须要理解,具体查看示例我的项目或查看Edit具体文档根本应用lsj-edit组件属性与事件绑定属性是否必填值类型默认值/返回值阐明html否String-初始化时加载的html,例如加载草稿placeholder否String开始输出编辑器提示信息maxCount否Number0最大输出字数,含空格和符号,超出最大限度时Edit返回overstep:truereadOnly否Booleanfalse编辑器是否只读styles否Object-编辑器自定义款式showImgSize否Booleantrue点击图片时显示图片大小控件showImgToolbar否Booleantrue点击图片时显示工具栏控件showImgResize否Booleantrue点击图片时显示批改尺寸控件@onReady否Function[Class] Edit编辑器初始化实现触发回调,返回edit实例对象附带的按钮edit-btns组件属性与事件绑定属性是否必填值类型默认值/返回值阐明edit是[Class] Edit-将edit对象传入和应用color否String#999999Tab栏字体默认色彩selectedColor否String#00aaffTab栏字体选中色彩fontColor否ArrayArray字体罕用色彩数组bgColor否ArrayArray字体罕用背景色数组tabs否Array#、@Tab栏是否须要显示#和@emojiList否Arraytrueemoji列表@click否FunctionObject {name,index}点击Tab栏时回调@submit否FunctionClass Edit点击Tab栏右侧提交按钮时回调VUE<lsj-edit ref="lsjEdit" placeholder="输出注释":maxCount="200"@onReady="editReady"> <template v-slot:btns="data"> <edit-btns :edit="data.edit" @click="onTabClick" @submit="save"></edit-btns> </template></lsj-edit>JSimport editBtns from '@/uni_modules/lsj-edit/components/lsj-edit/edit-btns/edit-btns.vue';export default { components:{ // 富文本基本操作按键,可自行抉择是否应用示例的按键 editBtns }, data() { return { edit: null } }, methods: { // 编辑器初始化结束,返回edit对象 editReady(edit) { // 将富文本对象寄存到以后页面,便于后续间接操作 this.edit = edit; }, // 演示----按钮组件点击事件 onTabClick({name,index}) { switch (index){ // 插入#话题# case 0: this.addLink(); break; // @某人 case 1: this.addLink2(); break; default: break; } }, // 演示公布 async save() { // 获取插入的图片列表 let imgs = await this.edit.getImages() // 判断是否容许提交 if (!this.edit.textCount && !imgs.length) { uni.showToast({ title: '请录入内容' }); } // 将所有未上传的本地图片上传到服务器并替换到编辑器 this.edit.replaceImage(async(img)=>{ // 已上传的无需再上传 // 这里没有放到edit外部去过滤,因为我感觉需不需要上传得你本人决定 // 比方插入的base64图片是否须要上传 // img.indexOf('http') = 0阐明这个图片曾经是网络地址,无需替换就间接跳过 if(img.indexOf('http') === 0) {return img;} // 上传并替换图片 /* let {data} = await uni.uploadFile({ url: 'https://www.example.com/upload', //仅为示例,非实在的接口地址 filePath: img, //本地图片 name: 'file', formData: { 'user': 'test' } }); return data; */ // 因为演示的时候没有服务器,所以间接换个网络图不便后续演示, // 理论我的项目应应用上方正文内容 return 'https://t7.baidu.com/it/u=3406125714,2513313326&fm=193&f=GIF' }).then(res=>{ console.log('替换实现,最终内容为',JSON.stringify(res)); // 示例我的项目可查看解析富文本演示 uni.navigateTo({ url: '/pages/article/article?data='+escape(res.html) }); }); }, // 插入话题示例 addLink() { this.edit.addLink({ prefix: '#', suffix: '#', name: '有问题欢送退出LSJ插件交换群', data: { name: 'QQ交换群', qqGroupChatID: '667530868', } }) }, // @某人示例 addLink2() { this.edit.addLink({ prefix: '@', name: '马冬梅', data: { userId: 10, } }) } }}Edit类实例的办法和事件机制Edit实例办法tool调用editorContext对象的事件,如撤销undo,复原redo,清空内容clear,失焦blur等调用形式:edit.tool('blur')参数阐明nameeditorContext对象的事件名称,如撤销undo,复原redo,清空内容clear等valueeditorContext事件参数,如初始化html内容edit.tool('setContents',{html}),设置文本edit.tool('insertText',{text})format批改款式,反对的值可查看editorContext format调用形式:edit.format('color','#999999')参数阐明name属性value值getContents获取编辑器内容,返回Promise.resolve调用形式:await edit.getContents()upKeyboard使光标进入编辑器并唤起键盘调用形式:edit.upKeyboard()emoji插入emoji表情调用形式:edit.emoji('')参数阐明emojiTextemoji字体addLink插入带参数的链接,如插入#话题或@谁调用形式:edit.addLink(Object)参数必填阐明prefix否在插入的内容后面增加一串字符,例如@谁suffix否在插入的内容前面增加一串字符,例如 #话题#的 #号name是插入的字符串data否链接附带的参数,用于解析后点击该链接返回getLink获取编辑器内增加的所有链接调用形式:edit.getLink()addImage通过相册/相机抉择图片并增加到编辑器中,此时图片是本地门路,在公布前应将图片上传,具体可查看示例我的项目index.vue提交事件示例;调用形式:edit.addImage(tempFilePaths)参数类型必填阐明tempFilePathsArray否不传参数时调起相册/相机抉择,传入图片数组时直接插入getImages获取编辑器内增加的所有图片调用形式:edit.getImages()replaceImage替换图片,编辑器内每个图片都会触发传入的fn,依据须要可自行替换成新的图片地址,用于将本地图片上传到服务器必须传入Function,且必须return一个图片地址调用形式:edit.replaceImage(fn)参数类型必填阐明fnFunction是return的图片地址将替换之前的图片// 提交前将所有未上传的本地图片上传到服务器并替换到编辑器edit.replaceImage(async(img)=>{ // 已上传的无需再上传 // 这里没有放到edit外部去过滤,因为我感觉需不需要替换得你本人决定 // 比方插入的base64图片是否须要上传 // img.indexOf('http') = 0阐明这个图片曾经是网络地址,就跳过 if(img.indexOf('http') === 0) {return img;} // 上传并替换图片 let {data} = await uni.uploadFile({ url: 'https://www.example.com/upload', //仅为示例,非实在的接口地址 filePath: img, //本地图片 name: 'file', formData: { 'user': 'test' } }); return data; }).then(res=>{ console.log('所有图片替换实现,返回最新的detail',JSON.stringify(res));}); 事件机制Edit为您设计了观察者模式,您能够在须要的中央注册和发送事件$fire(eventName,any)发送事件示例: ...

April 21, 2023 · 2 min · jiezi

关于uni-app:uniapp微信小程序React-Native跨端原理初探

文章内容以官网文档为根底,对uni-app的根底框架(逻辑层、渲染层)、组件、API进行简略地剖析以官网文档为根底,对微信小程序框架(逻辑层、视图层)、运行时进行简略地剖析以官网文档为根底,对React Native旧架构和新架构进行简略地剖析1. uni-app编译在web平台,将.vue文件编译为js代码。与一般的vue cli我的项目相似在微信小程序平台,编译器将.vue文件拆分生成wxml、wxss、js等代码在app平台,将.vue文件编译为js代码。进一步,如果波及uts代码: 在Android平台,将.uts文件编译为kotlin代码在iOS平台,将.uts文件编译为swift代码编译器分vue2版和vue3版 vue2版:基于webpack实现vue3版:基于Vite实现,性能更快编译器反对条件编译,即能够指定某局部代码只编译到特定的终端平台。从而将专用和个性化交融在一个工程中。 2. uni-app运行时runtime2.1 根底框架在web和小程序上,不须要uni-app提供js引擎和排版引擎,间接应用浏览器和小程序的即可。但app上须要uni-app提供App的js引擎:App-Android上,uni-app的js引擎是v8,App-iOS是jscoreApp的渲染引擎:同时提供了2套渲染引擎,.vue页面文件由webview渲染,原理与小程序雷同;.nvue页面文件由原生渲染,原理与react native雷同。开发者能够依据须要自主抉择渲染引擎。uni-app App 端内置了一个基于 weex 改良的原生渲染引擎,提供了原生渲染能力 在 App 端,如果应用 vue 页面,则应用 webview 渲染如果应用 nvue 页面(native vue 的缩写),则应用原生渲染一个 App 中能够同时应用两种页面,比方首页应用 nvue,二级页应用 vue 页面,hello uni-app 示例就是如此尽管 nvue 也能够多端编译,输入 H5 和小程序,但 nvue 的 css 写法受限,所以如果你不开发 App,那么不须要应用 nvue。 2.1.1 逻辑层和渲染层拆散在web平台,逻辑层(js)和渲染层(html、css),都运行在对立的webview里。但在小程序和app端,逻辑层和渲染层被拆散了。 拆散的外围起因是性能。过来很多开发者吐槽基于webview的app性能不佳,很大起因是js运算和界面渲染抢资源导致的卡顿。不论小程序还是app,逻辑层都独立为了独自的js引擎,渲染层依然是webview app上也反对纯原生渲染,应用.nvue文件2.1.2 逻辑层详解逻辑层是运行在一个独立的jscore里的,它不依赖于本机的webview,所以一方面它没有浏览器兼容问题,能够在Android4.4上跑es6代码,另一方面,它无奈运行window、document、navigator、localstorage等浏览器专用的js API。 jscore就是一个规范js引擎,规范js是能够失常运行的,比方if、for、各种字符串、日期解决等。js和浏览器的区别要留神辨别开来。 所谓浏览器的js引擎,就是jscore或v8的根底上新增了一批浏览器专用API,比方dom;node.js引擎,则是v8根底上补充一些电脑专用API,比方本地io;那么uni-app的App端和小程序端的js引擎,其实是在jscore上补充了一批手机端罕用的JS API,比方扫码。2.1.3 渲染层详解h5和小程序平台,以及app-vue,视图层是webview,即.vue文件都会被渲染为WebView app-nvue的视图层是基于weex革新的原生渲染视图,即.nvue文件会被革新为APP原生组件 兼容性 在iOS上,只能应用iOS提供的Webview(默认是WKWebview)。它有肯定的浏览器兼容问题,iOS版本不同,它的体现有轻微差别(个别可疏忽)。 在Android上,小程序大多自带了一个几十M的chromium webview,而App端没方法带这么大体积的三方包,因而uni-app默认应用了Android system webview,这个零碎webview追随手机不同而有差别 在Android上,App端也反对应用腾讯X5引擎,这样就对立版本,尽可能减少兼容性问题2.1.4 逻辑层和渲染层小结逻辑层: js根本没有不同手机的兼容问题(因为js引擎自带了) 渲染层: 在app-vue上应用零碎webview时会有手机浏览器的css兼容问题。此时或者不要用太新的css语法,或者集成腾讯x5引擎。 2.1.5 逻辑层和渲染层拆散的利与弊逻辑层和视图层拆散,益处是js运算不卡渲染,最简略间接的感触就是:窗体动画稳。 如果开发者应用过App,应该有概念,webview新窗体一边做进入动画,一边本身渲染,很容易卡动画。而uni-app则无需写预载代码,新窗体渲染快且动画稳固。然而两层拆散也带来一个害处,这两层相互通信,其实是有损耗的。 iOS还好,但Android低端机上,每次通信都要耗时几十毫秒。平时看不出来影响,但有几个场景体现显著: ...

April 19, 2023 · 3 min · jiezi

关于uniapp:环信-uniapp-Demo升级改造计划Vue2迁移到Vue3一

前言因为环信uni-app Demo 为晚期通过工具从微信小程序转换为的 uni-app 我的项目,通过理论的应用以及复用反馈,目前曾经不适用于以后的开发应用,因而开启了整体降级革新打算,目前一期打算将 vue2 代码进行手动转换为 vue3+vite,并剔除原我的项目中曾经无用的我的项目代码,上面记录一下降级操作,如果降级过程,对大家有所帮忙,深感荣幸~后期筹备【重要】浏览 uni-app 官网文档 Vue2 降级 Vue3 指南文档地址调研迁徙到 Vue3 中原有的 Demo 中哪些三方库或者办法将不可用(_次要 uview UI 库不反对 Vue3_)。下载并运行环信官网 uni-app 我的项目(原我的项目master分支)。Demo下载地址在 HubilderX 中创立容器我的项目(_所谓容器我的项目即为创立一个空白的 Vue3 模板,用以逐渐将 Vue2 的我的项目代码逐渐挪到此我的项目中。_)在空白我的项目中引入 uni-ui 组件,次要为了应用其组件替换原我的项目 uviewUI 组件确认降级流程以及形式(_本次降级采纳渐进式语法批改模式_),次要形式为迁徙一个组件则将批改一个组件的语法为 vue3,如该组件依赖多个组件则先切断相组件的连贯(_正文大法_),后续逐渐放开并配套批改。外围迁徙步骤第一步、导入环信 uni-app SDK原有 Vue2 版本 uni-app-demo 我的项目为本地引入 SDK 包,对于有些习惯 npm 装置导入的同学不太敌对,目前 uniSDK 曾经反对 npm 装置并导入,因而将原有本地引入 js 文件改为通过 npm 装置 SDK 并 import 导入 SDK。//第一步 关上终端执行 npm install easemob-websdk//第二步 复制原demo中的utils文件夹至空白我的项目中//第三步 找到utils文件夹中的WebIM.js 文件中的导入SDK形式改写为impot 导入 easemob-websdk/uniApp包,具体代码如下。/* 原我的项目引入SDK代码 */import websdk from '../newSDK/uniapp-sdk-4.1.2';/* 改写后的代码 */import websdk from 'easemob-websdk/uniApp/Easemob-chat';第二步、CommonJS 导入导出改写为 ESM这种改写起因两点: ...

April 18, 2023 · 7 min · jiezi

关于uni-app:uniappvue3vitetypescript架构搭建小程序

本文记录通过cli脚手架搭建uniapp+vue3+vite+typescript我的项目过程。 背景因为在开发uniapp我的项目时须要启动HbuilderX来运行我的项目,但很多时候是习惯应用vscode去开发的,而后再在小程序IDE上关上查看成果,一个我的项目须要开3个软件是很麻烦的一件事,所以看看能不能去掉HbuilderX这一环节,一看还真能够,uniapp官网曾经写出了应用cli创立我的项目的办法,我搭建了运行了一下没有问题,这里去记录一下搭建与欠缺过程。 创立我的项目在uniapp文档中有明确阐明有创立命令:传送门。我这里创立的是vite+ts的,我就间接贴代码了 vue create -p dcloudio/uni-preset-vue#alpha my-alpha-project如果碰到以下报错,须要去间接下载模板 [图片上传失败...(image-50ab5d-1680707519977)] 能够去uni-preset-vue的vite分支下间接下载zip包,解压后粘贴到本人的我的项目中。 实现后目录构造是这样 [图片上传失败...(image-c44f18-1680707519977)] 查看package.json中的script命令,运行命令启动小程序,这里我用微信小程序为例 pnpm run dev:mp-weixin启动起来后关上微信小程序IDE,抉择导入,而后抉择dist目录下dev文件夹下的mp-weixin导入,这里运行不同的环境和不同的小程序平台,打的包是不同的,所以留神辨别。 我的项目关上后初始就是这样,并且反对热更新,还是很不便的。 [图片上传失败...(image-df148a-1680707519977)] 配置eslint接下来就要配置代码查看的货色了, 首先装置eslint pnpm add eslint -D初始化eslint pnpm eslint --init我的抉择如下 [图片上传失败...(image-71753e-1680707519977)] 装置好后进入.eslintrc.js文件,在env中增加node:true解决报错 在package.json中增加lint命令 "lint": "eslint . --ext .vue,.js,.ts,.jsx,.tsx --fix"接下来运行pnpm run lint发现代码有谬误咱们一一解决。 .vue文件解析谬误,代码谬误如下[图片上传失败...(image-42a23b-1680707519977)] 解决办法 "parser": "vue-eslint-parser","parserOptions": { "ecmaVersion": "latest", "parser": "@typescript-eslint/parser", "sourceType": "module"},起因能够看这篇文章: vue3+ts+vite我的项目中应用eslint+prettier+stylelint+husky指南 - 掘金 vue文件命名不标准[图片上传失败...(image-e0325f-1680707519977)] 解决办法:在eslint中配置相应规定 "rules": { 'vue/multi-word-component-names':"off",}配置.eslintignore文件**/node_modules/***/build/***/dist/*配置prettier增加prettier pnpm add prettier -D在根目录新建.prettierrc.js module.exports = { // 一行的字符数,如果超过会进行换行,默认为80 printWidth: 100, // 一个tab代表几个空格数,默认为2 tabWidth: 2, // 是否应用tab进行缩进,默认为false,示意用空格进行缩减 useTabs: false, // 字符串是否应用单引号,默认为false,应用双引号 singleQuote: false, // 行位是否应用分号,默认为true semi: false, // 是否应用尾逗号,有三个可选值"<none|es5|all>" trailingComma: 'none', // 对象大括号间接是否有空格,默认为true,成果:{ foo: bar } bracketSpacing: true}在package.json中配置format命令 ...

April 5, 2023 · 1 min · jiezi

关于uniapp:uniapp实现文件选择上传支持App小程序H5

lsj-upload插件地址:https://ext.dcloud.net.cn/plugin?id=5459不分明应用形式可点击右侧导入示例我的项目运行残缺示例此次更新2.0与1.0应用形式略有差别,已应用1.0的同学自行斟酌是否更新到2.0版本!!!应用插件有任何问题欢送退出QQ探讨群: 群1:701468256(已满)群2:469580165(已满)群3:667530868若能帮到你请高抬贵手点亮5颗星~重要提醒组件是窗口级滚动,不要在scroll-view内应用!!组件是窗口级滚动,不要在scroll-view内应用!!组件是窗口级滚动,不要在scroll-view内应用!!控件的height高度应与slot自定义内容高度保持一致nvue窗口只能应用固定模式position=absoluteshow() 当DOM重排后在this.$nextTick内调用show(),控件定位会更加精确hide() APP端webview层级比view高,如不心愿触发点击时,应调用hide暗藏控件,反之调用show若iOS端跨域服务端同学切实配置不好,可把hybrid下html目录放到服务器去,同源则不存在跨域问题。小程序端因hybrid不能应用本地HTML,所以插件提供的是从微信音讯列表拉取文件并抉择,请知悉。file对象不是object对象,也不能转json字符串,如果你打印file那就是{},能够打印file.name和file.size。返回的path是个blob类型,仅供用于文件回显,插件已内置好上传函数,调用上传会主动提交待上传文件,若非要本人拿path去搞上传那你本人解决。应用阐明属性是否必填值类型默认值阐明width否String100%容器宽度height是String80rpx容器高度debug否Booleanfalse打印调试日志option是Object-文件上传接口相干参数instantly否Booleanfalsetrue=主动上传count否Number10附件抉择下限(个)size否Number10附件大小下限(M)wxFileType否Stringall微信小程序文件选择器格局限度(all=从所有文件抉择,video=只能抉择视频文件,image=只能抉择图片文件,file=能够抉择除了图片和视频之外的其它的文件)accept否String-文件选择器input file格局限度(局部机型不兼容,倡议应用formats)formats否String-限度容许上传的格局,空串=不限度,默认为空,多个格局以逗号隔开,例如png,jpg,pdfchildId否StringlsjUpload控件的id(仅APP无效,利用内每个控件命名一个惟一Id,不同窗口也不要同名Id)position否Stringstatic控件的定位模式(static=控件随页面滚动;absolute=控件在页面中相对定位,不随窗口内容滚动)top,left,right,bottom否[Number,String]0设置控件相对地位,position=absolute时无效@change否FunctionMap抉择文件触发,返回所有已抉择文件Map汇合@progress否FunctionObject上传过程中产生状态变动的文件对象,需通过set更新至Map汇合@uploadEnd否FunctionObject上传完结回调,返回参数与progress统一option阐明参数是否必填阐明url是上传接口地址name否上传接口文件key,默认为fileheader否上传接口申请头formData否上传接口额定参数ref调用作用办法名传入参数阐明显示控件show-控件显示状态下可触发点击暗藏控件hide-控件暗藏状态下不触发点击动静设置文件列表setFiles[Array,Map] files传入格局请与组件抉择返回格局保持一致,且name为必须属性,可查看下方演示动静更新参数setData[String] name,[any] valuename反对a.b 和 a[b],可查看下方演示移除抉择的文件clear[String] name不传参数清空所有文件,传入文件name时删除该name的文件手动上传upload[String] name不传参数默认顺次上传所有type=waiting的文件,传入文件name时不关怀type是否为waiting,独自上传指定name的文件progress返回对象字段阐明字段阐明file文件对象name文件名称size文件大小type文件上传状态:waiting(期待上传)、loading(上传中)、success(胜利) 、fail(失败)responseText上传胜利后服务端返回数据(仅type为success时存在)以下演示为vue窗口应用形式,nvue应用区别是必须传入控件相对地位如top,bottom,left,right,且position只能为absolute,如不分明可点击右侧导入示例我的项目有具体演示代码。vue:<lsj-upload ref="lsjUpload" childId="upload1" :width="width" :height="height" :option="option" :size="size" :formats="formats" :debug="debug" :instantly="instantly" @uploadEnd="onuploadEnd" @progress="onprogress" @change="onChange"> <view class="btn" :style="{width: width,height: height}">抉择附件</view></lsj-upload><view class="padding"> <view>已抉择文件列表:</view> <!-- #ifndef MP-WEIXIN --> <view v-for="(item,index) in files.values()" :key="index"> <image style="width: 100rpx;height: 100rpx;" :src="item.path" mode="widthFix"></image> <text>提醒:【path次要用于图片视频类文件回显,他用自行处理】:{{item.path}}</text> <text>{{item.name}}</text> <text style="margin-left: 10rpx;">大小:{{item.size}}</text> <text style="margin-left: 10rpx;">状态:{{item.type}}</text> <text style="margin-left: 10rpx;">进度:{{item.progress}}</text> <text style="margin-left: 10rpx;" v-if="item.responseText">服务端返回演示:{{item.responseText}}</text> <text @click="resetUpload(item.name)" v-if="item.type=='fail'" style="margin-left: 10rpx;padding: 0 10rpx;border: 1rpx solid #007AFF;">从新上传</text> <text @click="clear(item.name)" style="margin-left: 10rpx;padding: 0 10rpx;border: 1rpx solid #007AFF;">删除</text> </view> <!-- #endif --> <!-- #ifdef MP-WEIXIN --> <view v-for="(item,index) in wxFiles" :key="index"> <text>{{item.name}}</text> <text style="margin-left: 10rpx;">大小:{{item.size}}</text> <text style="margin-left: 10rpx;">状态:{{item.type}}</text> <text style="margin-left: 10rpx;">进度:{{item.progress}}</text> <view> <button @click="resetUpload(item.name)">从新上传</button> <button @click="clear(item.name)">删除</button> </view> </view> <!-- #endif --> </view>函数阐明export default { data() { return { // 上传接口参数 option: { // 上传服务器地址,须要替换为你的接口地址 url: 'http://hl.j56.com/dropbox/document/upload', // 该地址非实在门路,需替换为你我的项目本人的接口地址 // 上传附件的key name: 'file', // 依据你接口需要自定义申请头,默认不要写content-type,让浏览器自适配 header: { // 示例参数可删除 'Authorization': 'bearer eyJhbGciOiJSUzI1NiIsI', 'uid': '99', 'client': 'app', 'accountid': 'DP', }, // 依据你接口需要自定义body参数 formData: { // 'orderId': 1000 } }, // 抉择文件后是否立刻主动上传,true=抉择后立刻上传 instantly: true, // 必传宽高且宽高应与slot宽高保持一致 width: '180rpx', height: '180rpx', // 限度容许上传的格局,空串=不限度,默认为空 formats: '', // 文件上传大小限度 size: 30, // 文件数量限度 count: 2, // 文件回显列表 files: new Map(), // 微信小程序Map对象for循环不显示,所以转成一般数组,不要问为什么,我也不晓得 wxFiles: [], // 是否打印日志 debug: true, // 演示用 tabIndex: 0, list:[], } }, onReady() { setTimeout(()=>{ console.log('----演示动静更新参数-----'); this.$refs['lsjUpload'+this.tabIndex].setData('formData.orderId','动静设置的参数'); console.log('以下正文内容为-动静更新参数更多演示,放开后可查看演示成果'); // 批改option对象的name属性 // this.$refs.lsjUpload.setData('name','myFile'); // 批改option对象的formData内的属性 // this.$refs.lsjUpload.setData('formData.appid','1111'); // 替换option对象的formData // this.$refs.lsjUpload.setData('formData',{appid:'222'}); // option对象的formData新增属性 // this.$refs.lsjUpload.setData('formData.newkey','新插入到formData的属性'); // ---------演示初始化值,用于已提交后再次编辑时需带入已上传文件------- // 形式1=传入数组 // let files1 = [{name: '1.png'},{name: '2.png',}]; // 形式2=传入Map对象 // let files2 = new Map(); // files2.set('1.png',{name: '1.png'}) // 此处调用setFiles设置初始files // this.$refs.lsjUpload.setFiles(files1); // 初始化tab this.onTab(0); },2000) }, methods: { // 某文件上传完结回调(成功失败都回调) onuploadEnd(item) { console.log(`${item.name}已上传完结,上传状态=${item.type}`); // 更新以后窗口状态变动的文件 this.files.set(item.name,item); // ---可删除--演示上传实现后取服务端数据 if (item['responseText']) { console.log('演示服务器返回的字符串JSON转Object对象'); this.files.get(item.name).responseText = JSON.parse(item.responseText); } // 微信小程序Map对象for循环不显示,所以转成一般数组, // 如果你用不惯Map对象,也能够像这样转一般数组,组件应用Map次要是防止重复文件去重操作 // #ifdef MP-WEIXIN this.wxFiles = [...this.files.values()]; // #endif // 强制更新视图 this.$forceUpdate(); // ---可删除--演示判断是否所有文件均已上传胜利 let isAll = [...this.files.values()].find(item=>item.type!=='success'); if (!isAll) { console.log('已全副上传完毕'); } else { console.log(isAll.name+'待上传'); } }, // 上传进度回调 onprogress(item) { // 更新以后状态变动的文件 this.files.set(item.name,item); console.log('打印对象',JSON.stringify(this.files.get(item.name))); // 微信小程序Map对象for循环不显示,所以转成一般数组,不要问为什么,我也不晓得 // #ifdef MP-WEIXIN this.wxFiles = [...this.files.values()]; // #endif // 强制更新视图 this.$forceUpdate(); }, // 文件抉择回调 onChange(files) { console.log('以后抉择的文件列表:',JSON.stringify([...files.values()])); // 更新抉择的文件 this.files = files; // 强制更新视图 this.$forceUpdate(); // 微信小程序Map对象for循环不显示,所以转成一般数组,不要问为什么,我也不晓得 // #ifdef MP-WEIXIN this.wxFiles = [...this.files.values()]; // #endif // ---可删除--演示从新定位覆盖层控件 this.$nextTick(()=>{ console.log('演示从新定位'); this.$refs.lsjUpload0.show(); this.$refs.lsjUpload1.show(); this.$refs.lsjUpload2.show(); }); }, // 手动上传 upload() { // name=指定文件名,不指定则上传所有type等于waiting和fail的文件 this.$refs['lsjUpload'+this.tabIndex].upload(); }, // 指定上传某个文件 resetUpload(name) { this.$refs['lsjUpload'+this.tabIndex].upload(name); }, // 移除某个文件 clear(name) { // name=指定文件名,不传name默认移除所有文件 this.$refs['lsjUpload'+this.tabIndex].clear(name); }, /** * ---可删除--演示在组件上方增加新内容DOM变动 * DOM重排演示,重排后组件外部updated默认会触发show办法,若非凡状况未能触发updated也能够手动调用一次show() * 什么是DOM重排?自行百度去 */ add() { this.list.push('DOM重排测试'); }, /** * ---可删除--演示Tab切换时覆盖层是否能被点击 * APP端因为是webview,层级比view高,此时若不心愿点击触发抉择文件,须要手动调用hide() * 手动调用hide后,须要调用show()能力复原覆盖层的点击 */ onTab(tabIndex) { this.$refs.lsjUpload0.hide(); this.$refs.lsjUpload1.hide(); this.tabIndex = tabIndex; this.$nextTick(()=>{ this.$refs['lsjUpload'+this.tabIndex].show(); }) }, /** * 关上nvue窗口查看非追随窗口滚动成果 */ open() { uni.navigateTo({ url: '/pages/nvue-demo/nvue-demo' }); } }}舒适提醒文件上传如阐明表白还不够分明,不分明怎么应用可导入残缺示例我的项目运行体验和查看APP端请优先联调Android,上传胜利后再运行iOS端,如iOS返回status=0则须要后端开启容许跨域;header的Content-Type类型须要与服务端要求统一,否则收不到附件(服务端若没有明文规定则可不写,应用默认匹配)服务端不分明怎么配置跨域可加群征询,具体百度~欢送退出QQ探讨群:701468256(已满)欢送退出QQ探讨群:469580165(已满)欢送退出QQ探讨群:667530868若能帮到你还请点亮5颗小星星以作激励哈~若能帮到你还请点亮5颗小星星以作激励哈~若能帮到你还请点亮5颗小星星以作激励哈~

March 23, 2023 · 2 min · jiezi

关于uni-app:uniapp打包web项目uniapp开发vue网页应用

uni-app是什么uni-app 是一个应用 Vue.js 开发所有前端利用的框架,开发者编写一套代码,可公布到iOS、Android、Web(响应式)、以及各种小程序(微信/支付宝/百度/头条/飞书/QQ/快手/钉钉/淘宝)、快利用等多个平台。 本文内容应用 uni-app 这个平台进行开发web利用,语法是Vue.js的。 筹备1、下载 HBuilder 下载地址:htttps://hx.dcloud.net.cn/2、创立我的项目 3、开发 代码pages/index/index.vue <template> <view class="content"> <ul v-for="reslist in reslists"> <li @click="resinfo(reslist.res_id)"> <view class="res_title">{{reslist.res_title}}</view> <view class="res_category_equal"> <span class="res_category">{{reslist.res_category}}</span> <span class="res_equal">{{reslist.res_equal}}</span> </view> </li> </ul> </view></template><script> export default { data() { return { reslists:'' } }, onLoad() { uni.request({ url: 'http://demo.likeyunba.com/api/reslist/reslist.php', header: { 'header': 'application/json' }, success: (res) => { // 将获取到的后果存入reslists数组 this.reslists = res.data; } }); }, methods: { resinfo:function(res_id){ // 跳转到resinfo页面 uni.navigateTo({ url: '../resinfo/resinfo?res_id=' + res_id }); } } }</script><style> *{ padding: 0; margin: 0; } page{ background: #eee; } .content{ width: 90%; margin:30px auto; } .content ul li{ list-style: none; width: 100%; height: 80px; background: #fff; margin-bottom: 10px; border-radius: 10px; } .content ul li .res_title{ width: 100%; height: 40px; line-height: 50px; font-size: 17px; color: #333; text-indent: 15px; white-space: nowrap; text-overflow: ellipsis; overflow: hidden; word-break: break-all; } .content ul li .res_category_equal{ width: 100%; height: 40px; line-height: 30px; font-size: 14px; color: #999; text-indent: 15px; } .content ul li .res_category_equal .res_category{ float: left; } .content ul li .res_category_equal .res_equal{ float: left; } .content ul li .res_category_equal .res_creattime{ float: right; font-size: 13px; margin-right: 15px; }</style>pages/resinfo/resinfo.vue ...

March 13, 2023 · 2 min · jiezi

关于uni-app:uniapp中安卓包检查更新新版本下载下载进度条显示功能实现

需要形容如果想要做一个app的话,能够有很多种抉择计划,uni-app是其中的一个性价比高一些(坑多一些)的计划。本文记录一下,uni-app打安卓包当前,须要查看并下载更新,且显示进度条的性能。 代码在本人公司我的项目中利用,大家可放心使用。需要: 查看版本是否是最新版若不是最新版就下载远端服务器的最新的apk包下载中须要显示下载了多少了,当下载到100%的时候,主动装置接口思路剖析比方咱们有一个设置页面,在设置页面中能够去进行版本更新。 1. 查看是不是最新版当每次进入设置页面的时候,在onShow钩子中向后端发申请,获取最新版本的信息,并与以后的版本信息做比照。 比方后端提供的有这样一个:获取最新版本信息 的接口 // 接口申请,返回数据如下:{    "code": 1,    "success": true,    "data": {        "id": 123456, // 存在数据库的id        "applyName": "拼夕夕", // 版本名称        "applyVersion": "1.2.3", // 版本号        "versionDescribe": "此版本新增,是兄弟就帮忙砍一刀性能", // 版本形容 "fileSize":11566511, // 文件的总大小,计算下载进度百分比须要应用        "filePath": "http://ashuai.work:10000/appSrc/pdd.apk", // 版本的url门路,失常在浏览器地址栏中输出即间接下载了 ... // 等等    },    "msg": "操作胜利"}咱们首先拿到后端返回的这个applyVersion字段的值"1.2.3"去和当下的版本值作比照。如果远端的最新版的版本号高于当下的版本号,就阐明要更新了。否则当下的就是最新版,就不必更新。 那问题又来了,如何能拿到当下的版本呢?没关系,官网提供的有api,能够间接获取的,代码如下: plus.runtime.getProperty(plus.runtime.appid, (info) => { this.currentVersion = info.version; // 将当下版本存到currentVersion字段中去})留神这个获取版本号的操作是异步的哦,异步,异步。而后将版本号字符串"a.b.c"转换成数字进行比照即可。 形式有很多种,比方:a*100000 + b*1000 + c*1 // 当然这里须要if(this.applyVersionVal > this.currentVersionVal){ // 须要更新 this.AndroidUpdate()}else { // 以后已是最新版本 uni.showToast({ title: '以后已是最新版本', duration: 2000, icon:'none' }); return}2. 更新下载服务器远端的apk文件&进度条显示调用安卓的办法,创立一个下载工作,能拿到某一时刻下载的文件的大小,比照总大小即可失去下载进度百分比 AndroidCheckUpdate() { const _this = this uni.showModal({ title: "版本更新", content: 'APP有新版本公布,点击 立刻更新 进行最新版本下载。', confirmText: '立刻更新', cancelText: '稍后进行', success: function(res) { if (res.confirm) { _this.show = true // show变量管制一个下载进度弹框(这个UI款式本人写即可) // 创立一个下载工作,并依据后端返回的apk动态资源地址filePath进行下载 var dtask = plus.downloader.createDownload(_this.filePath, {}, function(d, status) { // 下载实现 if (status == 200) { _this.show = false // 下载实现再把下载进度弹框敞开即可 plus.runtime.install(plus.io.convertLocalFileSystemURL(d .filename), {}, {}, function(error) { uni.showToast({ title: '装置失败', duration: 1500 }); }) } else { uni.showToast({ title: '更新失败', duration: 1500 }); } }); dtask.start(); // 下载工作开始下载 // 对于进度的获取是应用定时器一直获取曾经下载的文件的大小,再比照总大小即可 let timer = setInterval(() => { let percent = (dtask.downloadedSize / this.fileSize).toFixed(2) // fileSize文件总大小,后端返回的 _this.percentVal = Math.floor(percent * 100) // 转成整数展现 if (percent >= 1) { // 留神百分比,及时革除定时器即可 clearInterval(timer) } }, 18) } else if (res.cancel) { console.log('稍后更新'); } } });}进度条应用的是u-popup组件,如下: ...

February 7, 2023 · 2 min · jiezi

关于uni-app:vue3-uniapp-vite构建流程h5简易版

看不清的话,能够按浏览器ctrl++放大查看 flowchart TB subgraph "命令行工具" scriptRun["uni dev"] end subgraph "vite-plugin-uni" uniDefaultDef["export default uni"] uniPluginNote["在此处定义了很多vite钩子"] uniPluginNote -..-> uniDefaultDef end subgraph 我的项目根目录 viteConfigDef["vite.config.ts"] viteConfigDef -."config.plugins".-> uniDefaultDef end subgraph "#64;vue/shared" shareExtendDef["shared.extend"] end subgraph vite serverCreateServerDef["server.createServer"] serverCreateServerDef -."process.env.VITE_ROOT_DIR".-> viteConfigDef end subgraph uni-app-vite subgraph dist subgraph utils subgraph easycom initEasycomDef["easycom.initEasycom"] end end subgraph cli subgraph index.js %% runBuildExc["action.runBuild"] runDevExc["action.runDev"] end runDevExc -..-> runDevDef subgraph action.js runDevDef["action.runDev"] --> shareExtendExc["shared.extend"] --> utilsInitEnvExc["utils.initEnv"] --> serverCreateServerExc["server.createServer"] --> initEasycomExc["easycom.initEasycom"] end scriptRun -..-> runDevExc shareExtendDef -..-> shareExtendExc utilsInitEnvDef -..-> utilsInitEnvExc serverCreateServerDef -..-> serverCreateServerExc initEasycomDef -..-> initEasycomExc subgraph utils.js utilsInitEnvDef["utils.initEnv"] end end end end ...

January 17, 2023 · 1 min · jiezi

关于uni-app:uniapp运行微信小程序无法启动小程序Enable-IDE-Service-yN-27D27C

uni-app运行微信小程序无奈启动小程序异样信息如下Enable IDE Service (y/N) [27D[27C(如下图) 解决形式手动开启微信小程序开发工具 -> 设置 -> 平安 -> 关上服务端口 参考资料uni-app官网文档中运行uni-app中第3点配置,其中留神项enable ide service (y/n) [27d[27c

December 27, 2022 · 1 min · jiezi

关于uniapp:uniapp-在微信小程序中图片宽度显示问题

在uniapp中,如果你的富文本图片显示宽度不失常,你能够通过设置图片的宽高属性来解决这个问题。例如,你能够在富文本中增加以下代码来设置图片的宽度为100%: <img src="your_image_url" style="width: 100%" /> 另外,如果你想设置图片的高度,你能够增加以下代码: <img src="your_image_url" style="height: 100px" /> 当然,能够实现一个 filter 来主动对图片宽度进行解决。 export default { // ... filters: { formatRichHtml(html) { if (!html) { return html; } //管制小程序中图片大小 let newContent = html.replace(/<img[^>]*>/gi, function (match, capture) { console.log(match.search(/style=/gi)); if (match.search(/style=/gi) === -1) { match = match.replace(/\<img/gi, '<img style=""'); } return match; }); newContent = newContent.replace(/style="/gi, '$& max-width:100% !important; '); newContent = newContent.replace(/<br[^>]*\/>/gi, ''); return newContent; } } // ...}在调用时只须要如下调用 export default { // ... filters: { formatRichHtml(html) { if (!html) { return html; } //管制小程序中图片大小 let newContent = html.replace(/<img[^>]*>/gi, function (match, capture) { console.log(match.search(/style=/gi)); if (match.search(/style=/gi) === -1) { match = match.replace(/\<img/gi, '<img style=""'); } return match; }); newContent = newContent.replace(/style="/gi, '$& max-width:100% !important; '); newContent = newContent.replace(/<br[^>]*\/>/gi, ''); return newContent; } } // ...}在调用时只须要如下调用即可 ...

December 27, 2022 · 1 min · jiezi

关于uniapp:uniapp-开发输入键盘几种-confirmtype-状态

在 uniapp 中,能够应用 confirm-type 属性来管制 input 组件的确定键的款式。如果要将确定键显示为搜寻按钮,能够将 confirm-type 设置为 search,代码示例如下: <input type="text" confirm-type="search" placeholder="请输出关键字" />须要留神的是,在不同平台上,这个属性的体现可能不同。例如,在安卓平台上,会将确定键显示为搜寻按钮,而在 iOS 平台上,可能会显示为实现按钮。如果您心愿在不同平台上看到雷同的成果,能够通过自定义款式来实现。 在 uniapp 中,confirm-type 属性能够设置为以下几种值: send:将确定键显示为发送按钮。search:将确定键显示为搜寻按钮。next:将确定键显示为下一步按钮。go:将确定键显示为返回按钮。done:将确定键显示为实现按钮。不同平台对这些值的反对状况可能不同。例如,在安卓平台上,将 confirm-type 设置为 send 可能会没有任何成果,而在 iOS 平台上,会将确定键显示为发送按钮。

December 15, 2022 · 1 min · jiezi

关于uniapp:uniapp-微信小程序开启发送好友和朋友圈

引言最近在开发微信小程序的过程中,须要在页面开启分享性能——分享给好友或者是朋友圈的性能。 找了一圈的uniapp文档,决定在这里记录一下,分享给有缘人应用。成果 在微信小程序中,这个默认是敞开状态的如下: 开启的正确形式 onShareAppMessage(res) { if (res.from === 'button') { console.log(res.target) } return { title: '分享进来的题目', path: `你以后的页面路由`, } }, onShareTimeline(res) { return { title: '分享进来的题目', path: `你以后的页面路由`, desc: '形容', } }应用形式很简略,只须要和生命周期钩子函数同级应用就行: 当然,如果您须要体验该性能,能够微信关上小程序搜寻 【太极开发者平台即可】

October 27, 2022 · 1 min · jiezi

关于uni-app:小程序uniapp接媳妇文本

1.uniapp插件市场下载mp-html。 链接:https://files.cnblogs.com/fil... 2.放到components目录下。 3.引入 import mpHtml from '@/components/mp-html/mp-html' components: { mpHtml },4.应用 <mp-html :content="content" />

October 17, 2022 · 1 min · jiezi

关于uni-app:融云-uniapp-原生插件生态丰富高效集成

uni-app 作为业内最风靡的利用框架之一,撑持着 12 亿沉闷手机用户的宏大生态。关注【融云寰球互联网通信云】理解更多 这个框架因在小程序端的舒爽构建体验和丰盛的开发生态而备受开发者青眼,同时可用来编译 App、Web 端利用,尤其是对于一些轻量级利用来说,是疾速实现多端笼罩产品的优选。融云为 uni-app 生态提供了丰盛的原生插件,蕴含单群聊、超级群,一对一、一对多音视频通话,低提早直播、视频会议等多种场景能力,并提供美颜、推送等 X 通信周边服务,助力开发者方便快捷地实现相干利用。 uni-app 缘何大火?uni-app 所属公司 DCloud 领有 900 万开发者、数百万利用、12 亿手机端月活用户,以及数千款 uni-app 插件。 开发一次,多端笼罩在 uni-app 开发一套源码,能够同时运行到 iOS、Android、Web、微信小程序、支付宝小程序、百度小程序、头条小程序、QQ 小程序、钉钉小程序等多端。在不就义平台特色的同时,实现对平台专有能力的优雅调用,做到了海纳百川、各取所长。 丰富多彩的周边生态DCloud 创立了凋谢、兼容的插件零碎,品种繁多,数量宏大,可满足开发者各种开发需要,包含前端组件、JS SDK、页面模版、我的项目模版、原生插件等数千款。 学习老本和开发成本低uni-app 开发以通用前端技术栈为根底,采纳 Vue 框架 JavaScript 语言,对于前端开发者来说简直没有额定的学习老本。不须要转换开发思维、不须要更改开发习惯即可实现跨端开发,疾速交付我的项目。 融云 uni-app 原生插件及跨平台 SDK融云为 uni-app 生态提供了丰盛的原生插件,开发者无需配置原生我的项目即可开发原生 App,助力开发者打造更好的 App 体验。 RCUniIMV2基于原生 IM SDK 封装成的 uni-app 原生插件,反对 Android 和 iOS 平台,接口易用、功能丰富、集成简略。 RCUniPush基于 Android 厂商推送 SDK 封装成的 uni-app 原生插件,配合 RCUniIMV2 插件,可实现融云音讯在 Android 端和 iOS 的推送告诉能力。安卓厂商推送蕴含华为、小米、OPPO、vivo、魅族。开发者只需在 uni-app 层设置推送参数,即可疾速实现融云音讯离线推送性能。 ...

October 11, 2022 · 2 min · jiezi

关于uniapp:可视化uniapp整合thinkphp6-EasyWeChat实现微信小程序支付

可视化uniapp整合thinkphp6 EasyWeChat实现微信小程序、公众事件领取,调用tp6接口返回微信相干下单参数。 开源地址:https://gitee.com/diygw/diygw... //小程序领取相干办法var Pay = { async pay(param){ let page = getApp().globalData.currentPage let session = page.$session; if(!session.getToken() || !session.getUser().openid){ //如果参数自带openid跳过验证 if(!param.openid){ page.showToast('请先登录') return; } } if(!param.total){ page.showToast('请配置价格参数total') return; } let data = await page.$http.post(param.url||'/api/wepay/order',{ total:param.total, body:param.body, openid:param.openid||session.getUser().openid, },{},'json') if(data.code!=200){ page.showToast(data.msg) return; } if(this[param.paytype]){ this[param.paytype](Object.assign(data,param)) }else{ page.showToast('请应用微信关上') return; } }, //微信领取 weixin(params = {}) { uni.requestPayment({ provider: 'wxpay', timeStamp: params.data.timeStamp,// 领取签名工夫戳,留神微信jssdk中的所有应用timestamp字段均为小写。但最新版的领取后盾生成签名应用的timeStamp字段名需大写其中的S字符 nonceStr: params.data.nonceStr,// 领取签名随机串,不长于 32 位 package: params.data.package,// 对立领取接口返回的prepay_id参数值,提交格局如:prepay_id=\*\*\*) signType: params.data.signType,// 签名形式,默认为'SHA1',应用新版领取需传入'MD5' paySign: params.data.paySign,// 领取签名 success: res => { if(typeof params.success=='function'){ params.success(res) }else{ console.log('配置领取回调胜利办法') } }, fail: res => { if(typeof params.fail=='function'){ params.fail(res) }else{ console.log('配置领取回调失败办法') } } }) }}export default Pay<?phpnamespace app\api\controller;use app\BaseController;use app\common\model\DiyOrderModel;use app\common\model\DiyUserModel;use EasyWeChat\Factory;use think\App;use think\facade\Log;/* * 领取 */class WepayController extends BaseController{ //判断是否全副不须要登录 public $notNeedLoginAll = false; public $isModel = false; //判断不须要登录的办法 public $notNeedLogin = ['notify']; public $wepayApp; /** * 构造方法 * @access public * @param App $app 利用对象 */ public function __construct(App $app) { parent::__construct($app); $paymentConfig = config('wechat.payment'); $this->wepayApp = Factory::payment($paymentConfig); } /** * 用户下单 * @return \think\response\Json * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException * @throws \GuzzleHttp\Exception\GuzzleException * @throws \think\exception\DbException */ public function order(){ $userModel = DiyUserModel::where(['id'=>$this->request->userId])->find(); if(!$userModel){ return $this->error('请先登录'.$this->request->userId); } $user = $userModel->toArray(); if(empty($user['openid'])){ return $this->error('请先登录'); } // 生成订单信息 $data = $this->request->param(); $data['orderNo'] = getOrderNo(); $data['status'] = 0; $data['payStatus'] = 0; $data['openid'] = $user['openid']; $data['userId'] = $this->request->userId; $model = new DiyOrderModel(); $data = $model->add($data); $notify_url = url('api/wepay/notify') ->suffix('html') ->domain($this->request->domain())->build(); //调起微信领取 $payData = [ 'body' => $data['body'], 'out_trade_no' =>$data['orderNo'] , 'total_fee' =>(float)($data['total']*100), 'notify_url' => $notify_url, // 领取后果告诉网址,如果不设置则会应用配置里的默认地址 'trade_type' => 'JSAPI', // 请对应换成你的领取形式对应的值类型 'openid' => $data['openid'], ]; $result = $this->wepayApp->order->unify($payData); if ($result['return_code'] === 'SUCCESS') { $jssdk = $this->wepayApp->jssdk; $config = $jssdk->bridgeConfig($result['prepay_id'],false); // 返回数组 return $this->successData($config); }else{ return $this->errorData($result); } } /** * 领取回调 * @return mixed */ public function notify(){ $response = $this->wepayApp->handlePaidNotify(function ($message,$error){ $order = DiyOrderModel::where(['order_no'=>$message['out_trade_no']])->find(); if (!$order || $order['status'] == '1') return true; if ($message['return_code'] === 'SUCCESS') { if ($message['result_code'] === 'SUCCESS') { $order['status'] = '1'; } elseif ($message['result_code'] === 'FAIL') { $order['status'] = '2'; } } else { return $error('通信失败,请稍后再告诉我'); } if ($order->save()){ return true; } return false; }); $send = $response->send(); return $send; }}<?phpnamespace app\api\controller;use app\BaseController;use app\common\model\DiyUserModel;use EasyWeChat\Factory;use Overtrue\Socialite\AuthorizeFailedException;use thans\jwt\facade\JWTAuth;use think\App;/* * 微信小程序 */class WexcxController extends BaseController{ //判断是否全副不须要登录 public $notNeedLoginAll = true; public $isModel = false; //判断不须要登录的办法 public $notNeedLogin = []; public $wexcxApp = null; /** * 构造方法 * @access public * @param App $app 利用对象 */ public function __construct(App $app) { parent::__construct($app); $minConfig = config('wechat.mini_program'); $this->wexcxApp = Factory::miniProgram($minConfig); } /** * 获取用户登录信息 * @return \think\response\Json * @throws \think\Exception * @throws \think\db\exception\DataNotFoundException * @throws \think\db\exception\DbException * @throws \think\db\exception\ModelNotFoundException */ public function login(){ $userInfo = json_decode($this->request->post('userInfo'),true); $code = $this->request->post('code'); $auth = $this->wexcxApp->auth; $opendata = $auth->session($code); if(isset($opendata['openid'])){ $openid = $opendata['openid']; $type = 'weixcx'; $model = new DiyUserModel(); //查找获取微信小程序用户 $user = $model->where('openid',$openid)->where('type',$type)->find(); $data['openid'] = $openid; $data['type'] = $type; $data['nickname'] = $userInfo['nickName']; $data['avatar'] = $userInfo['avatarUrl']; $data['country'] = $userInfo['country']; $data['province'] = $userInfo['province']; $data['gender'] = $userInfo['gender']; if($user){ $userId = $user->toArray()['id']; $data['id'] = $userId; $user->edit($data); }else{ $model = new DiyUserModel(); $model->add($data); $userId = $data['id']; } $token = "bearer".JWTAuth::builder(['uid' => $userId]); $opendata['token'] = $token; $data = array_merge($data,$opendata); return $this->successData($data); }else{ return $this->errorData($opendata,'登录失败'); } } /** * 服务端签名,获取操作权限 */ public function getSignPackage(){ $url = $this->request->param('url'); try { return $this->successData($this->wexcxApp->jssdk->buildConfig([ 'checkJsApi', 'onMenuShareTimeline', 'onMenuShareAppMessage', 'onMenuShareQQ', 'onMenuShareWeibo', 'hideMenuItems', 'showMenuItems', 'hideAllNonBaseMenuItem', 'showAllNonBaseMenuItem', 'translateVoice', 'startRecord', 'stopRecord', 'onRecordEnd', 'playVoice', 'pauseVoice', 'stopVoice', 'uploadVoice', 'downloadVoice', 'chooseImage', 'previewImage', 'uploadImage', 'downloadImage', 'getNetworkType', 'openLocation', 'getLocation', 'hideOptionMenu', 'showOptionMenu', 'closeWindow', 'scanQRCode', 'chooseWXPay', 'openProductSpecificView', 'addCard', 'chooseCard', 'openCard' ],false,false,false,['wx-open-launch-weapp'],'https://php.diygw.com/pay/index.html')); }catch (Throwable | Exception $e){ return $this->error("获取用户失败,请重试"); } }}

October 10, 2022 · 3 min · jiezi

关于uni-app:ShareSDK-Uniapp-插件

筹备下载开发工具HBuilderX 筹备uniapp我的项目如果没有曾经创立好的我的项目,能够自行创立新的我的项目 之后抉择新建uni-app我的项目。关上HBuildX的文件->导入->本地我的项目导入创立的文件夹->创立。 插件集成本地插件集成[下载离线插件](https://ext.dcloud.net.cn/plu...) 将下载好的插件放在我的项目的nativeplugins文件夹中。(若没有则创立此目录) 目录构造如下: 之后在uniapp的“manifest.json”中抉择“app原生插件配置”,点击抉择本地插件,如图: 云端插件集成在uniapp的“manifest.json”中抉择“app原生插件配置”,点击抉择云端插件,如图: 留神:本地插件和云端插件能够任选一样配置,区别在于本地插件寄存到工程nativeplugins目录下的原生插件,实用于未公布到插件市场的公有原生插件进行云打包,云端插件是曾经在插件市场购买或绑定试用的插件,无需下载插件到工程中,云打包时会间接合并打包原生插件到App中。不过咱们提供的插件是收费的哦!iOS平台相干配置配置初始化信息和URL SCheme在“app原生插件配置”中增加MobTech平台注册的MOBAppKey和MOBAppSecret,如何失去这2个参数,请参考这个流程。以及微信、QQ、新浪、Facebook、Twitter等平台的注册平台信息。各平台注册地址,请点击 这里 。 并在“app罕用其余设置”中的“iOS设置”中填写URL Scheme,以及白名单等信息,具体每个平台如何配置,请参考 原生文档配置Xcode我的项目这块。 配置平台的Universal Link微信以及qq要求用户在新版SDK中填写universalLink,所以须要在利用中配置通用链接,须要在manifest.json的源码视图添"app-plus"->"distribute"->"ios"下,增加如下代码: Android平台相干配置留神:安卓端只反对本地依赖形式导入 增加依赖 在uniapp插件市场找到ShareSDK插件,点击下载for离线打包 2.解压到uni-app利用的nativeplugins目录中具体参考:https://ask.dcloud.net.cn/art...,实现后如下图: 配置分享平台信息配置ShareSDK.xml文件在我的项目中mob-sharesdk/android下新建assets目录,在新创建的assets目录中创立名为ShareSDK.xml的文件,如下图: ShareSDK.xml文件内容示例为: 其中各平台的appkey等信息仅为demo示例,正式应用请替换为本人在分享受权平台申请的<?xml version="1.0" encoding="utf-8"?><DevInfor><SinaWeibo Id="1" SortId="59" AppKey="568898243" AppSecret="38a4f8204cc784f81f9f0daaf31e02e3" ShareByAppClient="true" Enable="true" RedirectUrl="http://www.sharesdk.cn" /><TencentWeibo Id="2" SortId="2" AppKey="801307650" AppSecret="ae36f4ee3946e1cbb98d6965b0b2ff5c" Enable="true" RedirectUri="http://sharesdk.cn" /><Douban Id="16" SortId="16" Enable="true" ApiKey="031a96a3aa8b28af094fc3eaffa17a0d" Secret="2e675e730571b75d" RedirectUri="http://mob.com" /><QZone Id="3" SortId="3" AppId="100371282" AppKey="aed9b0303e3ed1e27bae87c33761161d" ShareByAppClient="true" BypassApproval="false" Enable="true" /><Renren Enable="false" /><KaiXin Enable="false" /><Facebook Id="8" SortId="8" ShareByAppClient="true" Enable="true" ConsumerKey="2796236850615578" ConsumerSecret="7d353609b517b23a80dcb057995ef30c" RedirectUrl="https://mob.com" /><Twitter Id="9" SortId="9" ShareByAppClient="true" Enable="true" ConsumerKey="viOnkeLpHBKs6KXV7MPpeGyzE" ConsumerSecret="NJEglQUy2rqZ9Io9FcAU9p17omFqbORknUpRrCDOK46aAbIiey" CallbackUrl="http://mob.com" /><Evernote Id="19" SortId="19" HostType="sandbox" ShareByAppClient="true" Enable="true" ConsumerKey="sharesdk-7807" ConsumerSecret="d05bf86993836004" /><FourSquare Enable="false" /><GooglePlus Id="21" SortId="21" OfficialVersion="default" ShareByAppClient="true" Enable="true" ClientID="236300675100-am5pm8km7md1memjevq8rl9pg5c4s4b8.apps.googleusercontent.com" RedirectUrl="http://localhost" /><Instagram Id="28" SortId="28" ShareByAppClient="true" Enable="true" ClientId="ff68e3216b4f4f989121aa1c2962d058" ClientSecret="1b2e82f110264869b3505c3fe34e31a1" RedirectUri="http://sharesdk.cn" /><LinkedIn Id="20" SortId="20" ShareByAppClient="true" Enable="true" ApiKey="ejo5ibkye3vo" SecretKey="cC7B2jpxITqPLZ5M" RedirectUrl="http://sharesdk.cn" /><Tumblr Enable="false" /><Email Id="12" SortId="12" Enable="true" /><ShortMessage Id="13" SortId="13" Enable="true" /><Wechat Id="4" SortId="4" AppId="wx4868b35061f87885" AppSecret="64020361b8ec4c99936c0e3999a9f249" WithShareTicket="true" BypassApproval="false" Enable="true" /><WechatMoments Id="5" SortId="5" AppId="wx4868b35061f87885" AppSecret="64020361b8ec4c99936c0e3999a9f249" BypassApproval="false" Enable="true" /><QQ Id="7" SortId="7" AppId="100371282" AppKey="aed9b0303e3ed1e27bae87c33761161d" ShareByAppClient="true" BypassApproval="false" Enable="true" /><Instapaper Id="38" SortId="38" Enable="true" ConsumerKey="4rDJORmcOcSAZL1YpqGHRI605xUvrLbOhkJ07yO0wWrYrc61FA" ConsumerSecret="GNr1GespOQbrm8nvd7rlUsyRQsIo3boIbMguAl9gfpdL0aKZWe" /><Pocket Id="37" SortId="37" Enable="true" ConsumerKey="32741-389c565043c49947ba7edf05" /><YouDao Id="17" SortId="17" HostType="product" Enable="true" ConsumerKey="dcde25dca105bcc36884ed4534dab940" ConsumerSecret="d98217b4020e7f1874263795f44838fe" RedirectUri="http://www.sharesdk.cn/" /><Pinterest Enable="false" /><Flickr Enable="false" /><Dropbox Enable="false" /><VKontakte Id="27" SortId="27" ShareByAppClient="true" Enable="true" ApplicationId="3921561" /><WechatFavorite Id="6" SortId="6" AppId="wx4868b35061f87885" AppSecret="64020361b8ec4c99936c0e3999a9f249" BypassApproval="false" Enable="true" /><Yixin Enable="false" /><YixinMoments Enable="false" /><Mingdao Enable="false" /><Line Id="32" SortId="32" callbackscheme="lineauth" Enable="true" ChannelID="1639219273" ChannelSecret="58faad55ffce8bf8f63b59fe6fb702ae" RedirectUri="https://www.mob.com/" /><WhatsApp Id="35" SortId="35" Enable="true" /><KakaoTalk Id="33" SortId="33" AppKey="48d3f524e4a636b08d81b3ceb50f1003" Enable="true" /><KakaoStory Id="34" SortId="34" AppKey="48d3f524e4a636b08d81b3ceb50f1003" Enable="true" /><FacebookMessenger Id="39" SortId="39" AppId="107704292745179" OfficialVersion="default" Enable="true" /><Alipay Id="50" SortId="50" AppId="2015072400185895" Enable="true" /><AlipayMoments Id="51" SortId="51" AppId="2015072400185895" Enable="true" /><Dingding Id="52" SortId="52" AppId="dingoanxyrpiscaovl4qlw" BypassApproval="false" Enable="true" /><Youtube Id="53" SortId="53" AppSecret="AIzaSyAO06g-0TDpHcsXXO918a7QE3Zdct2bB5E" ShareByAppClient="true" Enable="true" ClientID="370141748022-bicrnsjfiije93bvdt63dh3728m4shas.apps.googleusercontent.com" RedirectUrl="http://localhost" /><Meipai Id="54" SortId="54" AppSecret="y9ym6rrjjijtkt23qtsc" ShareByAppClient="true" Enable="true" ClientID="1089867596" /><Telegram Id="47" SortId="47" AppKey="782826033" Enable="true" RedirectUrl="http://www.mob.com" /><Cmcc Id="55" SortId="55" AppId="300011860247" AppKey="2D464D8BFCE73A44B4F9DF95A2FDBE1C" /><Reddit Id="56" SortId="56" AppKey="MExDxPuTCtFiRw" RedirectUrl="http://www.sharesdk.cn" /><Telecom Id="57" SortId="57" AppKey="8148612606" AppSecret="mCltrhUqwshFa86egDTs0491ibaAulKA" Enable="true" RedirectUrl="http://www.sharesdk.cn" /><Accountkit Id="58" SortId="58" AppKey="579465512480462" AppSecret="8a6383652dd9f23fb0994f03d350d0ca" Enable="true" RedirectUrl="http://www.sharesdk.cn/" /><Douyin Id="59" SortId="1" AppKey="aw9ivykfjvi4hpwo" AppSecret="42b4caa6bda60bd49f05f06d0a4956e1" Enable="true" /><Wework Id="60" SortId="60" AppKey="wwa21eaecf93f0e3ba" AppSecret="dW7e27P7Hc8NiYdRxnbTeOLgfI1ugR72e-PM8uusq2s" AgentId="1000012" Schema="wwautha21eaecf93f0e3ba000012" /><HWAccount Enable="false" /><Oasis Enable="false" /><XMAccount Enable="false" /><SnapChat Enable="false" /><Kuaishou Id="68" SortId="68" Enable="true" /><Littleredbook Enable="false" /><Watermelonvideo Enable="false" /><Tiktok Enable="false" /></DevInfor>配置manifest.json抉择manifest.json文件中的App原生插件配置,增加本地插件或云端插件mob-sharesdk,别离填写Mob-AppKey、Mob-AppSecret、QQ-AppId、Facebook-AppKey、Line-CallBackScheme,其中Mob-AppKey、Mob-AppSecret为必填,其余三项可按需填写。 ...

September 22, 2022 · 4 min · jiezi

关于uni-app:uniapp浙政钉H5项目埋点

稳定性监控留神:间接把上面的代码复制到本人我的项目的public/index.html下<script src='https://wpk-gate.zjzwfw.gov.cn/static/wpk-jssdk.1.0.2/wpkReporter.js' crossorigin='true'></script><script>try { const config = { bid: '须要自行替换', signkey: '须要自行替换', gateway: 'https://px-emas.dg-work.cn'专有云利用,参数在部署时请替换为正确的专有云地址https://wpk-gate.zjzwfw.gov.cn};const wpk = new wpkReporter(config);wpk.installAll();window._wpk = wpk;} catch (err) { console.error('WpkReporter init fail', err);}</script> 流量剖析 (1)通用采集SDK 留神:同上,间接把上面的代码复制到本人我的项目的public/index.html下,跟在稳定性监控代码上面<script> (function(w, d, s, q, i) { w[q] = w[q] || []; var f = d.getElementsByTagName(s)[0],j = d.createElement(s); j.async = true; j.id = 'beacon-aplus'; j.src = 'https://alidt.alicdn.com/alilog/mlog/aplus_cloud.js'; f.parentNode.insertBefore(j, f); })(window, document, 'script', 'aplus_queue'); aplus_queue.push({ action: 'aplus.setMetaInfo', //专有云利用,第二个参数在部署时请替换为正确的专有云地址alog.zjzwfw.gov.cn arguments: ['aplus-rhost-v', 'alog.dg-work.cn'] }); aplus_queue.push({ action: 'aplus.setMetaInfo', //专有云利用,第二个参数在部署时请替换为正确的专有云地址alog.zjzwfw.gov.cn arguments: ['aplus-rhost-g', 'alog.dg-work.cn'] }); var u = navigator.userAgent var isAndroid = u.indexOf('Android') > -1 var isIOS = !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/) aplus_queue.push({ action: 'aplus.setMetaInfo', arguments: ['appId', isAndroid ? '28302650' : isIOS ? '28328447' : '47130293'] });</script> ...

September 8, 2022 · 2 min · jiezi

关于uni-app:云对象-重新定义前后端交互

背景从2000年开始,xml作为数据交换格局开始风行,服务器拼接xml接口,客户端js获取xml内容,动静批改页面。 几年后,数据量更小的json代替了xml。 挪动互联网到来后,因为客户端决裂,加剧了接口的泛滥。 一转眼,接口曾经玩了20年了。其余技术飞速发展,而前后端交互却始终是接口,没有什么翻新。 js曾经有了import、export,为什么调用后端接口,不能像调用一个前端模块一样呢? serverless,让这所有开始了变动。 亚马逊lambda提出了云函数的概念,不再应用restful的url,但依然是基于json替换前后端数据。 uniCloud最后也以反对云函数为开始,但咱们发现这仍不够优雅、简洁、直观、对立。 从HBuilderX 3.4 开始,uniCloud推出了“云对象”,让调用云端服务,真正变成像调用前端模块一样简略。 什么是云对象云对象:服务器编写API,客户端调用API,不再开发传输json的接口。思路更清晰、代码更精简。 比方服务端编写一个云对象news,该对象导出若干办法:add()、getList()、getDetailById()、softDel()、changeContent()、allowPublic()、addComment()、getComments()...等办法。 客户端的js则能够间接import这个news云对象,而后间接调用add等办法。 服务器示例代码如下: HBuilderX中在uniCloud/cloudfunctions目录新建云函数/云对象,抉择类型为云对象,起名为news。关上云对象入口index.obj.js,增加一个add办法。 // 云对象名:newsmodule.exports = { add(title, content) { title = title.trim() content = content.trim() if(!title || !content) { return { errCode: 'INVALID_NEWS', errMsg: '题目或内容不可为空' } } // ...其余逻辑 return { errCode: 0, errMsg: '创立胜利' } }}而后在客户端的js中,import这个news对象,调用它的add办法。 const news = uniCloud.importObject('news') //第一步导入云对象async function add () { try { const res = await news.add('title demo', 'content demo') //导入云对象后就能够间接调用该对象的办法了,留神应用异步await uni.showToast({ title: '创立胜利' }) } catch (e) { // 合乎uniCloud响应体标准 https://uniapp.dcloud.net.cn/uniCloud/cf-functions?id=resformat,主动抛出此谬误 }}能够看到云对象的代码十分清晰,代码行数也只有27行。 ...

September 8, 2022 · 2 min · jiezi

关于uniapp:uniapp中使用canvas实现二维码分享海报

案例1实现背景: 海报的尺寸依据图片大小来的,宽度百分百,高度同比例缩放,图上笼罩二维码如果没有设置海报图片,应用别的图片,在底部增加一个底部的固定图片,和二维码,和图片的左上角笼罩log图难点:因为是应用canvas渲染的图片,然而图片的尺寸不是固定,也就是canvas的尺寸不是固定(解决:在内部先获取图片的尺寸,传进这个组件中)h5是渲染失常的,微信小程序图片渲染不进去(解决:微信不反对canvas间接渲染网络图片,所以须要先缓存到本地)<template> <view class="poster-box" ref="posterBox" @click="hidePoster"> <canvas :style="{ width: posterOptions.poster.canvasWidth + 'px', height: posterOptions.poster.canvasHeight + 'px', }" canvas-id="myCanvas" ></canvas> <!-- #ifdef MP --> <image :src="base64" class="poster-image" :draggable="false" show-menu-by-longpress="true" ></image> <!-- #endif --> <!-- #ifdef H5 --> <image class="poster-image" :src="base64" :draggable="false"></image> <!-- #endif --> </view></template><script>import Qr from '@/utils/wxqrcode'export default { name: 'poster_canvas', data() { return { base64: '', // 海报绘制成图片以便保留 } }, props: { //图片地址 posterOptions: { type: Object, require: true, }, }, mounted() { this.$nextTick(() => { this.imgToCanvas() }) }, methods: { async imgToCanvas() { let that = this let canvasHeight = this.posterOptions.isHavePosterImg ? this.posterOptions.poster.canvasHeight : this.posterOptions.poster.canvasHeight - this.posterOptions.buttonOption.h // 渲染大图 let ctx = uni.createCanvasContext('myCanvas', that) console.log(11111,this.posterOptions) ctx.drawImage( this.posterOptions.poster.url, 0, 0, this.posterOptions.poster.canvasWidth, canvasHeight ) if (!this.posterOptions.isHavePosterImg) { //渲染底部的图片 ctx.drawImage( this.posterOptions.buttonOption.bottomUrl, this.posterOptions.buttonOption.x, this.posterOptions.buttonOption.y, this.posterOptions.buttonOption.w, this.posterOptions.buttonOption.h ) } // 渲染二维码 if (this.posterOptions.QrOption.isWeChatMiniApp) { ctx.drawImage( this.posterOptions.QrOption.QrUrl, this.posterOptions.QrOption.x, this.posterOptions.QrOption.y, this.posterOptions.QrOption.w, this.posterOptions.QrOption.h ) } else { //一般二维码 let qrCodeImg = Qr.createQrCodeImg(this.posterOptions.QrOption.QrUrl, { size: parseInt(300), }) ctx.drawImage( qrCodeImg, this.posterOptions.QrOption.x, this.posterOptions.QrOption.y, this.posterOptions.QrOption.w, this.posterOptions.QrOption.h ) } if (!this.posterOptions.isHavePosterImg) { // 渲染log 和文字 ctx.drawImage( this.posterOptions.logOption.logUrl, this.posterOptions.logOption.x, this.posterOptions.logOption.y, this.posterOptions.logOption.w, this.posterOptions.logOption.h ) ctx.fillStyle = this.posterOptions.textOption.color ctx.setFontSize(22) ctx.font = 'bold arial' ctx.fillText( this.posterOptions.textOption.text, this.posterOptions.textOption.x, this.posterOptions.textOption.y ) } ctx.save() //保留 ctx.draw() //绘制 // 不加提早的话,base64有时候会赋予undefined // 把以后画布指定区域的内容导出生成指定大小的图片,并返回文件门路 setTimeout(() => { uni.canvasToTempFilePath( { canvasId: "myCanvas", fileType: "jpg", width:that.posterOptions.poster.canvasWidth, height:that.posterOptions.poster.canvasHeight, destWidth:that.posterOptions.poster.canvasWidth, destHeight:that.posterOptions.poster.canvasHeight, success: function (res) { that.base64 = res.tempFilePath; }, fail: function (error) { console.log(error, "谬误"); }, },that ); }, 500); }, hidePoster() { // #ifdef H5 this.$parent.$parent.hidePoster() // #endif // #ifndef H5 this.$parent.hidePoster() // #endif }, },}</script><style lang="scss" scoped>.poster-box { position: fixed; top: 0; z-index: 999; background-color: rgba(0, 0, 0, 0.8); width: 100%; height: 100%; display: flex; align-items: center; justify-content: center;}.poster-image { position: absolute; top: 0; left: 0; z-index: 1000; width: 100%; height: 100%; opacity: 0;}</style>应用 ...

September 4, 2022 · 6 min · jiezi

关于uniapp:Uniapp-小程序开发完美适配刘海屏的Appbar方案

在Uniapp开发小程序的过程中,常常会遇到官网提供的appbar计划无奈满足开发需要的问题,在应用自定义appbar开发过程中,难以避免的会遇到适配刘海屏的问题,接下来我将会带给大家最完满的刘海屏适配计划,间接上代码。 在app.vue中退出获取机型头部高度的办法,并把获取的数据存入vuex <script> export default { data() { return { globalData: { //全局数据管理 navBarHeight: 0, // 导航栏高度 menuBottom: 0, // 胶囊距底部间距(顶部间距也是这个) menuHeight: 0, // 胶囊高度 }, } }, methods: { calcNavBarInfo () { // 获取零碎信息 const systemInfo = wx.getSystemInfoSync(); // 胶囊按钮地位信息 const menuButtonInfo = wx.getMenuButtonBoundingClientRect(); // 导航栏高度 = 状态栏到胶囊的间距(胶囊上坐标地位-状态栏高度) * 2 + 胶囊高度 + 状态栏高度 this.globalData.navBarHeight = (menuButtonInfo.top - systemInfo.statusBarHeight) * 2 + menuButtonInfo.height + systemInfo.statusBarHeight; // 状态栏和菜单按钮(标题栏)之间的间距 // 等同于菜单按钮(标题栏)到注释之间的间距(胶囊上坐标地位-状态栏高度) this.globalData.menuBottom = menuButtonInfo.top - systemInfo.statusBarHeight; // 菜单按钮栏(标题栏)的高度 this.globalData.menuHeight = menuButtonInfo.height; this.$store.commit('update_globalStyle', this.globalData); } }, onLaunch: function() { console.log('App Launch'); this.calcNavBarInfo(); }, onShow: function() { console.log('App Show') }, onHide: function() { console.log('App Hide') } }</script><style> /*每个页面公共css */ view { box-sizing: border-box; } ::-webkit-scrollbar { display: none; } .flex-right { display: flex; justify-content: flex-end; align-items: center; } .flex-center { display: flex; justify-content: center; align-items: center; }</style>创立自定义的appbar组件: ...

September 3, 2022 · 2 min · jiezi

关于uniapp:uniapp实现IM即时通讯仿微信聊天功能

本文介绍如何基于 UNIAPP 应用 即时通讯SDK ZIM SDK 疾速实现根本的音讯收发性能。 1 uniapp im 即时通讯性能 计划介绍即时通讯SDK ZIM SDK 提供了如下接入计划: 在此计划中,您须要通过您本人的业务零碎实现以下业务逻辑: 搭建客户端的用户治理逻辑,并下发用户 ID 用于客户端登录。鉴权 Token,倡议由您的业务后盾自行实现,保障鉴权数据安全。uni-app SDK 是一个基于原生 iOS/Android 平台 ZIM SDK 的 uni-app Wrapper。开发者如需应用 uni-app 开发 Web 或小程序平台的利用,请下载对应的 SDK 集成应用:下载 Web SDK 和 下载小程序 SDK。 2 集成 IM 即时通讯SDK 的前提条件在应用 IM即时通讯 SDK ZIM SDK 前,请确保: 已在 ZEGO 控制台 创立我的项目,获取到了接入 IM即时通讯 ZIM SDK 服务所需的 AppID 和 ServerSecret。ZIM 服务权限不是默认开启的,应用前,请先在 ZEGO 控制台 自助开明 ZIM 即时通讯 服务(详情请参考 项目管理 - 即时通讯),若无奈开明 ZIM即时通讯 服务,请分割 ZEGO 技术支持开明。已获取登录 即时通讯 SDK 所需的 Token,详情请参考 应用 Token 鉴权。3 集成 uniapp IM 即时通讯 SDK3.1 (可选)新建我的项目此步骤以如何创立新我的项目为例,如果是集成到已有我的项目,可疏忽此步。 ...

August 29, 2022 · 3 min · jiezi

关于uni-app:如何在uniapp使用iconfont字图标

增加图标关上,https://www.iconfont.cn/ 网站,找到本人的喜爱的图表退出到我的项目中 下载本地点击下载至本地 拷贝文件将iconfont.css,iconfont.woff,iconfont.woff2 复制到本人的我的项目中, 关上iconfont.css文件,我须要去编辑框框的中央 资源转换uni-app 字体文件小于 40kb,uni-app 会主动将其转化为 base64 格局uni-app 本地门路图标字体反对状况:字体文件大于等于 40kb, 需开发者本人转换,否则应用将不失效转换工具https://www.giftofspeed.com/base64-encoder/ 关上转换工具网站,抉择iconfont.ttf字体进行转换 复制内容,回到代码 成果浏览器端 App端

August 17, 2022 · 1 min · jiezi

关于uniapp:手把手教你uniapp接入聊天IM即时通讯功能源码分享

本文介绍如何基于uniapp应用 IM即时通讯SDK ZIM SDK 疾速实现同腾讯微信音讯收发聊天交友性能。实现uniapp跨平台框架开发多端利用,节俭开发成本。 1 IM即时通讯SDK接入计划介绍ZIM SDK IM即时通讯SDK提供了如下接入计划: 在此计划中,您须要通过您本人的IM即时通讯业务零碎实现以下业务逻辑: 搭建客户端的用户治理逻辑,并下发用户 ID 用于客户端登录。鉴权 Token,倡议由您的业务后盾自行实现,保障鉴权数据安全。2 接入IM即时通讯SDK的前提条件在应用 IM即时通讯SDK ZIM SDK 前,请确保: 开发环境: React Native 0.60.0 或以上版本。iOS 9.0 或以上版本的 iOS 设施或模拟器(举荐应用真机)。Android 4.0.3 或以上版本的 Android 设施或模拟器(举荐应用真机),如果为真机,请开启“容许调试”选项。iOS / Android 设施曾经连贯到 Internet。配置 VS Code 开发环境,可在利用商店中搜寻 “React Native Tools” 扩大并下载。已在 ZEGO 控制台 创立我的项目,获取到了接入 ZIM SDK 服务所需的 AppID 和 ServerSecret。ZIM 即时通讯SDK 服务权限不是默认开启的,应用前,请先在 ZEGO 控制台 自助开明 ZIM 服务(详情请参考 项目管理 - 即时通讯),若无奈开明 ZIM 即时通讯SDK 服务,请分割 ZEGO 技术支持开明。已获取登录 IM即时通讯SDK 所需的 Token,详情请参考 应用 Token 鉴权。3 集成 IM即时通讯SDK3.1 (可选)新建我的项目此步骤以如何创立新我的项目为例,如果是集成到已有我的项目,可疏忽此步。 ...

August 8, 2022 · 3 min · jiezi

关于uniapp:uniapp集成极光推送

本文旨在记录应用极光推送中遇到的坑 注册极光账号并获取AppKey去极光官网注册账号,并创立利用,填写包名,获取AppKey。 引入极光推送插件极光推送依赖 极光JCore官网SDK,所以首先须要引入 极光JCore官网SDK。而后引入 极光JPush官网SDK。而后在我的项目的manifest.json中,找到App原生插件配置抉择咱们援用的云端插件填写获取到的AppKey 援用曾经实现,上面开始编码。 调用极光推送在common中新建jpush.js 公共APIAndroid独有APIiOS独有API// 引入极光推送插件var jpushModule = uni.requireNativePlugin("JG-JPush");export default () => { // 开启debug模式 jpushModule.setLoggerEnable(true); // 初始化SDK jpushModule.initJPushService(); // 连贯状态回调 jpushModule.addConnectEventListener(result => { let connectEnable = result.connectEnable // true已连贯, false未连贯 console.log("jpush连贯", connectEnable) }) // 设置别名 jpushModule.setAlias({ "alias": "别名", "sequence": 1 }) // 告诉事件回调 jpushModule.addNotificationListener(result => { // 通过 notificationEventType字段辨别是收到告诉还是点击告诉 const { notificationEventType, messageID, title, content } = result if(notificationEventType == 'notificationOpened') { // 点击告诉操作 } else if(notificationEventType == 'notificationArrived') { // 收到告诉 } }) // 获取应用程序的 RegistrationID。 只有当应用程序胜利注册到 JPush 的服务器时才返回对应的值,否则返回空字符串 jpushModule.getRegistrationID(result => { if (result.registerID) { uni.setStorageSync("register_id", result.registerID) } }) // 自定义音讯,不会显示在告诉栏里 jpushModule.addCustomMessageListener(result => { console.log("自定义音讯", result) })}在App.vue中引入jpush.js ...

July 22, 2022 · 1 min · jiezi

关于uni-app:Uniapp开发App和插件以后如何开通广告盈利uniAD

Uni-app 作为近些年国内逐步衰亡的跨平台开发架构,一次开发就能够实现小程序、iOS APP、安卓 APP、 H5等平台的打包是受到关注的起因。于此同时,很多开发者也开始关注Uni-app架构之外的货色,比如说如何退出广告性能让本人的软件可能实现变现。 其实 Uni-app 的开发团队 DCloud 早就推出了一款名为 uni-AD 广告联盟的产品,开发者能够通过 uni-AD 广告联盟实现信息流广告/原生广告、插屏广告等性能。明天智密科技就来为大家介绍一下这款官网推出的广告公布插件。 uni-AD 目前反对的平台APP、微信小程序广告、H5 uni-AD 在APP端反对的广告渠道优量汇,快手,穿山甲,百度,华为,Sigmob,360 开明 uni-AD 的流程uni-AD登录地址:请登录uni-AD后盾进行注册,而后进行实名认证(确保实名认证的信息与广告联盟收款人信息保持一致)进入后盾,开明根底广 告与加强广告,加强广告须要软著和利用商店上架(快手和Sigmob广告除外)。根底广 告开明后即可应用,加强广告须要审核后才可应用,审核工夫为1-2个工作日遇节假日顺延。注:加强广告聚合了优量汇,快手等广告渠道,收益较根底广告要高审核通过后,即可创立广 告位,创立广 告位后生成apdid,进行广告代码部署与调试,确保利用上的广告位均可失常展现,从新公布您利用的新版本让用户进行更新。什么是根底广告和加强广告根底广告的模式包含:开屏广告悬浮广告推送广告加强广告的模式包含:开屏广告信息流广告激励视频广告全凭视频广告插屏广告因为uni-AD的所有申请程序都是动静调整的,会优先展现收益更高的渠道。因而如果是开屏广告同时存在有根底广告和加强广告,算法就会主动展现收益更高的广告。 部署根底广告API对接DPS广告,无需开发间接点击启动就能够展现广告部署加强广告通过SDK集成支流的广告联盟须要肯定的额定开发如何抉择原生利用广告接入与uni-app中应用uni-AD利用以后uni-AD反对应用原生利用广告接入。然而开发者在用原生利用接入广告时通常比uni-app利用接入广告要更费时(uni-app接入广告会比原生节俭一半工夫),这是因为原生代码相比uni-app的代码繁琐导致部署与调试效率降落。

July 14, 2022 · 1 min · jiezi

关于uniapp:uniapp封装unishowMsg提示框

在min.js中// 封装弹框办法 uni.$showMsg = function (title = '加载胜利', duration = 1500){ uni.showToast({ title, duration, icon:'none' })({ }) }调用提醒办法 onShow() { // uni.$showMsg() // 封装弹框办法 uni.$showMsg()},

July 7, 2022 · 1 min · jiezi

关于uni-app:uniapp下拉触底节流

<template> <view ><view class="clor" v-for="(item,index) in MathArr" :key="index":style="'background: rgba('+item+');'" >{{item}} </view></view></template> <script>export default { data(){ return { MathArr:[], lond:'' } },methods:{getColor(){ this.lond=true uni.showLoading({ title:'正在加载中...' }) const t=this uni.request({ url:'https://www.escook.cn/api/color', method:'GET', success:({data:res})=> { t.MathArr=[...t.MathArr,...res.data] }, complete:()=>{ uni.hideLoading() this.lond=false } })}},onLoad(){ this.getColor()},onReachBottom() { if(this.lond==false){ this.getColor()//下拉到底 触发申请 而后新旧数组一起合并 失去第二组第三组.....数据 }},}</script> <style> .clor{ line-height: 100px; height: 100px; border-radius: 8px; border: solid 1px #E6F3F9; text-align: center;}</style>

July 7, 2022 · 1 min · jiezi

关于uniapp:uniapp点击上传图片后清除原来的图片数据

执行步骤:点击“上传图片”按钮弹出弹窗,抉择图片点击“确定”图片上传胜利后弹窗敞开,再点击上传图片会发现弹窗会保留有上次选中图片的数据。开发要求:图片上传胜利后默认革除上一次选中上传的图片数据。解决办法: <view class="pop-up1" @click="rule1=true">弹窗1</view> <view class="sure_btn" @click="formData.type = 2;showOne()"> <p>上传图片</p> </view></view><!-- 弹窗 --><view class="boxBm test_pop" v-if="isLower"> <view class="box2 share-state"> <image class="img_close" @click="closePop" src="../../../static/img/koreaActive/close.png" mode=""></image> <view class="addImg"> <image class="" @click="addImg(),imgItem=true" src="../../../static/img/japanActive/upload.png" mode=""></image> </view> <textarea class="active_text" maxlength="1000" @input="getText" v-model="formData.remarks" placeholder="您尊贵的意见和倡议......" /> <button type="default" @click='uploadImage()'>確定</button> <view class="Img_box" v-if="imgItem" v-for="(item,index) in imgList" :key="index"> <image class="Img_item" :src="item" mode=""></image> </view> </view></view><script> import api from '@/apis/api.js' import URL from '@/common/config.js' export default { data() { return { token:'', showShare: false, isLower: false, imgList:[], List:'', rule1:false, formData: { pic: "", remarks:"", type:0 }, } }, async onLoad(e) { if (e.lang) { this.$i18n.locale = e.lang this.lang = e.lang } else { this.lang = 'en' } console.log("eee",e) await this.$onLaunched; //获取浏览器缓存的token this.token = localStorage.getItem('token') }, methods: { //弹出弹窗 showOne(){ this.showShare=true; this.isLower = true; // console.log('this.showShare',this.showShare) }, //革除上一次选中的图片数据 closePop() { this.formData = { pic: "", remarks:"", type:0 } this.imgList = [] this.List = [] this.isLower=false }, //点击抉择图片 addImg() { uni.chooseImage({ count: 3, //默认9 sizeType: ['original', 'compressed'], //能够指定是原图还是压缩图,默认二者都有 sourceType: ['album'], //从相册抉择 loop: true, success: res => { // console.log(res); if (res.tempFilePaths.length != 0) { this.imgList.push(res.tempFilePaths[0]); } var tempFiles = res.tempFiles[0]; uni.uploadFile({ url: URL.httpurl + '/api/common/upload', file: tempFiles, method: 'POST', name: 'file', header:{ token: this.token, }, success: uploadFileRes => { var data_ =JSON.parse(uploadFileRes.data) console.log('data_',data_) this.formData.pic = data_.data.url; this.formData.pic = data_.data.url; // console.log('上传图片', JSON.parse(uploadFileRes.data)); }, fail(err) { console.log(err); } }); } }); }, //点击“确定”上传图片 uploadImage(){ this.$apis.saveImg(this.formData) .then(res => { console.log(res) uni.showToast({//提醒 title: res.msg, // lang:this.lang, }) //执行革除数据办法 this.closePop() }) } }</script> ...

June 20, 2022 · 2 min · jiezi

关于uni-app:云开发扫码点餐系统实战

云开发是什么?还不晓得云开发是什么?看看微信官网的视频介绍:云开发是什么,置信看完之后,你会有所理解。 单刀直入扫码点餐零碎后盾治理端地址:乔巴餐饮店 账号:18000000000 明码:123qweASD 大家也能够本人注册账号密码去登录。 目前后盾菜品等数据较少,大家能够自行添加,就能够在小程序中展现进去了。 小程序端地址:默认是001号桌,这样就会间接进入点餐界面,不会到首页 也能够间接扫码 001号桌,能够进入首页,抉择就餐人数 示意图: 技术栈基于vue2.x语法的uniapp实现微信小程序云开发 + 云函数 + 云数据库 + 云托管 + 动态网站托管 + 腾讯云cos对象存储 + nodejs + koa + GoEasy 即时通讯。波及到的技术点还是比拟多的,然而都是目前支流的技术点,云开发更是将来的趋势。最初云开发当初越来越炽热,生态也越来越欠缺,各家云厂商更是百花齐放。腾讯云借助本身微信生态的劣势,更是吸引宽广程序员蠢蠢欲动,某些业务场景更是颠覆了传统的开发模式,一举成为 "短平快" 我的项目的宠儿。之前基于微信小程序云开发做过的一个cms相干的小程序,更是不到一周就搞定上线了,若依照传统开发模式去做,可能至多须要2~3周工夫。因为基于微信小程序云开发去实现,间接省去了后盾开发和后盾管理系统开发,间接基于微信云函数、云存储、云数据库、以及微信内置的弱小的 "内容治理" 零碎,只用将重心关注在小程序性能实现上,开发效率晋升好几倍,不要太爽! **学习,慢慢来,会很快。 有趣味能够关注下我的微信公众号 "面向 CtrlCV 编程",所有最新文章、学习资源、工具、会最先在公众号内公布。**回复 “点餐”,即可取得小程序端源码,可自行二次开发。有问题可扫下面二维码增加我的微信号。

May 31, 2022 · 1 min · jiezi

关于uniapp:uniapp-和-HTML5-区别

uniapp 和 HTML5 区别:1、uniapp 是一个应用 Vue.js 开发所有前端利用的框架,而 HTML5 是构建 Web 内容的一种语言形容形式;2、uniapp 不反对 dom 操作,而 H5 端有 dom 对象;3、uniapp 不反对过滤器等等。 本教程操作环境:windows7 零碎、uni-app2.5.1 版本、thinkpad t480 电脑。 举荐(收费):uni-app 开发教程 uniapp 是一个应用 Vue.js 开发所有前端利用的框架,开发者编写一套代码,可公布到 iOS、Android、Web(响应式)、以及各种小程序(微信 / 支付宝 / 百度 / 头条 / QQ / 钉钉 / 淘宝)、快利用等多个平台。 HTML5 是构建 Web 内容的一种语言形容形式。HTML5 是互联网的下一代规范,是构建以及出现互联网内容的一种语言形式.被认为是互联网的核心技术之一。HTML 产生于 1990 年,1997 年 HTML4 成为互联网规范,并广泛应用于互联网利用的开发。 uniapp 反对跨挪动端开发,如果只做 H5 端,用 uniapp 其实和用 vue 开发没什么区别,vue 能用的插件,uniapp 也能用。 uniapp 的性能问题次要集中在 app 端,做 H5 和 VUE 的开发体验是统一的。 ...

May 26, 2022 · 1 min · jiezi

关于uniapp:微信小程序和-uniapp-的区别是什么

区别:1、触摸事件名称上,微信小程序是 bindtap,uniapp 是 “@click”;2、if 判断上,微信小程序应用 “wx:if="{{isShow}}” 语句,uniapp 应用 “v-if="isShow"” 语句。 本教程操作环境:windows10 零碎、uni-app2.5.1 版本,Dell G3 电脑。 举荐:《uni-app 开发教程》 微信小程序和 uniapp 的区别 触摸事件名称:①微信小程序:bindtap②uni-app:@click 函数传参形式:①微信小程序:<view bindtap="click" data-id="id"></view>②uni-app:<view @click="click(id)"></view> 函数接管参数:①微信小程序:function(e){this.setData(currentId:e.currentTarget.dataset.id)}②uni-app:function(id){this.currentId = id} for 循环:①微信小程序:<view wx:for="{{currentList}}" wx:for-index="s_index" wx:for-item="s_item"></view>②uni-app:<view v-for="(s_item,s_index) in currentList"></view> if 判断:①微信小程序:<view wx:if="{{isShow}}"></view>②uni-app:<view v-if="isShow"></view> src 动静接管图片:①微信小程序:<image src="{{item.img}}"></image>②uni-app:<image :src="$util.img(item.img)"></image> 页面传参:①微信小程序:<navigator url="/pages/live?id={{item.room_id}}"></navigator>②uni-app:<navigator :url="'/pages/live?id=' + item.room_id"></navigator> 源码附件曾经打包好上传到百度云了,大家自行下载即可~ 链接: https://pan.baidu.com/s/14G-b...提取码: yu27百度云链接不稳固,随时可能会生效,大家放松保留哈。 如果百度云链接生效了的话,请留言通知我,我看到后会及时更新~ 开源地址码云地址:http://github.crmeb.net/u/defu Github 地址:http://github.crmeb.net/u/defu

May 25, 2022 · 1 min · jiezi

关于uni-app:uniapp复制功能

<template> <view> <view @click="copy("123")"></view> </view></template> <script>copy(value){ //提醒模板 uni.showModal({ content:value,//模板中提醒的内容 confirmText:'复制内容', success:()=>{//点击复制内容的后调函数 //uni.setClipboardData办法就是讲内容复制到粘贴板 uni.setClipboardData({ data:value,//要被复制的内容 success:()=>{//复制胜利的回调函数 uni.showToast({//提醒 title:'复制胜利' }) } }); } });}</script>

May 3, 2022 · 1 min · jiezi

关于uni-app:unipopup样式及遮罩

/小声BB/ :最近开始写uni-app,发现ui框架是真的很...难用。官网文档也...一言难尽。或者某种意义上来讲,这也属于是由奢入俭难吧。同样的,存在也即是正当,我没有不感恩的意思。 效果图: template:<template> <view> <view class="mark" v-show="showMask"></view> <!-- 其余组件代码略 --> <uni-popup ref="delete" type="dialog" class="popup-style"> <uni-popup-dialog type="error" cancelText="勾销" confirmText="确认" title="删除" content="是否确认删除" @confirm="deleteConfirm" @close="showMask=false"></uni-popup-dialog> </uni-popup> </view></template>script:import uniPopup from "@/components/uni-popup/uni-popup"import uniPopupDialog from "@/components/uni-popup-dialog/uni-popup-dialog"export default { components:{ uniPopup, uniPopupDialog }, data() { return { showMask: false, } }, <!-- 其余代码略 -->},scss:<style lang="scss" scoped> // uni-popup款式重置 /deep/.popup-style { .uni-popup-dialog { position: fixed; top: 30%; left: calc((100vw - 300px)/2); } // 遮罩层 .mark { height: 100vh; width: 100vw; background: rgba(0, 0, 0, 0.5); position: absolute; left: 0%; right: 0%; z-index: 1; }}</style>

April 29, 2022 · 1 min · jiezi

关于uniapp:腾讯云直播插件MLVB如何借助这些优势成为主播直播推拉流的神助攻

跨平台代码公布因为智密-腾讯云直播 MLVB 插件是基于 HbuilderX 开发,并采纳了 uni-app 框架。因而能够实现一套代码公布多个平台的跨平台开发个性。目前 uni-app 框架不仅反对了  iOS、Android 两大支流手机操作系统的APP公布,还反对 H5、小程序和 Web 版公布。 再联合 MLVB 的 SDK 自身就可能兼容这些平台进行数据接入,因而真正让主播和观众能够不受限制的推送/观看直播,构建多种直播场景。 高速推流腾讯云为规范 RTMP 提供 UDP 减速能力,当您应用挪动直播 SDK 的 RTMP 推流性能时,配合云直播,能够开启 UDP 减速能力,开启 UDP 减速后的推流品质会比规范 RTMP 推流有更好的网络稳定抵抗力,同时能够取得更好的推流速度,将传统直播中3秒 - 5秒延时升高至1秒以内,同时兼顾秒开、卡顿率等外围指标从而改善以后直播流的观看体验,升高全局卡顿率。 互动连麦性能所有主播在进行直播时,为了留住老观众,并吸引更多的新流量,与粉丝进行互动是必不可少的。不论是通过留言还是语音连麦,乃至于粉丝进行视频互动,当初都曾经是一个直播APP必备的性能。而基于uniapp框架开发的智密-腾讯云直播 SDK 因为其反对模块化开发的劣势,连麦的性能甚至不须要从新开发,仅作为功能模块能够非常简便地退出到现有的直播APP中。 同时因为摈弃了传统TCP协定而转向应用UDP协定进行RTMP传输,因而不论是语音连麦还是视频互动的提早都非常低。进一步晋升了粉丝与主播之间互动吸粉能力。 开源源码模块化开发如前一节提到的,应用 Uni-app 框架进行直播 App 的开发除了反对跨平台公布安装包,另外一大个性就是模块化开发。 置信很多开发者都遇到过给 APP 开发新性能的需要。在模块化开发之前,每次退出新性能都必须在原先的代码中减少和删减。如果从 Github 中其余开发者分享的代码移植到本人的软件我的项目中,还会遇到各种变量、隶属和 Bug 等问题。 然而 Uniapp 的模块化开发齐全能够让 APP 新增性能效率大大晋升。例如想要给本人的直播 APP 退出购物车和红包的性能,就能够参考往期的文章: 在这里,仅仅3段代码就能够实现购物车的性能:uniapp短视频APP持续革新降级:退出购物车与红包性能 10 分钟上手直播 APP DemoUni-app 的开发者应该都晓得,想要将 DCloud 的插件市场中的试用 Demo 移植到本人中央是一件比拟轻松的事件,甚至10分钟就能够实现从“申请试用+打包自定义基座“到 ”HBuilderX 导入我的项目“的配置。具体配置教程能够参考前文:如何在Uni-app中疾速创立属于本人的第一个仿抖音短视频App ...

April 12, 2022 · 1 min · jiezi

关于uniapp:用uniapp写一个内外循环的全选与反选不会的赶紧围观

依据我的项目需要;写的一个内外循环的全选与反选;遇到问题:因为是分页,抉择全选,当上拉加载时;新加载的数据并没有被选中等问题,都被解决;如果有其余些问题;欢送提出。 留神:这只我我的项目中的页面;有些全局援用的例如提醒或是一些组件;应用的时候能够删除;并不影响次要性能;获取数据时;因为后盾传的是认为数组;但理论须要的二维数据;上面获取数据的接口曾经过解决;依据你们返回的数据格式可自行更改;咱们我的项目中有一键换色;牵扯到色彩变量的可删除;写成固定色彩以下是具体代码: Html:<template> <view> <view class="record" :style="colorStyle" v-if="visitList.length"> <view class="nav acea-row row-between-wrapper"> <view class="left">以后共 <text class="num">{{count}}</text> 件商品</view> <view class="font-num" v-if="!isShowChecked" @click="switchTap">治理</view> <view v-else @click="switchTap">勾销</view> </view> <view class="list"> <checkbox-group @change="checkboxChange"> <view class="item" v-for="(item,index) in visitList" :key="index"> <view class="title"> <checkbox v-if="isShowChecked" :value="item.time" :checked="item.checked" /> <text>{{item.time}}</text> </view> <checkbox-group @change="(e)=>{picCheckbox(e,index)}"> <view class="picList acea-row row-middle"> <view class="picTxt" v-for="(j,jindex) in item.picList" :key="jindex" @click.stop="goDetails(j)"> <view class="pictrue"> <image :src="j.image"></image> <checkbox v-if="isShowChecked" :value="(j.id).toString()" :checked="j.checked" class="checkbox" /> </view> <view class="money">¥<text class="num">{{j.product_price}}</text></view> </view> </view> </checkbox-group> </view> </checkbox-group> <view class='loadingicon acea-row row-center-wrapper'> <text class='loading iconfont icon-jiazai' :hidden='loading==false'></text>{{loadTitle}} </view> </view> <view class="footer acea-row row-between-wrapper" v-if="isShowChecked"> <checkbox-group @change="checkboxAllChange"> <checkbox value="all" :checked="isAllSelect" /> <text class='checkAll'>全选</text> </checkbox-group> <view class="acea-row row-middle"> <view class="bnt acea-row row-center-wrapper" @click="collect">珍藏</view> <view class="bnt on acea-row row-center-wrapper" @click="del">删除</view> </view> </view> </view> <view class='noCommodity' v-else-if="!visitList.length && page == 1"> <view class='pictrue'> <image src='../../../static/images/noCollection.png'></image> </view> <recommend :hostProduct="hostProduct"></recommend> </view> <home v-if="navigation"></home> </view></template>Js:<script> import { getVisitList, getProductHot, deleteVisitList, collectAdd } from '@/api/store.js'; import { mapGetters } from "vuex"; import { toLogin } from '@/libs/login.js'; import recommend from '@/components/recommend'; // #ifdef MP import authorize from '@/components/Authorize'; // #endif import home from '@/components/home'; import colors from '@/mixins/color.js' export default { components: { recommend, // #ifdef MP authorize, // #endif home }, mixins: [colors], data() { return { isShowChecked: 0, count: 0, times: [], isAllSelect: false, hostProduct: [], loadTitle: '加载更多', loading: false, loadend: false, visitList: [], limit: 21, page: 1, isAuto: false, //没有受权的不会主动受权 isShowAuth: false, //是否暗藏受权 hotScroll: false, hotPage: 1, hotLimit: 10, isItemAll: [] }; }, computed: mapGetters(['isLogin']), onLoad() { if (this.isLogin) { this.loadend = false; this.page = 1; this.visitList = []; this.get_user_visit_list(); this.get_host_product(); } else { toLogin(); } }, onShow() { this.times = []; this.loadend = false; this.page = 1; this.visitList = []; this.get_user_visit_list(); }, methods: { goDetails(item){ if(this.isShowChecked) return false; uni.navigateTo({ url: '/pages/goods_details/index?id=' + item.product_id }) }, switchTap(){ this.isShowChecked = !this.isShowChecked; }, collect(){ let ids = []; this.visitList.forEach(item=>{ item.picList.forEach(j=>{ if(j.checked){ ids.push(j.id) } }) }) if(!ids.length){ return this.$util.Tips({ title: '请抉择珍藏商品' }); } collectAdd(ids).then(res=>{ return this.$util.Tips({ title: res.msg }); }) }, del(){ let ids = []; this.visitList.forEach(item=>{ item.picList.forEach(j=>{ if(j.checked){ ids.push(j.id) } }) }) if(!ids.length){ return this.$util.Tips({ title: '请抉择删除商品' }); } deleteVisitList(ids).then(res=>{ this.times = []; this.loadend = false; this.page = 1; this.$set(this, 'visitList', []); this.get_user_visit_list(); return this.$util.Tips({ title: res.msg }); }) }, picCheckbox(event, index) { let that = this, picTime = event.detail.value; that.visitList[index].picList.forEach(j => { if (picTime.indexOf(j.id + '') !== -1) { j.checked = true; } else { j.checked = false; } }) if(that.visitList[index].picList.length == picTime.length){ that.visitList[index].checked = true; }else{ that.visitList[index].checked = false; } let visitObj = []; that.visitList.forEach(item=>{ if(item.checked){ visitObj.push(item.time) }else{ if(visitObj.indexOf(item.time) !== -1){ visitObj.remove(item.time); } } }) if(visitObj.length == that.visitList.length){ that.isAllSelect = true; }else{ that.isAllSelect = false; } }, checkboxChange(event) { let that = this, timeList = event.detail.value; that.isItemAll = timeList; that.visitList.forEach((item, index) => { if (timeList.indexOf(item.time) !== -1) { item.checked = true; } else { item.checked = false; } item.picList.forEach(j => { if (item.checked) { j.checked = true; } else { j.checked = false; } }) }) if (timeList.length === that.visitList.length) { that.isAllSelect = true; } else { that.isAllSelect = false; } }, forGoods(val) { let that = this; if (!that.visitList.length) return that.visitList.forEach((item) => { if (val) { item.checked = true; } else { item.checked = false; } item.picList.forEach(j => { if (val) { j.checked = true; } else { j.checked = false; } }) }) }, checkboxAllChange(event) { let value = event.detail.value; if (value.length) { this.isAllSelect = true; this.forGoods(1) } else { this.isAllSelect = false; this.forGoods(0) } }, // 受权敞开 authColse: function(e) { this.isShowAuth = e }, /** * 获取珍藏产品 */ get_user_visit_list: function() { let that = this; if (this.loading) return; if (this.loadend) return; that.loading = true; that.loadTitle = ""; getVisitList({ page: that.page, limit: that.limit }).then(res => { this.count = res.data.count; for (let i = 0; i < res.data.time.length; i++) { if (this.times.indexOf(res.data.time[i]) == -1) { this.times.push(res.data.time[i]) this.visitList.push({ time: res.data.time[i], picList: [] }) } } for (let x = 0; x < this.times.length; x++) { this.visitList[x].checked = this.isAllSelect ? true : false; for (let j = 0; j < res.data.list.length; j++) { if (this.times[x] === res.data.list[j].time_key) { if (this.isAllSelect) { res.data.list[j].checked = true; } else { res.data.list[j].checked = false; } this.visitList[x].picList.push(res.data.list[j]) } } } let loadend = res.data.list.length < that.limit; that.loadend = loadend; that.loadTitle = loadend ? '没有更多内容啦~' : '加载更多'; that.page = that.page + 1; that.loading = false; }).catch(err => { that.loading = false; that.loadTitle = "加载更多"; }); }, /** * 获取我的举荐 */ get_host_product: function() { let that = this; if (that.hotScroll) return getProductHot( that.hotPage, that.hotLimit, ).then(res => { that.hotPage++ that.hotScroll = res.data.length < that.hotLimit that.hostProduct = that.hostProduct.concat(res.data) }); } }, onReachBottom() { if (this.visitList.length) { this.get_user_visit_list(); } else { this.get_host_product(); } } }</script>Css:<style lang="scss"> page { background-color: #fff; } .record .pictrue /deep/checkbox .uni-checkbox-input { background-color: rgba(0, 0, 0, 0.16); } .record .pictrue /deep/checkbox .wx-checkbox-input { background-color: rgba(0, 0, 0, 0.16); } .record { .footer { box-sizing: border-box; padding: 0 30rpx; width: 100%; height: 96rpx; box-shadow: 0px -4px 20px 0px rgba(0, 0, 0, 0.06); background-color: #fff; position: fixed; bottom: 0; z-index: 30; padding-bottom: constant(safe-area-inset-bottom); ///兼容 IOS<11.2/ padding-bottom: env(safe-area-inset-bottom); ///兼容 IOS>11.2/ .bnt { width: 160rpx; height: 60rpx; border-radius: 30rpx; border: 1rpx solid #ccc; color: #666666; &.on { border: 1rpx solid var(--view-theme); margin-left: 16rpx; color: var(--view-theme); } } } .nav { border-bottom: 1rpx solid #eee; color: #999999; font-size: 28rpx; height: 74rpx; padding: 0 30rpx; .left { color: #333; .num { color: var(--view-theme); margin: 0 10rpx; } } } .list { padding-top: 32rpx; padding-bottom: 96rpx; .item { .title { padding: 0 30rpx; margin-bottom: 34rpx; font-size: 34rpx; font-weight: 600; } .picList { padding: 0 30rpx 0 12rpx; .picTxt { margin-left: 18rpx; margin-bottom: 48rpx; .pictrue { width: 218rpx; height: 218rpx; border-radius: 10rpx; position: relative; image { width: 100%; height: 100%; border-radius: 10rpx; } .checkbox { position: absolute; right: 10rpx; top: 14rpx; } } .money { font-size: 24rpx; color: var(--view-theme); font-weight: 600; margin-top: 15rpx; .num { font-size: 32rpx; margin-left: 6rpx; } } } } } } }</style>最初如果你感觉这篇文章对你有点用的话,麻烦请给咱们的开源我的项目点点star:http://github.crmeb.net/u/defu不胜感激 ! ...

April 12, 2022 · 5 min · jiezi

关于uniapp:UNIAPP条件编译ifdef-ifndef-endif

语法释义#ifdef仅实用于某环境下#ifndef仅实用于非某环境下#endif完结1.标识含意标识含意VUE3HBuilderX 3.2.0+APP-PLUSAppAPP-PLUS-NVUE或APP-NVUEApp nvueH5H5MP微信小程序/支付宝小程序/百度小程序/头条小程序/QQ小程序MP-WEIXIN微信小程序MP-ALIPAY支付宝小程序MP-TOUTIAO字节跳动小程序MP-LARK飞书小程序MP-BAIDU、MP-QQ 、MP-KUAISHOU、MP-360 QUICKAPP-WEBVIEW快利用通用2.示例<!-- #ifndef APP-NVUE --><view><text>{{msg}}</text></view><!-- #endif --><!-- #ifdef APP-NVUE --><text><text>{{msg}}</text></text><!-- #endif -->

April 7, 2022 · 1 min · jiezi

关于uniapp:unipush消息推送及遇到的问题

1 . 在app.vue页面onLaunch中增加 onLaunch: function() { var platform = uni.getSystemInfoSync().platform; // #ifdef APP-PLUS plus.screen.lockOrientation("portrait-primary"); //推送 var pinf = plus.push.getClientInfo(); var cid = pinf.clientid; //客户端标识 console.log('cid:' + cid); const _self = this; const _handlePush = function(payload) { var pages = getCurrentPages(); console.log('----------', payload) //页面栈为0,标记app是被push唤醒,在欢送页执行跳转逻辑 if (payload.alive === false) { console.log('设置storage') uni.setStorage({ key:'appLaunchedByPush', data:payload }) } else { //app在线,收到push能够间接跳转 uni.navigateTo({ url: '/pages/index' }); } }; plus.push.addEventListener('click', function(message) { console.log('push click =======', message) if (platform == 'ios') { //离线是payload为object , 在线时本地创立的为string(本地创立告诉只能传string,否则无奈传递payload) if (typeof message.payload == 'string') { console.log('string') var payload = JSON.parse(message.payload); } else { console.log('obj') var payload = message.payload; } _handlePush(payload); return } //这里能够写跳转业务代码 _handlePush(message.payload); }); plus.push.addEventListener('receive', function(message) { console.log('push receive ======', message); if (message.type == "receive"){ // 这里判断触发的起源,否则始终推送。 if (platform == 'ios') { console.log('ios receive', message); if (typeof message.payload == 'string') { plus.push.createMessage( message.content, message.payload, { cover: false, title: message.title, }); } else { plus.push.createMessage( message.content, JSON.stringify(message.payload), { cover: false, title: message.title, }); } } else { console.log('android receive======', message); //执行跳转判断或增加本地告诉 plus.push.createMessage( message.content, JSON.stringify(message.payload), { cover: false, title: message.title }); } } }); }2 . 解决离线音讯跳转在app默认跳转页面增加我这里是登录页面 ...

April 2, 2022 · 2 min · jiezi

关于uni-app:开发日记03-uniapp-打包为-app

uni-app 打包为 app 前置条件老手向,但须要有一些开发根底。 Git官网下载:https://git-scm.com/downloads应用以下命令验证是否可用 git version# 示例输入# git version 2.32.0 (Apple Git-132)NodeJSnodejs 应用 lts 长期反对版本就行。 官网下载:https://nodejs.org/zh-cn/download/应用以下命令验证是否可用 node -v# 示例输入# v16.14.1装置全局须要用到的工具,如果是 mac 零碎须要加 sudo npm i yarn tbify -g# yarn: nodejs 包治理# tbify: 国内减速下载代理验证是否装置胜利 tyn -v# 示例输入# 1.22.17tnpm -v# 示例输入# 8.5.0HbuilderX下载正式版本下的 app 开发版本。 官网下载:https://www.dcloud.io/hbuilderx.html装置 sass 编译插件:https://ext.dcloud.net.cn/plugin?name=compile-node-sass 克隆代码git clone [你我的项目的git地址]# 示例git clone https://github.com/SunSeekerX/uni-app-starter.git 装置我的项目依赖uni-app 我的项目有两种类型, 一种是通过 HbuilderX 工具创立的一种是通过命令行工具创立的我比拟喜爱命令行工具创立的,因为所有依赖都能本人治理。同时也能进行 ci&cd集成,HbuilderX 创立的则更为简略不便。 分别形式 HbuilderX 工具创立 我的项目根目录下个别无 src 文件夹pages 文件夹在根目录命令行工具 ...

March 22, 2022 · 1 min · jiezi

关于uni-app:uniapp-通过命令行编译打包

# 切换node版本(不肯定须要)nvm use v16.2.0# 进入HBuild的cli目录# uni-app打包相干命令都封装在cli外面了cd /Applications/HBuilderX.app/Contents/HBuilderX/plugins/uniapp-cli/# 指定我的项目根地址INIT_CWD=/Users/robin/DO/VUE/xxx# H5端开发模式运行(对应IDE上的运行到浏览器,会主动关上浏览器)cross-env UNI_INPUT_DIR=$INIT_CWD/ UNI_OUTPUT_DIR=$INIT_CWD/unpackage/dist/dev/h5 UNI_PLATFORM=h5 NODE_ENV=development node bin/uniapp-cli.js# 开发模式打包appcross-env UNI_INPUT_DIR=$INIT_CWD/ UNI_OUTPUT_DIR=$INIT_CWD/unpackage/dist/dev/app-plus UNI_PLATFORM=app-plus NODE_ENV=development node bin/uniapp-cli.js# 打包编译H5端(对应IDE上的发行网站)cross-env UNI_INPUT_DIR=$INIT_CWD/ UNI_OUTPUT_DIR=$INIT_CWD/unpackage/dist/build/h5 UNI_PLATFORM=h5 NODE_ENV=production node bin/uniapp-cli.js# 发行模式打包app(最终生成wgt)# 先导出rm -rf $INIT_CWD/unpackage/dist/build/app-pluscross-env UNI_INPUT_DIR=$INIT_CWD/ UNI_OUTPUT_DIR=$INIT_CWD/unpackage/dist/build/app-plus UNI_PLATFORM=app-plus NODE_ENV=production node bin/uniapp-cli.js# 在zip压缩成wgtcd $INIT_CWD/unpackage/dist/build/app-pluszip -q -r $INIT_CWD/unpackage/release/app-plus.wgt ./

March 22, 2022 · 1 min · jiezi

关于uni-app:uniapp混合开发以微信小程序为例

官网文档uni-app 全局变量的几种实现形式:http://ask.dcloud.net.cn/arti...uni-app反对混合开发。详见:https://uniapp.dcloud.io/hybrid重点中央次要应用计划三:原生开发的小程序仍保留,局部新性能应用uni-app开发。 新建uni-app我的项目我的项目全局变量引入vuex vue create -p dcloudio/uni-preset-vue my-project装置vuexnpm i install vuex --save页面引入vuex,和惯例vue我的项目统一新建页面,page.json写门路混合开发打包 npm run build:mp-weixin -- --subpackage=sub16.dist文件夹内找到打包后的sub1的文件夹 新建一个小程序新建一个文件夹,放入刚刚sub1的文件夹的文件app.json写入subpackages,补充完sub1的页面门路全局变量通信uni-app我的项目是用的vuex,无奈应用微信小程序的全局变量要在App.vue 里定义和小程序同样的变量名,就能够读取到主程序的全局变量App.vueindex.vue setText () { getApp().globalData.text++ this.text = getApp().globalData.text }此处的getApp().globalData.text会读取到主程序的全局变量,进行操作 全局办法通信uni-app我的项目调用微信小程序app.js 定义的办法在小程序里uni-app useMainFun () { getApp().globalData.useMainFun() }uni.app 的页面就能够调用小程序主包的办法了

February 15, 2022 · 1 min · jiezi

关于uniapp:unisimplerouter使用vuerouter管理uniapp路由

笔记中的内容仅实用于HBulider构建的uniapp我的项目,通过其余形式构建的uniapp我的项目请参考uni-simple-router官网 uni-simple-router (hhyang.cn)uniapp用到了vue的很多api,但在路由治理的性能上相较于vue-router还是比拟欠缺的,比方全局导航守卫。 咱们能够通uniapp的插件uni-simple-router来实现相似于vue-router的性能,但多端兼容时,一些用法还须要留神,咱们会讲到。 一、装置如果你的我的项目没有应用package,请先初始化: $ npm init -y装置依赖: $ npm install uni-simple-router uni-read-pagesuni-read-pages的作用是:读取uniapp的pages.json,作为router的配置,把pages.json中的路由配置转换成vue-router配置的模式。二、配置与初始化1、根目录新建 vue.config.js 文件,写入以下内容: //vue.config.jsconst TransformPages = require('uni-read-pages')const {webpack} = new TransformPages()module.exports = { configureWebpack: { plugins: [ new webpack.DefinePlugin({ ROUTES: webpack.DefinePlugin.runtimeValue(() => { const tfPages = new TransformPages({ includes: ['path', 'name', 'aliasPath'] }); return JSON.stringify(tfPages.routes) }, true ) }) ] }}⚠️ 其中要重点关注第 10 行: // ... includes: ['path', 'name', 'aliasPath']// ...includes 中蕴含的是router会读取pages路由中的字段名,后续如果有用到meta等路由信息,能够在 includes 里减少 'meta',在pages路由中写对应的数据,router中就能够获取失去(前面再补充案例) 2、根目录新建并写入router.js,写入以下内容: ...

February 14, 2022 · 2 min · jiezi

关于uni-app:uniapp热更新后不匹配的版本可能造成应用异常的原因和解决方法

问题的呈现线上紧急修复bug的时候,常常应用热更新,最近一次热更新后遇到了问题:更新完后下一次关上app时,提醒了: “本利用应用HBuilder3.2.16编译或对应的cli版本编译,而手机端SKD版本是3.2.9。不匹配的版本可能造成利用异样。”呈现这一提醒的起因是,上一次版本公布的app曾经大半个月了,期间我降级了HBuilder的利用版本,在打包wgt文件时,应用了3.2.16版本的hbuilder打包进去的,而用户手机上安装的是3.2.9版本的hbuilder打包的整包,所以在更新时提醒编译版本和手机内运行的版本不统一。 解决办法1、从新打包apk解决这个问题的办法有很多,其中对app来说,最好的办法就是用高版本的3.2.16打一个新包,并让用户强制更新到新包,因为hbuilder降级会修复很多bug,其中有一些bug是须要咱们关注的,降级到最新版本能够达到缩小bug的目标。 2、回退hbuilder版本然而整包强制更新对用户不太敌对,对于用户来说,最好的办法就是重新安装3.2.9的hbuilder打包,放弃和用户手机对立的版本,在下一次须要整包更新的再降级到最新的hbuilder,这样的毛病就是,当hbuilder修复了一些重要的bug,作为开发者不能第一工夫享受到这个修复,如果这个bug还影响用户,那就必须进行降级了。 3、疏忽弹窗第三种办法就是不解决版本差别,而间接疏忽弹窗,“不匹配的版本可能造成利用异样。”,可能也就代表了不肯定,小版本的更新,少数状况下咱们是能够间接疏忽的,疏忽的办法也很简略: 在manifest.json中,"app-plus"->"compatible"增加配置: "app-plus": { "compatible": { "ignoreVersion": true //true示意疏忽版本查看提示框,HBuilderX1.9.0及以上版本反对 }}, 更多细节内容能够参考官网的阐明: uni-app运行环境版本和编译器版本不统一的问题

February 13, 2022 · 1 min · jiezi

关于uniapp:uniuAdmin基于uniappuViewUI跨端后台管理模板uniapp后台实例

一、前言网上很多后盾管理系统都是pc网页端,手机端的后盾零碎绝对比拟少。而跨端的挪动端后盾治理模板少之又少。于是本人就应用uniapp+uview-ui+uni-ui捣鼓了一个跨设施后盾管理系统uniapp-uadmin我的项目。 uni-uAdmin我的项目是一款基于uniapp+vue.js+uView-ui+uni-ui+mock.js等技术开发的跨端后盾管理系统模板我的项目。 二、技术框架编辑器:HbuilderX3.3.5应用技术:vue+uniapp+uViewUI+mockjs弹窗组件:ua-popup(基于uni-app跨端弹框组件)表格组件:ua-table(基于uni-app封装的多功能表格)自定义组件:uaDock全新的dock格调tabbar组件图表组件:u-charts图表库模仿数据:mock.js 全新的毛玻璃视觉UI质感,应用了图表、自定义表格、表单、瀑布流及图文编辑器等业务模块,动静权限治理,谬误页解决,可编译至H5+小程序+APP端 三、我的项目构造目录 四、公共模板页面整体分为顶部自定义导航条+内容区域+底部dock菜单三大部分。 <!-- 公共页面模板 --><template> <view class="ua__pageview flexbox flex-col" :style="{'--SKIN': $store.state.skin, 'background': bgcolor, 'color': color}"> <slot name="header" /> <!-- //主容器 --> <view class="ua__scrollview flex1"> <slot /> </view> <!-- //底部 --> <slot name="footer" /> <!-- //dock菜单 --> <ua-dock v-if="dock && dock != 'false'" @click="handleDockClick" /> <!-- //函数式弹框 -->![ <ua-popup ref="uapopup" />](/img/bVcXG8X) <!-- //换肤弹框模板 --> <ua-popup v-model="isVisibleSkin" position="right"> <Skin /> </ua-popup> </view></template> ...

January 29, 2022 · 3 min · jiezi

关于uniapp:uniapp-webview如何与H5相互通信

uniapp webview如何与H5互相通信 h5封装的代码能够从这里获取git:https://github.com/MyButifull... 进入主题一、uniapp如何接管H5发送的音讯uniapp端:应用@message来监听H5的音讯 H5端:index.htmel 导入 uni.webview.js 最新版地址:https://js.cdn.aliyun.dcloud....这里有一个坑安卓端运行时会加载不了这个JS,所以要加这个js代码拿下来本地再引入 运行时监听uniappjs加载实现,加载实现后可应用 window.uni.postMessage 发送音讯至uniapp底座。 发送内容要写在data里 document.addEventListener('UniAppJSBridgeReady', function(e) { uni.getEnv(function(res) { console.log('以后环境:' + JSON.stringify(res)); }); // 向uniapp底座发送音讯 uni.postMessage({ data: 'H5发送的音讯' }); });二、uniapp发送音讯给H5

January 28, 2022 · 1 min · jiezi

关于uniapp:20220120uniapp和Android-Studio无线真机调试

uniapp和Android Studio无线真机调试查找adb所在目录 uniapp的adb门路是 HBuilderX\plugins\launcher\tools\adbsAndroid Studio的adb门路是 Android\Sdk\platform-tools Android Studio的sdk目录能够通过as的setting查看如果你电脑上同时有HbuilderX和AS的话,能够用其中一个为了方便使用咱们把adb目录设置为环境变量,如何设置这里就不做阐明了,自行百度adb有俩种模式,tcpip和usb,默认是usb,所以咱们真机调试的时候都是须要连贯数据线的,usb模式下无奈应用无线调试,然而tcpip模式下能够无线,也能够有线咱们设置tcpip模式,第一次设置tcpip是须要应用数据线的,插上数据线当前,咱们执行命令 adb tcpip 5555 ,5555是安卓默认的近程调试端口,你也能够更换,呈现如图所示提醒就是胜利这个时候就能够拔掉数据线了,执行 adb connect 192.168.0.129 ,ip是你手机的ip而后在HbuilderX和AS中看到本人的手机了当前调试的时候只须要 adb connect 手机ip即可,你也能够写一个脚本,更加不便的无线连接手机,我这提供一个繁难的脚本 @ECHO offSET /P ip="IP:[default] 192.168.0.129]"IF "%ip%"=="" ( SET ip="192.168.0.129")adb connect %ip%具体成果自行测试即可强迫症如果想换回usb模式的话,能够执行 adb usb 即可

January 20, 2022 · 1 min · jiezi

关于uni-app:vue3和vite双向加持uniapp性能再次提升

uni-app对vue3 & Vite的降级,是一个渐进式过程: 2020年9月:小程序平台反对 vue3 开发,小程序平台编译器仍然应用webpack;2021年5月:H5平台反对 vue3 开发,H5平台编译器降级为 Vite;2021年8月:App平台反对 vue3 开发,App平台编译器降级为 Vite;2021年11月:小程序平台编译器降级为 Vite;至此,uni-app在全平台反对了 Vite 编译及Vue 3.x 运行。 so,这场持续一年之久的大版本升级,到底给uni-app我的项目带来了哪些晋升? 是时候总结(秀)一波了。 新版 uni-app 框架次要做了三大改良: 重写框架内核:基于vue3 + ts重写内置组件和API,实现更彻底、更高效的tree-shaking;新增反对 Vite 构建工具,在H5平台实现秒开预览;新增反对 Vue3.x,实现更灵便的开发方式,及更高的运行性能;基于这三大改良,uni-app我的项目取得了多快好省四大收益: 更多的语法反对,反对组合式API,业务聚焦,开发效率更高;更快的编译速度,H5平台十倍减速,小程序、App减速30%以上;更好的运行性能,用户端响应更快,体验更好;更小的代码体积,瘦身30%以上,更省体积、更省流量更多的语法反对新版uni-app反对Vue 3.x框架,反对组合式API,可实现更聚焦的业务开发。 Vue 3.x的一些新增个性,uni-app也曾经齐全反对,如: 反对<script setup>反对<style scoped>、<style module>、State-Driven Dynamic CSS(v-bind)反对jsx、tsx(h5,app 平台反对,小程序不反对)另外,在小程序平台,新版uni-app也扩大了更多的语法,如: 更欠缺的模板语法反对(如 class、style 反对函数、变量等,不再局限数组、对象类型)更残缺的 props 反对(如传递函数)更欠缺的 slot 反对(如作用域插槽)更快的编译速度开发者日常工作中,最无聊的就是期待编译构建。 某乎上还有一个”程序员在期待编译的时候都做什么?“的探讨帖,可见编译工夫对开发者而言,是一个如许难堪无聊的碎片工夫。 uni-app本次降级vue3 & Vite后,在编译工夫上有多少改良?带给开发者多少福利?咱们安顿实在测试,以数据谈话。 测试环境阐明: 硬件:RedmiBook 14 二代处理器:Intel(R) Core(TM) i7-1065G7 CPU @ 1.30GHz 内存:16.0 GB操作系统:Windows 11 专业版 64 位操作系统对于编译速度,咱们做了两个维度的比照: 纵向比照:筛选uni-app罕用我的项目模板,在H5、小程序、App平台,别离测试vue 2.6和vue 3.x的编译工夫横向比照:应用业内优良的其它跨端框架,创立默认我的项目模板,记录其编译工夫,和uni-app的vue 3.x版本进行比照uni-app 历史版本纵向比照咱们抉择uni-app默认模板、uni-starter、hello-uniapp三个我的项目模板,别离测试vue 2.6和vue 3.x的编译工夫。 ...

January 11, 2022 · 1 min · jiezi

关于uniapp:uniapp-使用easycom-失效-填坑

看看pages.json文件是否配置了呀

January 6, 2022 · 1 min · jiezi

关于uniapp:20211231uniapp之安卓原生插件开发教程

uniapp之安卓原生插件开发教程筹备hbuilderX,下载app离线SDK,下载Andorid Studio,安卓官网或中文社区证书(能够本人筹备,也能够应用android Studio生成)插件性能简介加法性能,咱们把插件名称起名为leruge-add,办法是add,参数是a和b过程HbuilderX创立一个我的项目在pages/index/index.vue中轻易写一个按钮,而后调用咱们的原生插件leruge-add,代码如下 <template> <view> <button @click="add">加法</button> </view></template><script> export default { methods: { add() { // 引入原生插件 leruge-add let lerugeAdd = uni.requireNativePlugin("leruge-add") // 调用 lerugeAdd.add({ a: 1, b: 2 }, res => { uni.showToast({ title: JSON.stringify(res), icon: 'none' }) }) } } }</script><style></style>申请Appkey,在开发者核心,点击方才创立的appAndroid包名和IOS Bundled都填写成com.android.UniPluginSHA1签名自行百度如何获取吧,这里就不错具体解说了,教程点击保留,生成appkey解压咱们下载好的APP离线SDK,下载地址关上Android Studio,open抉择UniPlugin-Hello-AS我集体习惯project模式,所以切换一下把咱们方才申请的appkey填写到app/src/main/AndroidManifest.xml中,因为开发的是安卓,所以appkey必定也是安卓的把咱们的证书放到app目录下,我的证书名字叫leruge.keystore配置证书,在app/build.gradle的signingConfigs选项中右键UniPlugin-Hello-AS,创立Module填写插件信息配置leruge_add/build.gradle,复制例子uniplugin_module/build.gradle在leruge_add/src/main/java/com/example/leruge/add创立类AddModule实现加法,代码如下 package com.example.leruge.add;import com.alibaba.fastjson.JSONObject;import io.dcloud.feature.uniapp.annotation.UniJSMethod;import io.dcloud.feature.uniapp.bridge.UniJSCallback;import io.dcloud.feature.uniapp.common.UniModule;public class AddModule extends UniModule { @UniJSMethod public void add(JSONObject json, UniJSCallback callback) { int a = json.getIntValue("a"); int b = json.getIntValue("b"); JSONObject res = new JSONObject(); res.put("code", 1); res.put("result", a + b); callback.invoke(res); }}注册插件,在app/src/main/assets/dcloud_uniplugins.json文件中增加,如下到HbuilderX生成本地打包资源把生成的本地打包资源复制到app/src/main/assets/apps目录下配置appid,在app/src/main/assets/data/dcloud_control.xml中配置增加插件project援用,在app/build.gradle中增加组件测试,手机或者虚构设施连贯当前,点击运行进行测试测试胜利当前就生成uniapp插件,点击Android Studio右侧的Gradle,顺次抉择leruge_add/Tasks/other/assembleRelease,双击生成aar包,生成的包在leruge_add/build/outputs/aar目录下创立跟插件雷同名字的文件夹leruge_add,在leruge_add下创立android文件夹和package.json文件aar包放到android文件夹下,package.json最小配置即可,也能够依照理论状况配置 ...

December 31, 2021 · 1 min · jiezi

关于uniapp:uniapp-使用sass-踩坑记

背景:有力吐槽,搞了我好多好多天,始终说版本问题,各种试@vue/cli 创立的支付宝小程序我的项目,无奈应用sass ,应用lang=‘scss’ 报错,尝试过好几个版本都不好使上面是我应用的版本,大家避避坑,如果你们能够 那当我没说 "node-sass": "^4.14.1", "sass-loader": "^7.3.1","node-sass": "^4.14.1", "sass-loader": "^7.1.0", ...还有几个遗记了 (每次都是给整个node_module删除重新安装的)上面进入正题 : 我本人的 node版本: v12.16.0首先给本人的包卸载掉npm uninstall node-sass sass-loader- 装置sass ,留神这里是sass 不是node-sassnpm install sass npm install sass-loader@8.0.2不输出命令,就间接在packagejson文件增加这两个,本人执行npm install也能够 操作完这些,发现我还报错,很怄气,刚好电脑很卡 我就重启一下,emm 这货竟然好了,泪目。。。

December 30, 2021 · 1 min · jiezi

关于uniapp:uniapp-配置eslint-prettier

背景: 应用的是vue/cli创立的支付宝小程序我的项目话不多说上菜 装置eslint ,因为我的项目中应用的是cli搭建的,所以间接应用 vue add @vue/eslint vue add @vue/eslint而后依据本人爱好抉择格调,这里我抉择的是prettier配置.eslintrc.js 在我的项目根目录新建文件.eslintrc.js,依据本人需要配置规定module.exports = { root: true, env: { node: true, }, globals: { uni: "readonly", my:"readonly" }, extends: ["plugin:vue/essential", "eslint:recommended", "@vue/prettier"], parserOptions: { parser: "babel-eslint", }, rules: { "no-console": process.env.NODE_ENV === "production" ? "warn" : "off", "no-debugger": process.env.NODE_ENV === "production" ? "warn" : "off", "no-sequences": 0, "import/named": 0, "no-useless-concat": 0, "no-unreachable": 0, "no-case-declarations": 0, "no-continue": 0, "no-redeclare": 0, "block-scoped-var": 0, "operator-assignment": 0, "no-multi-assign": 0, "comma-dangle": 0, "prefer-const": 0, "semi": 0, "eol-last": 0, "linebreak-style": 0, "no-unused-vars": 0, "no-useless-computed-key": 0, "default-case": 0, "prefer-destructuring": 0, "arrow-parens": 0, 'no-var': 2, // 要求应用 let 或 const 而不是 var "comma-spacing": 0, "no-mixed-operators": 0, "radix": 0, "prefer-promise-reject-errors": 0, "arrow-body-style": 0, "prefer-rest-params": 0, "no-restricted-syntax": 0, "vars-on-top": 0, "import/no-named-as-default": 0, "import/extensions": 0, "import/no-named-as-default-member": 0, "guard-for-in": 0, "no-unused-expressions": 0, "import/prefer-default-export": 0, "no-shadow": 0, "no-nested-ternary": 0, "no-empty": 0, "eqeqeq": 0, "camelcase": 0, "prefer-template": 0, "dot-notation": 0, "prefer-arrow-callback": 0, "no-plusplus": 0, "no-else-return": 0, "one-var-declaration-per-line": 0, "consistent-return": 0, "no-param-reassign": 0, "max-len": 0, "no-lonely-if": 0, "array-callback-return": 0, "prefer-object-spread": 0, "import/order": 0, "import/newline-after-import": 0, "func-names": 0, "no-console": 0, "no-underscore-dangle": 0, "no-useless-escape": 0 },};配置eslint不必查看的文件 .eslintignore根目录 新建文件.eslintignore ,依据理论需要配置/utils/subpackage/utils/node_modules/postcss.config.js/babel.config.js最初配置.prettierrc.js 根目录新建.prettierrc.js文件,依据理论需要配置//配置 prettier 。prettierrc.jsmodule.exports = { // 单行最大长度 printWidth: 100, // 设置编辑器每一个程度缩进的空格数 tabWidth: 2, // 在句尾增加分号 semi: true, // 应用单引号 singleQuote: true, jsxSingleQuote: true, // 在任何可能的多行中输出尾逗号。 trailingComma: 'all', // 在对象字面量申明所应用的的花括号后({)和前(})输入空格 bracketSpacing: true, // 在多行JSX元素最初一行的开端增加 > 而使 > 独自一行(不适用于自闭和元素) jsxBracketSameLinte: false, // 为单行箭头函数的参数增加圆括号。 alwaysParens: 'always', // 行完结 endOfLine:"auto", vueIndentScriptAndStyle: true, //是否缩进Vue 文件中的代码<script>和<style>标签 htmlWhitespaceSensitivity:'ignore',//HTML 空白敏感度};最初一步在package.json文件中批改一下lint的命令,批改为 ...

December 30, 2021 · 2 min · jiezi

关于uniapp:uniapp-swiper

swiper 切换知识点:获取页面/组件高度// 重点let info = uni.createSelectorQuery().select(".swiper-item");info.boundingClientRect(function(data) { //data - 各种参数 _this.sceneH = data.height // 获取元素宽度 console.log(data.height,'bbbbbbbbbbb')}).exec()swiper轮播 监听高度 // swiper切换此函数被监听swiperChange(e) { let _this = this this.selectStatus = e.detail.current; if (e.detail.current == 0) { // 重点 let info = uni.createSelectorQuery().select(".swiper-item"); info.boundingClientRect(function(data) { //data - 各种参数 _this.sceneH = data.height // 获取元素宽度 console.log(data.height,'bbbbbbbbbbb') }).exec() } if (e.detail.current == 1) { let info = uni.createSelectorQuery().select(".swiper-item2"); console.log(info) info.boundingClientRect(function(data) { //data - 各种参数 console.log(data) _this.sceneH = data.height // 获取元素宽度 console.log(data.height,'aaaaaaaaaaaaaaaaaaaaaa') }).exec() } }, 页面 全副写法<template> <view class="collectWrapper"> <view class="tabbar"> <view :class="selectStatus == 0 ? 'selectStatus' : '' " @tap="changeTabs(0)">tabs1</view> <view :class="selectStatus == 1 ? 'selectStatus' : '' " @tap="changeTabs(1)">tabs2</view> <view :class="selectStatus == 2 ? 'selectStatus' : '' " @tap="changeTabs(2)">tabs2</view> </view> <view class="uni-padding-wrap"> <view class="page-section swiper"> <view class="page-section-spacing"> <swiper class="swiper" :duration="duration" @change="swiperChange" :current="currentVal"> <swiper-item><view class="swiper-item">内容区域一</view></swiper-item> <swiper-item><view class="swiper-item">内容区域二</view></swiper-item> <swiper-item><view class="swiper-item">内容区域三</view></swiper-item> </swiper> </view> </view> </view> </view></template><script>export default { data() { return { background: ['color1', 'color2', 'color3'], duration: 500, // 管制swiper的显示 currentVal: 0, // 顶部tabs显示状态 selectStatus: 0, } }, methods: { // 点击顶部tabs触发该函数 changeTabs(i) { this.currentVal = i; this.selectStatus = i; }, // swiper切换此函数被监听 swiperChange(e) { this.selectStatus = e.detail.current; }, }}</script><style lang="scss">page { width: 100%; height: 100%;}.selectStatus { color: rgba(19, 149, 244, 1); border-bottom: 4rpx solid rgba(19, 149, 244, 1);}.collectWrapper { // 确保swiper 内容填满设施,若需自适应只需勾销掉100%即可 width: 100%; height: 100%; .tabbar { width: 100%; height: 70rpx; } .uni-padding-wrap { height: 100%; .page-section-spacing { height: 100%; } .swiper { height: 100%; } }}</style>

December 15, 2021 · 2 min · jiezi

关于uni-app:拥抱简洁代码vue3中的script-setup最强解析

vue3除了Composition API是一个亮点之外,尤大大又给咱们带来了一个全新的玩意 —— script setup,对于setup大家置信都不生疏,而对于script setup有些同学则示意难以了解,那么从当初开始,这一篇文章将让你一看就懂。 ref与reactive在setup中,咱们领有ref和reactive俩个api去创立一个响应式变量,这俩者存在的区别是ref是针对根本类型的响应,而reactive是针对援用类型的响应。 import { ref, reactive } from 'vue'const data = ref('123')const other = reactive({ is: '123' })console.log(data.value)console.log(other.is)// 这里须要留神,reactive的对象能够间接拜访,批改外部的子数据,而data须要应用.value拜访批改,如下data.value = '666' // okdata = '666' // noother.is = '666' // okother = '666' // no导入自定义组件在之前的optionApi中咱们应用的是components: { ... } 的形式导入自定义组件,而在当初,咱们只须要间接import组件即可应用 <template> <Button>OK!</Button></template><script setup> import Button from 'element-ui-plus'</script>自定义办法在之前的optionApi中咱们应用的是在methods中写自定义办法,而这里咱们间接定义一个办法或者变量,在template中间接应用即可 <template> <button @click="touchMe">OK!</button> <button @click="touchIt">OK!</button></template><script setup> import { ref, reactive } from 'vue' const text = ref('123') const touchMe = () => { text.value = '666' } function touchIt() { text.value = '666' }</script>个别状况下笔者倡议开发者都应用ref,因为ref适用范围更广。 ...

December 12, 2021 · 1 min · jiezi

关于uni-app:uniapp过滤器兼容全平台写法

过滤器过滤器是vue框架里格式化的性能,它十分不便,在原始的vue外面能够用于模板插值和组件属性 <div>{{ val | num(0) }}</div><div :id="val | num(0)"></div>当初的小程序广泛提供了一套脚本语言能够实现雷同的性能,比方微信的wxs,百度与字节的sjs。uni-app文档给的例子外面引入了多个版本的js文件,然而兼容性仍然不够好,而且齐全不兼容html-vue框架。 <script module="utils" lang="filter" src="./utils.filter.js"></script><script module="utils" lang="sjs" src="./utils.sjs"></script>其实在vue外面过滤器是注册在$options上的。依据这点,能够写出一种兼容所有平台的写法。 <!-- 模板插值与之前统一 --><div>{{ val | num(0) }}</div><!-- 属性赋值改为表达式 --><input :value="$options.filters.num(val, 0)"/><!-- 类名属性须要加上中括号 --><img :class="[$options.filters.num(val, 0)]"/>

December 3, 2021 · 1 min · jiezi

关于uni-app:uniapp框架如何实现仿微信相册插件-图视频编辑-压缩

在上上篇文章中(),咱们基于uniapp框架实现了仿微信相册中的拍照+录像性能。明天,就持续在uni-app中实现: 1: 图片编辑 2: 视频编辑 3: 文件压缩 成果预览: 技术实现开发环境:HbuilderX + nodejs技术框架:uniapp + vue2.x测试环境:App端(Android + IOS)、代码:开源 成果预览 业务剖析 这里次要是承接上次写的仿微信相册(https://segmentfault.com/a/11...)的持续扩大上来,对于插件而言,当用户点击图片非选区的地位的时候,插件会调用回调事件反馈点击编辑事件,具体如下: // 相册事件回调AlbumCallbackHanlder (res) { let { type, data } = res switch (type) { // 触发点击编辑图视频 case 'onClickEditImage': // 这里的data就是触发的文件门路 console.log(res); break; default: console.log(res) break; }}当咱们触发了编辑事件之后,咱们就能够开始调用api执行编辑图视频 编辑图视频编辑图视频相对来说简略,咱们只须要传入文件门路,插件本人外部会主动解析应该是编辑图片还是编辑视频,然而咱们提供的门路必须是原生可辨认的门路, 以 / 结尾。如果是非凡门路,能够应用plus自带的办法进行门路转换,具体如下: let localPath = plus.io.convertLocalFileSystemURL(path)引入插件对象 var sdkwx = uni.requireNativePlugin('Zhimi-EditImage');编辑图视频 // path 原文件门路// distPath 编辑后文件保留门路sdkwx.edit(path, distPath => { console.log(distPath)})这里其实很简略的就是传入门路之后就会弹出来文件编辑界面,然而不一样的是如果咱们编辑之后须要同步的更新到相册中,咱们须要调用以下办法:更新相册Item // 这里编辑实现之后调用,过后调用默认更新最初一次编辑的文件albumView.changeListEditImage(path)图片视频压缩在这里个别失去的是原图,原视频。随着当初手机设施的性能晋升,相机分辨率也随之晋升,拍进去的视频图片往往曾经超过了1080p的领域了,对于服务器来说压力十分在,在这里咱们能够通过插件内置的压缩模块压缩图片视频,一共有3种压缩形式。 引入压缩模块 var sdkwx = uni.requireNativePlugin('Zhimi-compression');压缩图片 ...

November 28, 2021 · 1 min · jiezi

关于uniapp:uniapp-瀑布流

<template> <view class="Index"> <!-- 瀑布流布局列表 --> <view class="pubuBox"> <view class="pubuItem"> <view class="item-masonry" v-for="(item, index) in comList" :key="index"> <image :src="item.img" mode="widthFix"></image> <view class="listtitle"> <!-- 这是没有高度的父盒子(下半局部) --> <view class="listtitle1">{{ item.name }}</view> <view class="listtitle2"> <text class="listtitle2son">¥</text> {{ item.commdityPrice }} </view> <view class="listtitle3"> 来自莫成尘的旗舰店 </view> </view> </view> </view> </view> </view></template><script> export default { data() { return { comList: [{ img: "http://pic1.sc.chinaz.com/Files/pic/pic9/202002/zzpic23346_s.jpg", name: '商品的名称,能够很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长', commdityPrice: 100 }, { img: 'http://pic1.sc.chinaz.com/Files/pic/pic9/202002/zzpic23346_s.jpg', name: '商品名称会在超出两行时候主动折叠', commdityPrice: 100 }, { img: 'http://pic1.sc.chinaz.com/Files/pic/pic9/202002/zzpic23346_s.jpg', name: '只有一行题目时高度为39', commdityPrice: 100 }, { img: 'http://pic1.sc.chinaz.com/Files/pic/pic9/202002/zzpic23346_s.jpg', name: '具体款式您能够自定义', commdityPrice: 100 }, { img: 'http://pic1.sc.chinaz.com/Files/pic/pic9/202002/zzpic23346_s.jpg', name: 'vue的H5页面也是如此应用', commdityPrice: 100 } ], //商品列表 }; }, onShow() {}, onLoad() {}, methods: {}, };</script><style scoped="scoped" lang="scss"> //瀑布流 page { background-color: #eee; height: 100%; } .pubuBox { padding: 22rpx; } .pubuItem { column-count: 2; column-gap: 20rpx; } .item-masonry { box-sizing: border-box; border-radius: 15rpx; overflow: hidden; background-color: #fff; break-inside: avoid; /*防止在元素外部插入分页符*/ box-sizing: border-box; margin-bottom: 20rpx; box-shadow: 0px 0px 28rpx 1rpx rgba(78, 101, 153, 0.14); } .item-masonry image { width: 100%; } .listtitle { padding-left: 22rpx; font-size: 24rpx; padding-bottom: 22rpx; .listtitle1 { line-height: 39rpx; text-overflow: -o-ellipsis-lastline; overflow: hidden; text-overflow: ellipsis; display: -webkit-box; -webkit-line-clamp: 2; line-clamp: 2; -webkit-box-orient: vertical; min-height: 39rpx; max-height: 78rpx; } .listtitle2 { color: #ff0000; font-size: 32rpx; line-height: 32rpx; font-weight: bold; padding-top: 22rpx; .listtitle2son { font-size: 32rpx; } } .listtitle3 { font-size: 28rpx; color: #909399; line-height: 32rpx; padding-top: 22rpx; } } .Index { width: 100%; height: 100%; }</style>

November 22, 2021 · 2 min · jiezi

关于uni-app:uniapp框架如何实现仿微信相册-图视频过滤相册选择功能

明天咱们分享基于uniapp + vue实现仿微信相册实例,该插件齐全还原了微信相册的性能 1: 相册抉择 2: 图片,视频类型过滤 3: 自定义相册界面UI 技术实现 开发环境:HbuilderX + nodejs技术框架:uniapp + vue2.x测试环境:App端(Android + IOS)代码:开源成果概览  界面布局这里仿微信相册界面次要还是款式为主,性能上应用了“智密相册-自定义原生相册”插件,应用插件实现相册的相干性能,而后咱们本人实现仿微信相册界面。这里布局代码次要如下 <view class="album-container" :style="{ paddingTop: statusBarHeight + 'px' }"> <!-- 顶部栏,用于显示按钮和下一步 --> <view class="album-title-bar"> <view class="album-title-bar__left" @click="doClear"> <image class="album-close-btn" src="../../static/icon_close.png" mode="widthFix"></image> </view> <view class="album-title-bar__center" @click="showAlbumSelect = !showAlbumSelect"> <view class="album-title-bar__center-album-btn"> <text class="album-title-bar__center-name">{{ albumName || '所有照片' }}</text> <view class="album-title-bar__center-arrow"> <image class="album-title-bar__center-arrow-inner" src="../../static/icon_arrow_down.png" mode="widthFix"></image> </view> </view> </view> <view class="album-title-bar__right" @click="doFinish"> <text class="album-title-bar__right-btn">下一步{{ selectedCount ? `(${selectedCount})` : '' }}</text> </view> </view> <!-- 插件自带的原生控件 --> <zhimi_album_view ref='albumView' class="album-elem" :class="{ 'show-album-ctx': !showAlbumSelect }"></zhimi_album_view> </view>这里有个重点,因为咱们去掉了原生的标题栏,这须要在pages.json中进行配置,具体配置如下 { "path": "pages/index/wxAlbum", "style": { "navigationStyle":"custom" }},相册控件初始化在这里咱们次要是操作原生控件“zhimi_album_view”提供的办法,首先咱们须要执行控件办法设置相册类型,回调事件,以及获取相册列表,具体如下设置回调事件 ...

November 13, 2021 · 2 min · jiezi

关于uniapp:uniapp-学习笔记

注意事项背景图片不反对本地图片 反对网络门路/base64格局字体同上 也不反对本地字体rpa计算形式设计稿 1px / 设计稿基准宽度 = 框架款式 1rpx / 750rpx若设计稿宽度为 750px,元素 A 在设计稿上的宽度为 100px,那么元素 A 在 uni-app 外面的宽度应该设为:750 * 100 / 750,后果为:100rpx。若设计稿宽度为 640px,元素 A 在设计稿上的宽度为 100px,那么元素 A 在 uni-app 外面的宽度应该设为:750 * 100 / 640,后果为:117rpx。若设计稿宽度为 375px,元素 B 在设计稿上的宽度为 200px,那么元素 B 在 uni-app 外面的宽度应该设为:750 * 200 / 375,后果为:400rpx。 疾速判断运行环境uEnvDev、uEnvProd 能够疾速生成对应 development、production 的运行环境断定代码。// uEnvDevif (process.env.NODE_ENV === 'development') { // TODO}// uEnvProdif (process.env.NODE_ENV === 'production') { // TODO}

November 9, 2021 · 1 min · jiezi

关于uniapp:uniapp-实现pagesjson的模块加载

对于一个日渐宏大的下uni-app我的项目,pages.json文件会变得有大有难以保护,所有就思考怎么样将pages.json文件才分易保护的小文件。起初在浏览他的源码时发现了这个 const pagesJsonJsFileName = 'pages.js'function processPagesJson (pagesJson, loader = { addDependency: function () {}}) { const pagesJsonJsPath = path.resolve(process.env.UNI_INPUT_DIR, pagesJsonJsFileName) if (fs.existsSync(pagesJsonJsPath)) { delete require.cache[pagesJsonJsPath] const pagesJsonJsFn = require(pagesJsonJsPath) if (typeof pagesJsonJsFn === 'function') { pagesJson = pagesJsonJsFn(pagesJson, loader) if (!pagesJson) { console.error(`${pagesJsonJsFileName} ${uniI18n.__('cliShared.requireReturnJsonObject')}`) } } else { console.error(`${pagesJsonJsFileName} ${uniI18n.__('cliShared.requireExportFunction')}`) } } // 将 subpackages 转换成 subPackages if (pagesJson.subpackages && !pagesJson.subPackages) { pagesJson.subPackages = pagesJson.subpackages delete pagesJson.subpackages } let uniNVueEntryPagePath if (pagesJson.pages && pagesJson.pages.length) { // 如果首页是 nvue if (isNVuePage(pagesJson.pages[0])) { uniNVueEntryPagePath = pagesJson.pages[0].path } } // pages filterPages(pagesJson.pages) // subPackages if (Array.isArray(pagesJson.subPackages) && pagesJson.subPackages.length) { pagesJson.subPackages.forEach(subPackage => { filterPages(subPackage.pages, subPackage.root) }) } if (uniNVuePages.length) { // 间接挂在 pagesJson 上 pagesJson.nvue = { pages: uniNVuePages.reverse() } if (uniNVueEntryPagePath) { pagesJson.nvue.entryPagePath = uniNVueEntryPagePath } } return pagesJson}于是就有上面这个工具仓库地址uni-module-pages ...

October 11, 2021 · 1 min · jiezi

关于uni-app:关于uni-开发跨平台App的坑

1.uni.share()问题,分享图文时,图片不显示?解决办法:将图片大小进行解决,大概为20k,应用腾讯云oss 图片地址增加 '?imageView2/2/w/100/h/100/q/60',进行品质压缩,根本能够应用2.uni对于组件款式兼容微信小程序的坑//自定义组件 在微信小程序无奈失效的问题//须要在组件内减少属性 解决办法:export default { options: { styleIsolation: 'shared' }, //将属性失效至页面}3.对于uni-app input组件无奈监听 keyup.enter事件问题解决办法:<input class="search_input" type="text" placeholder-class="search_placeholder" placeholder="搜寻资讯题目,关键词" v-model="queryParams.keyword" confirm-type="search" @confirm="handleSearch" /> //最初一句confirm-type="search"最为重要4.对于uni 自适应 rpx 在ipad pro不失效问题解决办法:须要在pages.json中globalStyle字段下进行非凡配置 "globalStyle": { "navigationBarTextStyle": "white", "navigationBarTitleText": "uni-app", "navigationBarBackgroundColor": "#007AFF", "backgroundColor": "#FFFFFF", "rpxCalcMaxDeviceWidth": 960, // rpx 计算所反对的最大设施宽度,单位 px,默认值为 960 "rpxCalcBaseDeviceWidth":1024, // rpx 计算应用的基准设施宽度,设施理论宽度超出 rpx 计算所反对的最大设施宽度时将按基准宽度计算,单位 px,默认值为 375 "rpxCalcIncludeWidth": 750 // rpx 计算非凡解决的值,始终按理论的设施宽度计算,单位 rpx,默认值为 750}5.对于uni canvas各类问题canvas操作时 尤其是canvasGetImageData、canvasPutImageData 其width、height 特地留神 整数 以及 边界值 ,极有可能造成fail,在进行图片变色 canvasPutImageData时,在 微信小程序 兼容上会有通明局部 间接将底色笼罩景象,h5以及app失常,须要将图片信息获取之后 拼接到另一个canvas实现背景色浮现,uni.createCanvasContext(canvasId,this);uni.canvasGetImageData(Object,this);uni.canvasPutImageData(Object,this);三个 this 很重要,遗记增加 及其容易产生bug ...

September 27, 2021 · 1 min · jiezi

关于uni-app:uniapp-下拉刷新

"globalStyle": { // "enablePullDownRefresh": true // 开启全局下拉刷新 "pullToRefresh": { // 下拉款式 "support": true, "color": "#000000", "style": "circle" } }, "pages": [ { "path": "pages/home", "style": { // 开启单页刷新 "enablePullDownRefresh": true, } }, ]

September 24, 2021 · 1 min · jiezi

关于uniapp:unittLive基于uniappuViewUI短视频聊天直播实例

一、我的项目概述uniapp-ttlive 一款基于uni-app+uview-ui+vue.js+uapopup等技术混合开发的多端仿造抖音短视频/直播/聊天我的项目。反对全屏沉迷式、高低滑动切换视频等性能。 二、预览成果如下图:在h5、小程序、APP端编译成果 三、编码技术编码器/技术:HbuilderX3.1.21+Uniapp+Nvue+Vuex+UapopupUI组件库:uView-ui / uni-ui矢量图标库:iconfont字体图标弹窗组件:UApopup 基于uni-app封装跨端弹窗组件自定义导航条+底部菜单栏编译反对:H5+小程序+APP端 四、性能个性✅ 反对全屏沉迷式通明模式✅ 顺滑的高低滑动体验✅ 迷你工夫进度条✅ 自定义组件反对Nvue页面 五、目录构造/编译 我的项目中应用的组件库是uview-ui,多平台疾速开发UI框架。 main.js配置import Vue from 'vue'import App from './App'import uView from 'uview-ui'Vue.use(uView)import API from '@/common/request'Vue.prototype.$api = API// 引入状态治理import Store from './store'Vue.prototype.$store = StoreVue.config.productionTip = falseApp.mpType = 'app'// #ifdef APP-PLUSplus.navigator.closeSplashscreen()// #endifconst app = new Vue({ ...App})app.$mount()思考到Nvue页面不反对prototype原型全局挂载,改为应用globalData来管制。 /** * 主入口配置 * @author xiaoyan */<script> export default { globalData: { // 全局设置状态栏和导航栏高度 statusBarH: 0, customBarH: 0, }, onLaunch: function() { uni.getSystemInfo({ success: (e) => { // 获取手机状态栏高度 let statusBar = e.statusBarHeight let customBar // #ifndef MP customBar = statusBar + (e.platform == 'android' ? 50 : 45) // #endif // #ifdef MP-WEIXIN // 获取胶囊按钮的布局地位信息 let menu = wx.getMenuButtonBoundingClientRect() // 导航栏高度 = 胶囊下间隔 + 胶囊上间隔 - 状态栏高度 customBar = menu.bottom + menu.top - statusBar // #endif // #ifdef MP-ALIPAY customBar = statusBar + e.titleBarHeight // #endif // 兼容nvue写法(H5/小程序/APP/APP-Nvue) this.globalData.statusBarH = statusBar this.globalData.customBarH = customBar } }) }, onShow: function() { console.log('App Show') }, onHide: function() { console.log('App Hide') } }</script>uniapp自定义navbar+tabbar组件大家看到的顶部导航条及底部菜单栏,是全新开发的反对nvue组件。 ...

September 20, 2021 · 4 min · jiezi

关于uni-app:uniapp的项目如何去掉顶端uniapp字样

1. 先看一下有uni-app字样的状况: 2. 没有uni-app字样: 3. 如何去掉在pages.json页面中退出 "titleNView": false 当然也能够批改uni-app的款式:文字改为“这里显示uni-app字样”,背景色改为“#007AFF”显示成果

August 15, 2021 · 1 min · jiezi

关于uni-app:uniapp开发App引导页

App的疏导页是当用户第一次关上一款App时所展现的3-5精美的图片,用于告知用户产品的性能及特点。好的疏导页会促使用户对产品减少更多的趣味,当然这是UI设计的能力体现了,只管很多人都会疾速的滑过。对于开发人员怎么去增加这几张图片只有在用户第一次关上app时展现呢。 其实原理很简略,在本地设置标识flag,默认为false,从而进入疏导页,进入之后,flag设置为true,下次进入天然不会展现的;当然这个疏导页能够设置为一个页面,用轮播图搁置几张疏导页;只有不革除本地的flag缓存,则疏导页只会呈现一次;以uniapp开发的我的项目为例:在onLaunch函数中,查看flag是否为false,如果为false,则跳转到疏导页面,在疏导页中可设置跳转到首页。留神,最好用reLaunch,防止,用户物理按键返回;为true,则存储flag到本地。原理既是如此;然而理论开发时,会发现,存在闪屏景象,这样用户的体验就不太好,所以比拟要害的中央就在于这块,还是以uniapp为例,须要在uniapp的源码视图下将splashscreen的设置进行批改,将autoclose改为false,在onLaunch中通过设置延迟时间调用plus.navigator.closeSplashscreen办法来敞开启动图。delay设置为0。这样启动图的设置就ok了。以下封装了查看是否进入疏导页的办法,仅供参考下: guidePage(){ try { // 获取本地存储中launchFlag标识 console.log(uni.getStorageSync('first_flag')) if(!uni.getStorageSync('first_flag')){//第一次进入app,为false // 进入疏导页 uni.reLaunch({ url:'/pages/GuidePage/GuidePage', }) } } catch(e) { //error // 设置为true uni.setStorageSync('first_flag', true); }}Tip: 在屡次的利用中发现,如果在手机自身比拟卡的状况下,用户在第一次开启app时,还是会存在首页在疏导页之前呈现,这种状况的解决形式是将疏导页默认设置为主页,即在路由治理中,将疏导页写在第一个,而后通过flag去判断是否跳转到首页;以上的疏导页开发只是提供一种思路,还有很多其余的形式,比方后端去管制是否展现疏导页,疏导页的动态变化。当然问题自身不难实现,关键在于理论利用时所存在的问题。

August 10, 2021 · 1 min · jiezi

关于uni-app:uniapp四步搞定支付

传统的开发领取须要前后端做很多工作,各种参数的解决,签名,秘钥的验证校验等,尤其是波及到多种不同的平台领取,更是繁琐;而且以往的领取是由后端主导的,如果后端是个菜鸡,那么做这个领取会相当累人,所以为了防止这种阻碍,前端只须要一个人就能搞定领取,uniapp的云开发提供了一种形式,一套代码兼容不同的领取形式,小程序,App,H5等一网打尽,最次要还收费。上面就介绍下这种无脑开发的领取形式有多简略,但前提是应用的框架要可能创立uniCloud云空间,否则下列的做法可能不适宜! 第一步:我的项目创立云空间; 在Hbuilderx中抉择我的项目,右键创立云开发环境,目前只有腾讯云和阿里云,阿里云是收费的,如果是仅仅做领取,阿里云是足够的;我的项目中如果曾经存在云空间,则不必创立;创立之后,会在cloundfunctions文件夹中含有common目录和database,common是搁置公共模块的目录,database是数据库相干的目录,只做领取的话,不波及到database目录; 第二步:引入uni-pay插件: 能够通过在插件市场引入或者npm的形式下载,当初次要说的是插件市场引入,引入之后,会在common目录下引入uni-pay模块,外面默认有index.js和package.json文件;之后再上传公共模块到服务空间; 第三步:云函数的创立及编写: 云函数的创立,在uniCloud/cloudfunctions中右键创立云函数,会默认生成index.js文件,是该云函数的入口文件;留神:云函数的创立同名,则会笼罩; 如果该云函数依赖某个公共模块的函数,须要装置该公共模块函数的依赖;如果uni-pay是通过uni_modules引入的,这时在云函数目录右键“治理公共模块依赖”,须要哪个公共模块,则抉择那个;依赖装置之后,在index.js中引入uni-pay;如果uni-pay是通过非uni_modules装置的,则须要先给该函数通过npm init -y生成package.json文件,再在该云函数中通过终端,执行npm install '须要引入的云函数模块门路'; 云函数的编写,以App的微信领取为例: 先要引入uni-pay; const unipay = require('unipay');再初始化unipay实例const unipayIns = unipay.initWeixin({ appId: 'your appId',//利用在对应领取平台的appId mchId: 'your mchId',//商户号 key: 'you parterner key',//领取秘钥 pfx: fs.readFileSync('/path/to/your/pfxfile'), // p12文件门路,应用微信退款时须要,须要留神的是阿里云目前不反对以相对路径读取文件,请应用绝对路径的模式})领取的参数,以app 的微信领取为例 exports.main = async function (event,context) { //event是客户端传过来的参数 let orderInfo = await unipayIns.getOrderInfo({ body: '商品形容', outTradeNo: '商户订单号', totalFee: 1, // 金额,单位分 tradeType:'APP' notifyUrl: 'https://xxx.xx' // 领取后果告诉地址 }) return { orderInfo }}第四步:客户端调用云函数 uniCloud.callFunction({ name: 'getOrderInfo', //这个name是须要调用的云函数名称 data:{},//领取所须要的参数,用于向云函数传递 success(res) { uni.requestPayment({ // #ifdef APP-PLUS provider: ‘wxpay’// App端此参数必填,能够通过uni.getProvider获取 // #endif // #ifdef MP-WEIXIN ...res.result.orderInfo, // #endif // #ifdef APP-PLUS || MP-ALIPAY orderInfo: res.result.orderInfo, // #endif ...res.result.orderInfo success(){ 返回领取后果 }, fail(){} }) }})至此,领取的流程曾经完结,付款后果会返回,如果须要查问订单,则须要调用unipayIns.orderQuery函数去查问了。 ...

August 10, 2021 · 1 min · jiezi

关于uniapp:crmeb-小程序包大小超过2M的解决方法

crmeb 小程序包大小超过2M的解决办法微信限度了小程序的代码包不能超过2MB,这次要是出于对小程序启动速度的思考。然而,2MB 的大小也限度了小程序性能的扩大,如果大小超出了2MB该如何解决呢? 优化代码,删除掉不必的代码图片压缩或者上传服务器个别图片所占用的空间比拟大,尽量不要放在小程序本地文件夹中,如果图片不多的话能够对图片进行压缩,图片压缩平台:https://tinyjpg.com/另外, 通过cli命令创立的uni app我的项目,可将图片或字体图标放入assets文件夹下,通过require引入, 也可缩小主包大。分包加载:什么是分包加载: 小程序个别都是由某几个性能组成,通常这几个性能之间是独立的,但会依赖一些公共的逻辑,且这些性能个别会对应某几个独立的页面。那么小程序代码的打包,能够依照性能的划分,拆分成几个分包,当须要用到某个性能时,才加载这个性能对应的分包。 对于用户来说,小程序加载流程变成了: 1.首次启动时,先下载小程序主包,显示主包内的页面; 2.当进入某个分包的页面,再下载这个对应分包,下载结束后,显示分包的页面。 采纳分包加载,对开发者而言,能使小程序有更大的代码体积,承载更多的性能与服务;而对用户而言,能够更快地关上小程序,同时在不影响启动速度前提下应用更多功能。 分包的划分: 在配置前,依照性能对各个分包的内容进行划分,将同一个性能下的页面和逻辑放在童改一个目录下,把一些跨性能的公共逻辑放在主包下。 在分包划分时需注意: 1.包与包之间性能尽可能独立,防止分包与分包之间援用上的耦合。因为分包的加载是由用户操作触发的,并不能确保某分包加载时,另外一个分包就肯定存在,这个时候可能会导致 JS 逻辑异样的状况,例如报「"xxx.js" is not defined」这样的谬误; 2.一些公共的自定义组件,要放在主包内。 分包的配置: 在uni app中通过cli初始化的小程序目录构造如下: ├── src ├── main.js ├── App.vue ├── pages.json ├── manifest.json ├── orderPackages │ └── pages │ ├── goodsDetail │ └── myorder ├── pages │ ├── index │ └── user └── utils 需在pages.json中配置subPackages字段,在subPackage外面申明我的项目的分包构造: crmeb 小程序包大小超过2M的解决办法目前小程序分包大小的限度: 整个小程序所有分包大小不超过 4M 单个分包/主包大小不能超过 2M 以上只列举了uni app框架分包加载的步骤, 原生小程序分包办法依据官网文档即可疾速实现,小程序框架虽多, 大都大同小异,如果后续有应用其余框架进行开发,会进行补充。 如果你感觉这篇文章对你有点用的话,麻烦请给咱们的开源我的项目点点star:http://github.crmeb.net/u/defu 不胜感激 ! ...

August 9, 2021 · 1 min · jiezi

关于uni-app:uniapp项目瀑布流布局完美解决方案

预览图 应用教程间接复制代码 <hd-list/> 列表布局数据本人写 <template> <view class="waterfall-wrap"> <view class="waterfall-list"> <view class="left"> <hd-list :listData="item" v-for="(item,index) in goodsLeftList" :key="index" @onImageLoad="onImageLoad" ></hd-list> </view> <view class="right"> <hd-list :listData="item" v-for="(item,index) in goodsRightList" :key="index" @onImageLoad="onImageLoad" ></hd-list> </view> </view> </view></template><script>import hdList from "../component/hd-list.vue";export default { name: "waterfall", props: { listData: { type: Array, default: [] } }, components: { hdList }, watch: { /** * 监听listData数据 */ listData: { handler: function(data) { data.length > 0 && this.waterfallImage(); }, immediate: true } }, data() { return { goodsListCount: 0, //加载第i张图片 // 左侧商品列表 goodsLeftList: [], goodsLeftListHeight: 0, // 右侧商品列表 goodsRightList: [], goodsRightListHeight: 0 }; }, methods: { // 图片绑定事件,通过比拟左右列表高度,实现瀑布流展现 onImageLoad: function(e) { let divWidth = 342; //显示的单栏宽度,我设为342rpx let oImgW = e.detail.width; //图片原始宽度 let oImgH = e.detail.height; //图片原始高度 let rImgH = (divWidth * oImgH) / oImgW + 32; //依据宽高比计算以后载入的图片的高度 if (this.goodsListCount == 0) { this.goodsLeftListHeight += rImgH; //第一张图片高度加到goodsLeftListHeight this.goodsListCount++; //图片索引加1 this.goodsRightList.push(this.listData[this.goodsListCount]); //增加第二张图片到goodsRightList数组,因为第一张曾经初始化到左侧列表中 } else { this.goodsListCount++; //图片索引加1 if (this.goodsLeftListHeight > this.goodsRightListHeight) { //把图片的高度加到目前高度更低的栏中 this.goodsRightListHeight += rImgH; //第二张图片高度加到goodsRightListHeight } else { this.goodsLeftListHeight += rImgH; } if (this.goodsListCount < this.listData.length) { //依据目前的栏高,把下一张图片,push到低的那栏 if (this.goodsLeftListHeight > this.goodsRightListHeight) { this.goodsRightList.push(this.listData[this.goodsListCount]); } else { this.goodsLeftList.push(this.listData[this.goodsListCount]); } } } }, // 向商品列表增加第一张图片 async waterfallImage() { this.goodsListCount = 0; this.goodsLeftList.push(this.listData[0]); } }};</script>兼容性uni-app我的项目中应用都兼容 ...

August 4, 2021 · 1 min · jiezi

关于uni-app:uniapp导入企业微信sdk的血泪史

废话不多说,间接上后果 uni-app导入企业微信sdk办法: npm install wecomjsdkwecomjsdk文档地址:https://www.npmjs.com/package... 并且uni-app有个坑,就是uni-app有个内置的wx变量,所以要依照上面的办法改: //main.js//调用企业微信api的时候将wx换成$wximport wx from "wecomjsdk"Vue.prototype.$wx = wx这样就能在uni-app里引入胜利,失常调用企业微信的api了 感激这位大佬上传了这个企业微信sdk的npm版,把我从秃头的危机中拯救了进去....

July 19, 2021 · 1 min · jiezi

关于uni-app:uniapp自定义弹框uapopup组件增强版

组件介绍UA-Popup 一款基于 uniapp 开发的轻量级多端自定义弹框组件。反对超过20+参数配置、组件式+函数式两种调用形式。完满运行到h5+App端+小程序及Nvue原生组件页面。 如上图:兼容h5+小程序+App端,运行成果统一。 导入组件在main.js中全局引入组件。 import UAPopup from './components/ua-popup/index.vue'Vue.component('ua-popup', UAPopup)当然,也反对 easycom 模式。能够省略下面这一步导入。 反对组件式写法和函数调用两种形式。 组件式调用<!-- msg提醒 --><ua-popup v-model="showMsg" anim="fadeIn" content="上善若水,水利万物而不争" shadeClose="false" time="3" /><!-- 信息框 --><ua-popup v-model="showInfo" anim="scaleIn" content="阳光下人走不出本人的影子,光明中人看不见本人的影子。只有还有今天,明天就永远是起跑线。" :btns="[ {text: '晓得了', style: 'color:#999;', click: hideInfo}, ]"/> 函数式调用// 函数式嵌套调用handleInfo() { let $ua = this.$refs.uapopup let $toast = this.$refs.uatoast $ua.open({ content: '人生漫漫,且行且珍惜', customStyle: {'background-color': 'rgba(170, 0, 127, 0.6)', 'color': '#fff'}, time: 3, onClose() { $ua.open({ type: 'android', content: '<div style="color:#aa007f">预测将来的最好方法是本人亲手发明将来</div>', customStyle: {'width': '200px'}, zIndex: 202120, btns: [ { text: 'close', click() { $ua.close() } }, { text: 'Get一下', style: 'color:#00aa00;', click() { $toast.open({ type: 'toast', icon: 'loading', content: '请稍后...', opacity: .2, time: 2, zIndex: 202125, }) } } ] }) } })},handleBtnClick() { this.$refs.uapopup.open({ content: '正在操作中,请稍后...', shadeClose: false, anim: 'footer', customStyle: {'background-color': 'rgba(0, 170, 0, 0.6)', 'color': '#fff', 'border-radius': '6px'}, opacity: .1, time: 2, onClose: () => { this.$refs.uatoast.open({ type: 'toast', icon: 'success', content: '操作胜利', time: 2, }) } });}, ...

July 11, 2021 · 4 min · jiezi

关于uniapp:uniapp踩坑记录uview的collapse组件面板打开时获取数据不显示内容以及显示慢的问题

环境HBuilder X 3.1.18uview-ui 1.8.4 问题形容应用uview-ui的collapse组件,当某个面板关上时,获取数据并更新内容 <template> <view> <u-collapse> <u-collapse-item title="title" v-for="(item, index) in list" @change="handleOpenChange(item, index)" > {{item.content}} </u-collapse-item> </u-collapse> </view></template><script> export default { data() { return { list: [{ content: '' }, { content: '' }] }; }, methods: { handleOpenChange(item, index) { this.list[index].content = '我是内容'; } } }</script>以上代码,当组件面板关上时,内容并不显示,调试发现DOM中已有内容,但高度为0 解决查看文档尝试调用init办法,内容胜利显示,但有重大的性能问题,当item较多时,十分卡顿,查看源码发现init办法会循环解决所有的子元素查看u-collapse-item.vue源码组件外部有queryRect办法用于更新内容高度故批改代码如下首先给u-collapse-item增加ref属性 <u-collapse-item title="title" v-for="(item, index) in list" ref="collapseItem" @change="handleOpenChange(item, index)">再批改事件处理办法,调用以后item的queryRect办法,问题解决 handleOpenChange(item, index) { this.list[index].content = '我是内容'; // 实测如果用$nextTick,在android端依然有概率获取不到高度,故改用setTimeout setTimeout(() => { this.$refs.collapseItem[index].queryRect(); }, 100);}

July 7, 2021 · 1 min · jiezi

关于uni-app:uniapp中使用echarts-时在h5中-tooltips无效的解决办法

版本信息echarts:5.1.2uniapp:3.1.8 起因:echarts 引入的时候,会优先判断以后的环境。 uniapp的又一个全局变量就叫做wx。导致这里的判断间接走第一个。 解决办法:在main.js中 window.wx = {}间接将wx从新赋值。

July 7, 2021 · 1 min · jiezi

关于uniapp:关于uniapp基于uView框架开发的一些js文件配置

装置npm依赖npm install uview-ui 开发环境请将 http.interceptor.js 文件中的 baseUrl: appconfig.serverUrl, 加上条件编译,如下// #ifndef H5 baseUrl: appconfig.serverUrl,// #endif开发环境跨域配置vue.config.js 正式环境能够将 http.interceptor.js 文件中的 baseUrl: appconfig.serverUrl 条件编译去掉 变成如下模式baseUrl: appconfig.serverUrl,后续更换域名同样批改 vue.config.js 和 config.js 中的域名main.jsimport Vue from 'vue'import App from './App'import store from './store'import * as utils from '@/common/utils.js'import uView from "uview-ui";Vue.use(uView);import cuCustom from 'colorui/components/cu-custom.vue'Vue.component('cu-custom',cuCustom)Vue.config.productionTip = falseVue.prototype.$store = storeVue.prototype.$utils = utilsApp.mpType = 'app'const app = new Vue({ ...App})// http拦截器,此为须要退出的内容,如果不是写在common目录,请自行批改引入门路import httpInterceptor from '@/common/http.interceptor.js'// 这里须要写在最初,是为了等Vue创建对象实现,引入"app"对象(也即页面的"this"实例)Vue.use(httpInterceptor, app)// http接口API集中管理引入局部import httpApi from '@/common/http.api.js'Vue.use(httpApi, app)app.$mount()config.js//配置文件放这里吧export default { apiurl:'', serverUrl:"",//服务器接口api地址,本地跨域配置临时用空 imageUrl:"",//服务图片加载地址 imgupload:"",//图片上传地址 appid:""//公众号appid }http.api.jsimport appconfig from './config.js'// 如果没有通过拦截器配置域名的话,能够在这里写上残缺的URL(加上域名局部)let loginUrl="" //登录// 此处第二个参数vm,就是咱们在页面应用的this,你能够通过vm获取vuex等操作,更多内容详见uView对拦截器的介绍局部:// https://uviewui.com/js/http.html#%E4%BD%95%E8%B0%93%E8%AF%B7%E6%B1%82%E6%8B%A6%E6%88%AA%EF%BC%9Fconst install = (Vue, vm) => { // 应用传入的params参数 let login = (params = {}) => vm.$u.post(loginUrl, { username:params.username, password:params.password }); // 将各个定义的接口名称,对立放进对象挂载到vm.$u.api(因为vm就是this,也即this.$u.api)下 vm.$u.api = {login};}export default { install}http.interceptor.js//引入配置文件import appconfig from './config.js'// 这里的vm,就是咱们在vue文件外面的this,所以咱们能在这里获取vuex的变量,比方寄存在外面的token变量const install = (Vue, vm) => { // 此为自定义配置参数,具体参数见上方阐明 Vue.prototype.$u.http.setConfig({ baseUrl: appconfig.serverUrl, loadingText: '致力加载中~', loadingTime: 800, // 在此工夫内,申请还没回来的话,就显示加载中动画,单位ms originalData: false, // 是否在拦截器中返回服务端的原始数据 false时服务器状态码不为200,会modal弹框提醒 loadingMask: true, // 展现loading的时候,是否给一个通明的蒙层,避免触摸穿透 showLoading: true, // 是否显示申请中的loading // 设置为json,返回后会对数据进行一次JSON.parse() dataType: 'json', // 配置申请头信息 header: { 'content-type': 'application/json', } }); // 申请拦挡,配置Token等参数 Vue.prototype.$u.http.interceptor.request = (config) => { // 援用token console.log("申请拦挡:",config); // 形式一,寄存在vuex的token,假如应用了uView封装的vuex形式 // 见:https://uviewui.com/components/globalVariable.html // config.header.token = vm.token; // 形式二,如果没有应用uView封装的vuex办法,那么须要应用$store.state获取 // config.header.token = vm.$store.state.token; // 形式三,如果token放在了globalData,通过getApp().globalData获取 // config.header.token = getApp().globalData.username; // 形式四,如果token放在了Storage本地存储中,拦挡是每次申请都执行的 // 所以哪怕您从新登录批改了Storage,下一次的申请将会是最新值 const token = uni.getStorageSync('token'); config.header.token = token; // 能够对某个url进行特地解决,此url参数为this.$u.get(url)中的url值 // if(config.url == '/user/login') config.header.noToken = true; // 最初须要将config进行return return config; // 如果return一个false值,则会勾销本次申请 // if(config.url == '/user/rest') return false; // 勾销某次申请 } // 响应拦挡,判断状态码是否通过 Vue.prototype.$u.http.interceptor.response = (res) => { // console.log("响应拦挡:", res); //临时就间接诶返回吧 return res; // if(res.code == 200) { // // res为服务端返回值,可能有code,result等字段 // // 这里对res.result进行返回,将会在this.$u.post(url).then(res => {})的then回调中的res的到 // // 如果配置了originalData为true,请注意这里的返回值 // return res.result; // } else if(res.code == 201) { // // 假如201为token生效,这里跳转登录 // vm.$u.toast('验证失败,请从新登录'); // setTimeout(() => { // // 此为uView的办法,详见路由相干文档 // vm.$u.route('/pages/user/login') // }, 1500) // return false; // } else { // // 如果返回false,则会调用Promise的reject回调, // // 并将进入this.$u.post(url).then().catch(res=>{})的catch回调中,res为服务端的返回值 // return false; // } }}export default { install}

June 29, 2021 · 2 min · jiezi

关于uni-app:uniapp在编译多端时vfor在H5和小程序端编译结果不一致

在应用 v-for="number in productImage.cutCount"遍历一个数值时, <view v-for="number in productImage.cutCount"> <view>{{ number }}</view> </view>在微信小程序中,遍历进去的后果是 <view>0</view> <view>1</view> <view>2</view> <view>3</view> <view>4</view> 在H5中,遍历进去的后果是 <view>1</view> <view>2</view> <view>3</view> <view>4</view> <view>5</view>注意事项在H5平台 应用 v-for 循环整数时和其余平台存在差别,如 v-for="(item, index) in 10" 中,在H5平台 item 从 1 开始,其余平台 item 从 0 开始,可应用第二个参数 index 来保持一致。

June 17, 2021 · 1 min · jiezi

关于uni-app:uniapp自定义密码输入框

最近在用uni-app开发时遇到一个相似微信领取的明码框需要,要求:用户输出明码后主动向后跳转一个输入框,并且取得焦点,直到输出结束。用户删除时,删除完以后输入框的内容,再按一个“退格/删除”键,则主动往前跳一个输入框,并将其内容删除。成果如: 实现思路有且只能有一个input输入框 如果采纳一个方框用一个input输入框,在模拟器里没有什么问题,但在实在的手机中会呈现软件盘弹起不了问题。肉眼看到的输入框(方框)是虚构的,光标也是虚构的input输入框的大小与方框大小统一,字体大小保持一致,字体色彩为通明,设置字体色彩为通明后输入框的光标也会随之隐没光标挪动到哪个方框,input输入框也要随之挪动input输入框限度最多只能输出2个字符,如果只有一个字符则要在该字符后面补一个空格 因为要实现以后输入框的值删除掉后再按一个“退格/删除”键以后输入框的前一个输入框的值也要删除掉性能用户在方框中输出一个字符后,input输入框立刻挪动到下一个方框,并且清空input输入框删除行为,在input输入框中应用input事件来模仿“退格/删除”行为代码实现template <template> <view class="password-input-com" ref="passwordInputCom"> <input ref="passwordInput" v-model="inputValue" :focus="inputFocus" :style="{left: passwordInputLeft + 'px'}" type="text" maxlength="2" @input="onInput" @blur="onBlur" class="password-input"> <view class="virtual-input-list" ref="virtualInputList"> <view class="virtual-input-item" v-for="(item, index) in virtualInputs" :key="index" :class="{security: mask, 'input-focus': virtualInputItemIndex == index}" @click="onVirtualInputClick(index)"> <view v-if="!mask" class="text-viewer">{{item.value}}</view> <view v-show="item.value != ' ' && mask" class="security-mask"></view> <view class="virtual-input-cursor"></view> </view> </view> </view></template>javascript <script> export default { name: "PasswordInput", props: { value: { type: String, default: '' }, length: { // 明码最大长度 type: Number, default: 6 }, mask: { type: Boolean, default: false } }, data() { // 获取运行平台 let getPlatform = () => { let platform; // #ifdef H5 platform = 'H5'; // #endif // #ifdef MP-WEIXIN platform = 'mp-weixin'; // #endif // #ifdef MP-ALIPAY platform = 'mp-alipay'; // #endif return platform; } return { platform: getPlatform(), virtualInputs: [], // specialStr: '●', // 特殊字符 // splitStr: '★', // 宰割字符 inputValue: '', inputFocus: false, passwordInputLeft: 1, virtualInputItemIndex: -1, passwordInputComRect: { width: 0, height: 0, left: 0, right: 0 }, virtualInputItemRect: { width: 0, height: 0, left: 0, right: 0 } }; }, watch: { value: { immediate: true, handler(newVal){ this.calcVirtualInputs(newVal); } } }, methods: { // 计算须要输入框的个数 calcVirtualInputs(newVal){ let valueArr = ((newVal + '').length > 0 ? (newVal + '') : '●●●●●●●●●●●●●●●●●●●●●●●●').split(''); let length = this.length; // console.log('valueArr', valueArr) if(valueArr.length > length){ valueArr.splice(length); }else if(valueArr.length < length){ let lengthDiff = length - valueArr.length; while(lengthDiff > 0){ valueArr.push('●'); lengthDiff--; } } let virtualInputs = valueArr.map((str, index) => { return { value: str == '●' ? ' ' : str, focus: false, index: index }; }); this.virtualInputs = virtualInputs; }, onInput(evt){ // console.log(evt) let val = evt.detail.value; let virtualInputItemIndex = this.virtualInputItemIndex; console.log('onInput', val); if(val.length == 2){ // 以后虚构输入框输出值后立刻向后一个输入框挪动 this.virtualInputs[virtualInputItemIndex].value = val.charAt(1); if((virtualInputItemIndex + 1) < this.length){ this.virtualInputItemIndex = virtualInputItemIndex + 1; this.inputMoveTo(this.virtualInputItemIndex, () => { let nextVirtualInputVal = this.virtualInputs[this.virtualInputItemIndex].value; console.log('nextVirtualInputVal', nextVirtualInputVal) // 这里须要提早60毫秒再设置下一个虚构输入框的值,不然有效 let timer = setTimeout(() => { clearTimeout(timer); this.inputValue = nextVirtualInputVal == ' ' ? nextVirtualInputVal : (' ' + nextVirtualInputVal); console.log('this.inputValue', this.inputValue) }, 60); }); } this.$nextTick(() => { this.detectInputComplete(); }); } else if(val.length == 1){ console.log('length等于1', val) if(val == ' '){ // 以后操作为删除虚构框中的值 this.virtualInputs[virtualInputItemIndex].value = ' '; }else{ // 以后操作为正在输出 if((virtualInputItemIndex + 1) < this.length){ this.virtualInputItemIndex = virtualInputItemIndex + 1; this.inputMoveTo(this.virtualInputItemIndex, () => { let nextVirtualInputVal = this.virtualInputs[this.virtualInputItemIndex].value; let timer = setTimeout(() => { clearTimeout(timer); this.inputValue = nextVirtualInputVal == ' ' ? nextVirtualInputVal : (' ' + nextVirtualInputVal); console.log('this.inputValue2', this.inputValue) }, 60); }); } this.$nextTick(() => { this.detectInputComplete(); }); } } else if(val.length == 0){ // 往前一个输入框挪动,并删除其值 if(virtualInputItemIndex - 1 >= 0){ this.virtualInputItemIndex = virtualInputItemIndex - 1; this.inputMoveTo(this.virtualInputItemIndex, () => { this.virtualInputs[this.virtualInputItemIndex].value = ' '; // 这里须要提早60毫秒再设置下一个虚构输入框的值,不然有效 let timer = setTimeout(() => { clearTimeout(timer); this.inputValue = ' '; }, 60); }); } } }, onBlur(){ this.inputFocus = false; this.virtualInputItemIndex = -1; }, detectInputComplete(){ let length = this.length; let valStr = this.getValue(); console.log('detectInputComplete', valStr); if(length == valStr.length){ this.$emit('complete', valStr); } }, inputMoveTo(virtualInputIndex, cb){ console.log('inputMoveTo', virtualInputIndex) let passwordInputComRect = this.passwordInputComRect; let obj = uni.createSelectorQuery().in(this).selectAll('.virtual-input-item'); // 获取元素宽高 obj.boundingClientRect((rectData) => { console.log(rectData) let currentDomRect = rectData[virtualInputIndex]; console.log('currentDomRect', currentDomRect, virtualInputIndex, passwordInputComRect) // +1是因为有1px的左边框 this.passwordInputLeft = currentDomRect.left - passwordInputComRect.left + 1; typeof cb == 'function' ? cb() : 1; }).exec(); }, onVirtualInputClick(index){ console.log('onVirtualInputClick', index) let $passwordInput = this.$refs.passwordInput; this.inputMoveTo(index, () => { let virtualInputVal = this.virtualInputs[index].value; this.inputFocus = true; this.inputValue = virtualInputVal == ' ' ? virtualInputVal : (' ' + virtualInputVal); this.virtualInputItemIndex = index; if(this.platform == 'H5'){ this.$refs.passwordInput.$el.focus(); } }); }, getValue(){ let length = this.length; let valStr = this.virtualInputs.reduce((res, item) => { let itemVal = item.value.replace(/ /g, ''); return res += itemVal; }, ''); if(valStr.length > length){ valStr = valStr.substr(0, length); } return valStr; } }, mounted() { this.$nextTick(() => { let obj = uni.createSelectorQuery().in(this).select('.password-input-com'); // 获取元素宽高 obj.boundingClientRect((data) => { if(!data){ // 支付宝小程序获取不到地位信息 let systemInfo = uni.getSystemInfoSync(); let wh = systemInfo.windowWidth; let rpxCalcIncludeWidth = 750; let pagePaddingLeft = 48; data = { left: wh / 750 * 48 } }else{ this.passwordInputComRect = data; } console.log('组件宽高地位信息', data) }).exec(); }); } }</script>css ...

June 17, 2021 · 4 min · jiezi