UNI-APP 实践问题记录
最近需要将一个原来vuejs 技术栈的 移动端业务改造小程序,基于成本和时间的考虑,选择了 uni-app
,一开始直接将旧代码迁入到新的工程里。在逐步开发过程中,遇到了一些问题,整理记录一下,当然这些问题可能只是在我们项目特定场景、特定情况下出现的,仅供参考,提供一个思路。
语法问题
- 编译后,WXML提示
bad attrs
在于template中写了个短路运算,
v-if="false && item.count > 1"
(之前主要是为了防止产品又要改回来,加了短路运算)。解决方案:删除短路运算相关代码
- v-show 判断问题
v-show 在数据表达式条件成立后,表现结果错误。
v-show="count > 0"
, 当count > 0的时候,v-show对应的el 仍旧没有显示出来。解决方案: v-show 改为 v-if
自定义配置
- 自定义构建配置
我们需要将小程序中用到的图片、字体构建到cdn 服务中,而不是打包在小程序代码中,所以需要修改构建工作流。
在官方文档中,支持
vue.config.js
来配置一些 webpack 工作流。对于图片、字体等默认是会对小于40KB进行base64。
由于
vue-cli
中,字体、图片等用的是url-loader
,所以为了将图片、字体构建到cdn种,需要在vue.config.js
中配置url-loader
,url-loader
fallback 到file-loader
。先看下完整配置
// vue.config.js
'use strict'
const path = require('path')
const isWin = /^win/.test(process.platform)
const isProd = process.env.NODE_ENV === 'production'
const normalizePath = (path) => (isWin ? path.replace(/\\/g, '/') : path)
const extConfig = require('./src/ext.json')
function resolve(dir) {
return path.join(__dirname, dir)
}
// 配置H5 跨域
const devServer = {
target: 'your.domain.com',
// 重要
changeOrigin: true,
pathRewrite: { '^/': '' },
// 重要
secure: false,
prependPath: true,
onProxyReq: function (proxyReq, req, res) {
},
}
module.exports = {
// 路径别名
chainWebpack: (config) => {
/* .resolve.alias
.set('@', resolve('src'))
.set('@p', resolve('src/pages'))
.set('@c', resolve('src/components'))
.set('@a', resolve('src/assets'))
.set('@utils', resolve('src/utils'))
.end()
.extensions.add('.js')
.add('.vue')
.add('.scss')
.end()
.end() */
config.module
.rule('vue')
.test([/\.vue$/, /\.nvue$/])
.use('vue-loader')
.tap((options) =>
Object.assign({}, options, {
// 配置 小程序image标签的src 也进行资源路径转换
transformAssetUrls: {
image: 'src',
},
}),
)
.end()
if (isProd) {
config.module
.rule('images') //.test(/\.(png|jpe?g|gif|svg)(\?.*)?$/)
.use('url-loader')
.tap((args) => {
const newArgs = Object.assign({}, args, {
// 配置转换规则,-1 表示任何大小的资源都不进行base64转换
limit: -1,
// 这里重要,publicPath 配置给url-loader 会不生效,必须配置到fallback里传递给file-loader
fallback: {
loader: 'file-loader',
options: {
publicPath(url, resourcePath, context) {
return (
extConfig.ext.publicPath +
normalizePath(path.relative(process.env.UNI_INPUT_DIR, resourcePath))
)
},
emitFile: false,
},
},
})
return newArgs
})
.end()
.end()
.rule('fonts')
.use('url-loader')
.tap((args) => {
const newArgs = Object.assign({}, args, {
limit: -1,
fallback: {
loader: 'file-loader',
options: {
publicPath(url, resourcePath, context) {
return (
extConfig.ext.publicPath +
normalizePath(path.relative(process.env.UNI_INPUT_DIR, resourcePath))
)
},
emitFile: false,
},
},
})
return newArgs
})
}
},
devServer: {
disableHostCheck: true,
proxy: {
'/api': devServer,
},
},
}
另外,uni-app 中 路径别名默认 @
指向 src
目录,如果配置了其他自定义别名,比如上面配置中的 @c
会导致编译的时候无法正确识别 @c
引用的资源。
性能优化相关
uni-app 会将 component
的 data
属性转化为小程序的 data
, vue中任何修改 data的
操作都会最终触发小程序的 setData
,众所周知, setData
是小程序性能优化一个重点。
- 与template 无关的数据尽量不要放到
data
里,否则任何修改的操作都会导致setData
,从而影响性能。 尽量不要频繁的触发setData
<script> data() { return { name: ['YoRoling'] } }, methods: { getName() { if (a) { // 触发setData this.name.push('a') } if (b) { // 触发setData this.name.push('b') } } } </script>
上面的代码,a和b 都会导致最终触发
setData
,而且是触发两次,对于这种简单的数据可能还好,如果是一个复杂的JSON 对象,setData 可能就会引起性能问题。使用临时变量存储数据,最后再一次性修改
data
。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。