记录--开发uniapp nvue App+微信小程序,我踩过的坑( 纯干货 )
这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助
最近接了个项目,采用uniapp的nvue开发安卓和ios端+小程序端,第一次开发nvue,对于css布局这块,还是踩了很多坑。以及一些uniapp的Api在nvue中也无法使用。文章中也收录了一些我在项目中使用的一些方法,比如富文本解析、App绑定微信等,大家可以参考下。
1、注意事项
1. nvue仅支持flex布局
1 2 3 4 5 6 | // 默认布局为(不需要写) display: flex; flex-direction: column; // 横向局部改为 flex-direction: row; |
2. class 进行绑定时只支持数组语法
1 2 3 4 5 6 7 | < template > // 支持的数组写法 < text :class="[isError ? 'isError' : 'isRight']"></ text > // 不支持对象写法 < text :class="{isError}"></ text > </ template > |
3. 只有<text>标签可以设置字体大小,字体颜色
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | < template > // 可以修改字体大小和颜色 < text class='text'>文本内容</ text > // 不可以修改字体大小和颜色 < view class='text'>文本内容</ view > </ template > < style > .text { color: red; font-size: 28rpx; } </ style > |
盒模型
- nvue盒模型的 box-sizing 默认为 border-box;
- 在 Android 平台,overflow只支持 hidden;
- 在 ios 上,overflow支持 hidden 和 visible,默认是 visible。
2、对CSS的限制(常用)
1 2 3 4 5 6 7 8 9 10 11 | // 不支持的CSS margin: auto; display: ...; content: ...; animation: ...; width: vw、%; height: vh、%; background-image: ...; // 不支持的CSS属性 border-radius: 百分比无效; |
3、多端单行/多行文本溢出
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 29 30 31 32 33 34 35 36 37 38 | // 文本溢出 @mixin line($lineNum, $width: 100%) { /* 一行时 */ @if $lineNum == 1 { // App端 /* #ifdef APP-PLUS */ lines: 1; // 1或n text-overflow: ellipsis; /* #endif */ // 其他端 /* #ifndef APP-PLUS */ overflow:hidden; text-overflow:ellipsis; white-space:nowrap; width: $width; /* #endif */ } @else { /* 多行时 */ // App端 /* #ifdef APP-PLUS */ lines: $lineNum; // 1或n text-overflow: ellipsis; /* #endif */ // 其他端 /* #ifndef APP-PLUS */ overflow: hidden; -webkit-line-clamp: $lineNum; display: -webkit-box; text-overflow: ellipsis; word-wrap: break-word; white-space: normal !important; -webkit-box-orient: vertical; /* #endif */ } } |
使用
1 2 3 | // 使用 @include line(1, 400rpx); // 单行 @include line(2); // 多行 |
4、获取导航栏高度
1 2 3 4 5 | // App导航栏高度 uni.getSystemInfoSync().safeArea.top + 'px' // 小程序导航栏高度 uni.getMenuButtonBoundingClientRect().top + 'px' |
5、获取底部安全区域高度
1 2 | const safeArea = uni.getSystemInfoSync().safeArea const paddingBottom = safeArea.bottom - safeArea.height + 'rpx' |
6、App修改导航栏电池、时间颜色
1 2 3 4 | //只支持dark和light // #ifdef APP-PLUS plus.navigator.setStatusBarStyle('dark') // #endif |
7、CSS过渡动画
1 2 3 4 5 | // 使用动画的CSS属性、动画时间、动画过渡效果、动画延迟时间 transition-property: transform; transition-duration: 0.2s; transition-timing-function: ease; transition-delay:0.1s; |
8、边框样式
1 2 3 4 5 6 7 | // HBuilderX 3.1.0之前需要分开写 border-top: 1px; border-style: solid; border-top-color: #eee; // HBuilderX 3.1.0+ 开始支持简写样式 border-top: 1px solid #eee; |
9、nvue中不支持的uni-app API
1 2 3 4 5 6 7 8 | // 1、创建动画 uni.createAnimation() // 2、页面滚动 uni.pageScrollTo() // 3、节点布局交互(交叉观察器) uni.createIntersectionObserver() |
10、微信端底部安全区域
1 2 3 | /* #ifndef APP-PLUS */ padding-bottom: calc(env(safe-area-inset-bottom)); /* #endif */ |
11、nvue解析富文本(支持小程序)
App-nvue 和支付宝小程序不支持 HTML String 方式,仅支持直接使用节点列表即 Array 类型,需将 HTML String 转化为 nodes 数组,可使用 html-parser 转换。
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 29 | < template > < rich-text :nodes='htmlNodes'/> </ template > < script > // nvue仅支持node节点渲染,所以要将HTML转换成node节点 import parseHtml from './html-parse.js' export default { data () { return { htmlStr: ` < h1 >我的日记</ h1 > < p >今天天气真好</ p > < p >适合出去玩</ p > `, htmlNodes: [] } }, onLoad () { this.getContent() }, methods: { getContent () { // 将HTML文本转换成node节点 this.htmlNodes = parseHtml(this.htmlStr) } } } </ script > |
12、App端计算缓存和清理缓存
cacheSetting.js
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 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 | // 计算缓存 export const computedCache = () => { return new Promise(resolve => { plus.cache.calculate((size) => { let cachSize = '' size = parseInt(size) if (size === 0) { cachSize = '' } else if (size < 1024 ) { cachSize = size + 'B' } else if (size < 1048576) { cachSize = (size / 1024).toFixed(2) + 'KB' } else if (size < 1073741824) { cachSize = (size / 1048576).toFixed(2) + 'MB' } else { cachSize = (size / 1073741824).toFixed(2) + 'GB' } resolve(cachSize) }) }) } // 清除缓存 export const clearCache = (cb) => { uni.showLoading({ title: '清理中…' }) const os = plus.os.name if (os === 'Android') { const main = plus.android.runtimeMainActivity() const sdRoot = main.getCacheDir() const files = plus.android.invoke(sdRoot, 'listFiles') const len = files.length for (let i = 0; i < len ; i++) { const filePath = '' + files[i] // 没有找到合适的方法获取路径,这样写可以转成文件路径 plus.io.resolveLocalFileSystemURL(filePath, (entry) => { if (entry.isDirectory) { entry.removeRecursively(() => { // 递归删除其下的所有文件及子目录 uni.showToast({ title: '缓存清理完成', duration: 2000 }) cb() }, (e) => { console.log(e.message) }) } else { entry.remove() } }, () => { console.log('文件路径读取失败') }) } } else { // ios plus.cache.clear(() => { uni.showToast({ title: '缓存清理完成', duration: 2000 }) cb() }) } } |
13、多端1px边框
1. 新建border.scss
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 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 | // 默认边框色 $border: #e4e7ed; // nvue端 /* 此处加上!important并是因为目前*.nvue页面编译到H5时, App.vue的样式会被uni-app的view元素的自带border属性覆盖,导致无效, 所以为了多端兼容,必须要加上!important App端兼容性较好,直接使用0.5px去实现细边框,不使用伪元素形式实现 */ /* #ifdef APP-NVUE */ .border { border-width: 0.5px!important; border-color: $border!important; border-style: solid; } .border-t { border-top-width: 0.5px!important; border-color: $border!important; border-top-style: solid; } .border-l { border-left-width: 0.5px!important; border-color: $border!important; border-left-style: solid; } .border-r { border-right-width: 0.5px!important; border-color: $border!important; border-right-style: solid; } .border-b { border-bottom-width: 0.5px!important; border-color: $border!important; border-bottom-style: solid; } .border-tb { border-top-width: 0.5px!important; border-bottom-width: 0.5px!important; border-color: $border!important; border-top-style: solid; border-bottom-style: solid; } /* #endif */ // 非nvue端 /* #ifndef APP-NVUE */ .border, .border-b, .border-l, .border-r, .border-t, .border-tb { position: relative; } .border-b:after, .border-l:after, .border-r:after, .border-tb:after, .border-t:after, .border:after { content: ' '; position: absolute; left: 0; top: 0; pointer-events: none; box-sizing: border-box; -webkit-transform-origin: 0 0; transform-origin: 0 0; width: 200%; height: 200%; transform: scale(0.5, 0.5); border: 0 solid $border; z-index: 1; } .border-t:after { border-top-width: 1px; } .border-l:after { border-left-width: 1px; } .border-r:after { border-right-width: 1px; } .border-b:after { border-bottom-width: 1px; } .border-tb:after { border-width: 1px 0; } .border:after { border-width: 1px; } /* #endif */ |
2. uni.scss引入
1 | @import './assets/style/border.scss'; |
3. 组件内使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | // 1.作为类名使用 < template > < view class='border-tb'></ view > </ template > // 2.作为选择器继承 < template > < view class='cell'></ view > </ template > < style lang='scss' scoped> .cell { @extend .border-tb; } </ style > |
14、App用户绑定微信/App微信登录
1. manifest.json配置
2. 代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | appBindWx () { const that = this uni.getProvider({ service: 'oauth', success: (res) => { //支持微信、qq和微博等 if (~res.provider.indexOf('weixin')) { uni.login({ provider: 'weixin', success: ({authResult}) => { // 微信返回的数据见下方图片 // 请求接口完成绑定 }, fail: (res) => { console.log('App微信获取用户信息失败', res) } }) } } }) } |
3. 微信返回的数据
15、App分享为微信小程序
1. manifest.json配置
2. 代码
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 29 30 31 32 33 34 | const shareAppToMp = (shareInfo, cb) => { // 建议将图片下载到本地再进行分享,防止有些图片存在鉴权导致无法分享成功 uni.downloadFile({ url: 'xxx', // 图片路径 success (res) { if (res.statusCode === 200) { uni.share({ provider: 'weixin', // 分享服务提供商 // WXSceneSession分享到聊天界面、WXSceneTimeline分享到朋友圈、WXSceneFavorite分享到微信收藏 scene: 'WXSceneSession', // provider为weixin 时必选 type: 5, // 图文、纯文字、纯图片、音乐、视频、小程序,5为小程序 imageUrl: res.tempFilePath, // 本地图片地址 title: 'title', // 小程序分享标题 miniProgram: { id: 'gh_xxxxxxxxxx', // 小程序原始ID path: '/pages/homePage/index', // 小程序分享的页面 type: 0, // 小程序版本类型,0正式版、1测试版、2-体验版,默认为0 webUrl: 'xxxxx' // 兼容低版本的网页链接,可选 }, success () { uni.showToast({ title: '分享成功!', duration: 2000 }) cb() }, fail (e) { console.log('分享失败原因:', e) } }) } } }) } |
3.注意事项
配置正确的情况下,打包成App后才能成功分享,否则会提示以下错误
16、强制退出App
1 2 3 4 5 6 7 8 9 10 11 12 | quitApp () { switch (uni.getSystemInfoSync().platform) { // 安卓 case 'android': plus.runtime.quit() break // ios case 'ios': plus.ios.import('UIApplication').sharedApplication().performSelector('exit') break } } |
17、App和小程序阻止点击事件冒泡
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | < template > < ul @click='clickParent'> <!-- 小程序阻止冒泡 --> < li @click.stop='clickChild'>子元素</ li > </ ul > </ template > < script > export default { methods: { clickParent () { console.log('点击父元素') }, clickChild (e) { console.log('点击子元素') // App阻止冒泡 // #ifdef APP-NVUE e.stopPropagation() // #endif } } } </ script > |
本文转载于:
https://juejin.cn/post/7034362206036852767
如果对您有所帮助,欢迎您点个关注,我会定时更新技术文档,大家一起讨论学习,一起进步。
__EOF__
分类:
uni-app学习笔记
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 本地部署 DeepSeek:小白也能轻松搞定!
· 如何给本地部署的DeepSeek投喂数据,让他更懂你
· 从 Windows Forms 到微服务的经验教训
· 李飞飞的50美金比肩DeepSeek把CEO忽悠瘸了,倒霉的却是程序员
· 超详细,DeepSeek 接入PyCharm实现AI编程!(支持本地部署DeepSeek及官方Dee