一、简单说说准备工作:
创立项目
- 东西: HBuilder最新稳定版, uni-app官网可下载
- 菜单栏:文件-> 新建 -> 项目,创立一个空白的根据vue3版别的模板目录即可
调试
- 东西:预先下载安装 微信开发者东西
- HBuilder中选中当前项目的任何一个文件
- 菜单栏:运转-> 运转到小程序模拟器 ->微信开发者东西
- 运转成功会主动发动
微信开发者东西
,等候编译完成会看到测验界面
【坑】开发方式进行真机调试会白屏,需求在发行方式下进行真机调试
【坑】如呈现微信开发者东西
console里边爆红,能够试试点一下微信开发者东西
上方菜单里边的从头编译,说不定就好了(* ̄︶ ̄)
发布
- 菜单栏:发行-> 小程序-微信
- 此时需求一个小程序AppId,需在微信公众平台上开通
二、一些技巧和坑
1.引证vant组件
引进组件目录
- 与
/pages
同级创立/wxcomponents/vant
目录 - 下载微信小程序版别的vant代码
- 解压代码,把
/dist
目录内的文件复制进去新建的/wxcomponents/vant
目录中 - 开发进程中应参阅对应版别的文档:vant-contrib.gitee.io/vant-weapp 但需求把对应的引证语法改成vue的语法,如:
<van-cell-group>
<van-field value="{{ value }}" placeholder="请输入用户名" border="{{ false }}"
bind:change="onChange" />
</van-cell-group>
改为:
<van-cell-group>
<van-field :value="value" placeholder="请输入用户名" :border="false"
@change="onChange" />
</van-cell-group>
引证
修正pages.json
文件
大局引证
在"globalStyle":{}
属性下参加以下片段,可按需引进具体需求大局引进的组件,引进规矩如下:
"usingComponents": {
"van-cell-group": "/wxcomponents/vant/cell-group/index",
"van-field": "/wxcomponents/vant/field/index",
//...
}
单页引证
把上述的代码放在对应的页面装备内,如:
【坑】报错??
页面【wxcomponents/vant/info/index]过错:
Error: module 'wxcomponents/vant/info/index.js' is not defined,
require args is 'wxcomponents/vant/info/index.js'
WAServiceMainContext.js?t=wechat&s=1666746784000&v=2.27.0:1 SyntaxError:
Cannot use import statement outside a module(env: Windows,mp,1.06.2209190; lib: 2.27.0)
【填坑】
这是由于微信开发者东西
没有启用ES6转ES5功用而报错
在微信开发者东西
右上角:详情-> 本地设置 -> 勾选“将JS编译成ES5”即可
但或许从头编译或热重载后,该选项“将JS编译成ES5”又不勾选了,此时能够直接去修正项目文件manifest.json
, 勾选微信小程序装备
-> ES6转ES5
即可
如翻开的是manifest.json
的源码,能够在对应的方位增加以下装备:
【坑】引证van-toast组件无效或报错
1.未找到van-toast 节点,请承认 selector 及 context 是否正确
组件内引证牢记参阅官方文档,需求给页面引进一个van-toast组件,才能在script
内运用 Toast()
的办法
<van-toast id="van-toast" />
留意:只需或许会调用Toast()
的界面,都需求刺进该组件
2.在非组件的js文件中引证Toast()
,正常运用或许会像如下的方式:
开发方式下是能够正常调用,可是在发行方式下,会报错
vendor.js? [sm]:1 TypeError: s.Toast is not a function
或
TypeError: Cannot read property 'success' of undefined
假如把Toast
打印出来,会发现为null
, 原因是Toast
并未正常引进
理由揭秘:
翻开/wxcomponents/vant/toast/toast.js
,你会发现,最终一句代码为:
export default Toast;
开发方式下,初度编译,在微信开发者东西
翻开这个文件,发现这句话没有变,编译进程并没有把它进行处理
而当回去修正了一下代码,热重载后,这句话就变成了:
exports.Toast = Toast;
估量就是微信开发者东西
进行了再次编译,把一些组件目录的代码进行转换了,而uni-app没有对这些代码进行处理
发布方式下,不存在热重载,在微信开发者东西
翻开这个文件,就会发现它一直是
export default Toast;
而编译后引证这个文件的代码始终是一样的:
都是经过[module].Toast()
来进行引证。
这就会导致一个问题,咱们什么都不改直接引证的话,会呈现热重载后是能正常,初始加载和发布都不能正常运用,由于
exports.Toast
和export default Toast
咱们引进后的内容是不一样的
具体原理可参阅这个地址
【填坑】
把/wxcomponents/vant/toast/toast.js
的最终一句导出句子修正为:
exports.Toast = Toast;
引进句子修正为:
const Toast = require('../wxcomponents/vant/toast/toast.js').Toast
export function loadInfo() {
Toast('加载成功')
}
大功告成!
2.自定义顶部导航栏,以便于修正顶栏款式(复原UI规划图;加布景图、Logo之类..)
修正pages.json
文件
{
...,
"globalStyle": {
"navigationStyle": "custom",
...
}
}
创立对应的自定义组件: components/commonHeader/commonHeader.vue
, 在界面中引进即可(可按下方第4点的方式进行按需引进的设置)
私家tips:
获取系统状况栏和菜单高度,用于设置自定义顶部导航栏的高度
修正App.vue
文件
onLaunch: function() {
console.log('App Launch')
uni.getSystemInfo({
success: function(e) {
// #ifdef MP-WEIXIN
uni.$StatusBarHeight = e.statusBarHeight;
// getMenuButtonBoundingClientRect 用于获取页面右上角圆角按钮的方位信息
let custom = wx.getMenuButtonBoundingClientRect();
uni.$CustomBarHeight = custom.bottom - e.statusBarHeight + 8
// #endif
//uni 为大局目标,能够挂载大局参数,在其他组件能够直接运用
}
})
}
私家tips2: 监听页面翻翻滚态修正顶部导航栏款式
场景:可用于全屏布景图,翻滚后需求修正顶部导航栏的布景和文字颜色的场景
// page代码
onPageScroll(e) {
const { scrollTop } = e
// pageTop 可指定翻滚高度
const pageTop = 100
if (scrollTop > pageTop) {
// headerBg, headerColor 能够是自定义导航栏的一些props, 按需运用
this.headerBg = '#fff'
this.headerColor = 'black'
// 修正状况栏款式(顶部的时间日期等内容)
uni.setNavigationBarColor({
frontColor: '#000000',
backgroundColor: '' // 必填项,不能不传,但能够为空字符串
})
} else {
this.headerBg = 'transparent'
this.headerColor = 'white'
uni.setNavigationBarColor({
frontColor: '#ffffff',
backgroundColor: ''
})
}
}
3.自定义底部菜单栏tabbar
修正pages.json
文件
{
...,
"tabBar": {
"custom": true,
"list": [{
"pagePath": "pages/index/index",
"text": "主页"
},
{
"pagePath": "pages/passed/index",
"text": "主页面1"
},
{
"pagePath": "pages/my/index",
"text": "个人中心"
},
...
]
}
}
创立对应的自定义组件: components/commonTabbar/commonTabbar.vue
, 在对应主界面中引进即可,能够运用vant
的tabbar
组件,可参阅如下:
<template>
<van-tabbar :active="active" active-color="#00C84A" inactive-color="#CDCDCD" :border="false" @change="onChange">
<van-tabbar-item v-for="item in tabs" :key="item.name">
<image slot="icon" :src="item.iconNormal" mode="contain" style="width: 48rpx; height: 48rpx;" />
<image slot="icon-active" :src="item.iconActive" mode="contain" style="width: 48rpx; height: 48rpx;" />
{{item.name}}
</van-tabbar-item>
</van-tabbar>
</template>
<script>
export default {
props: {
current: {
type: Number,
default: 1
}
},
data() {
return {
active: 1,
tabs: [{
name: '主页面1',
iconNormal: '/static/passed.png',
iconActive: '/static/passed-active.png',
path: '/pages/passed/index'
},
{
name: '主页',
iconNormal: '/static/index.png',
iconActive: '/static/index-active.png',
path: '/pages/index/index'
},
{
name: '个人中心',
iconNormal: '/static/my.png',
iconActive: '/static/my-active.png',
path: '/pages/my/index'
}
]
}
},
watch: {
current: {
immediate: true,
handler: function(val) {
this.active = val
}
}
},
methods: {
onChange(e) {
const current = e.detail
uni.switchTab({
url: this.paths[current]
})
}
}
}
私家tips:
为了使界面主要内容不受tabbar覆盖,能够在van-tabbar
组件前面参加一个空节点,如下:
<view class="footer-empty"> </view>
//css 款式
.footer-empty {
height: 100rpx;
padding-bottom: env(safe-area-inset-bottom);
}
4.运用easycom主动按需加载自定义组件(为什么我的组件总是无法主动识别?)
修正pages.json
文件
{
...,
"easycom": {
"autoscan": true,
"custom": {
"^uni-(.*)": "@/components/uni-$1.vue", // 匹配components目录内的vue文件
"^vue-file-(.*)": "packageName/path/to/vue-file-$1.vue" // 匹配node_modules内的vue文件
}
}
}
只需敞开了autoscan
, 会主动扫描目录规矩契合/components/组件称号/组件称号.vue
的所有文件,主动进行引进,无需再在custom
中引进
引进后page中直接运用组件即可
留意:假如新建的组件引证无效,在HBuilder中从头编译项目试试
5.引证富文本显示和编辑组件mp-html
官方文档
mp-html
默许只要显示富文本功用,需求支撑编辑状况的话,要额外代码, 参阅
editable方式设置文档
小程序示例代码
其实引证组件不费事,参照demo,能够按照自己的需求修正菜单icon之类的,比较便利
6.运用微信原生小程序提供的wxml-to-canvas
进行动态海报生成以及保存到本地
官方文档
为了便利改造,不采用npm的办法进行安装,直接翻开代码片段
在代码片段中对应的两个目录,复制到自己的项目中/wxcomponents
目录下
改造目的和内容:
1.wxml-to-canvas
一般用于生成海报,而海报又一般经过popup的方式弹出,所以需求改造烘托时机,等popup弹出后再烘托
默许引证即烘托,可是canvas没法在一个躲藏节点中烘托,所以把默许的烘托时机改为手动(经过自定义代码调用烘托)
修正wxml-to-canvas/index.js
文件
- 在methods中新增一个办法:
methods: {
initCanvas() {
...
}
}
- 把
attached
中的烘托代码剪切进去
- canvas需求先初始化,初始化完毕后再调用
renderToCanvas
进行制作, 否则会报错 网上许多方案都是用setTimeout来进行延迟调用, 可是我觉得这是不稳妥的, 延迟时间设长了设短了都不好, 所以我把initCanvas
写成一个异步函数,如下:
methods: {
initCanvas() {
return new Promise((resolve,reject) => {
const dpr = wx.getSystemInfoSync().pixelRatio
const query = this.createSelectorQuery()
this.dpr = dpr
query.select('#canvas')
.fields({node: true, size: true})
.exec(res => {
const canvas = res[0].node
const ctx = canvas.getContext('2d')
canvas.width = res[0].width * dpr
canvas.height = res[0].height * dpr
ctx.scale(dpr, dpr)
this.ctx = ctx
this.canvas = canvas
resolve(canvas)
})
})
},
...
},
- 页面代码中:
刺进组件
<van-popup :show="showPopup" :close-on-click-overlay="true" custom-style="background:transparent" @close="showPopup = false" @after-enter="opened">
<view>
<wxml-to-canvas ref="widget" class="widget"></wxml-to-canvas>
</view>
</van-popup>
在popup弹出后,调用办法
methods: {
async opened() {
const canvas = await this.$refs.widget.initCanvas()
Toast.loading({
message: '加载中',
forbidClick: true
});
const obj = { wxml: '...', styles: '...'}
this.$refs.widget.renderToCanvas(obj).then(res => {
Toast.clear()
})
}
}
2.canvas自适应宽高改造:
-
获取实践屏幕宽度和规划稿的比例,核算每个元素的实践尺寸和边距等
-
修正
wxml-to-canvas/index.js
文件- 修正
attached()
办法
attached() { const sys = wx.getSystemInfoSync(); //拿到设备的宽度,跟规划图宽度的比例 const screenRatio = sys.screenWidth / 375; this.setData({ screenRatio, width: this.data.width * screenRatio, height: this.data.height * screenRatio, }); }
- 修正
initCanvas()
办法
initCanvas() { // ...省掉 // canvas.width = res[0].width * dpr // canvas.height = res[0].height * dpr canvas.width = this.data.width * dpr; canvas.height = this.data.height * dpr; // ...省掉 }
- 修正
renderToCanvas()
办法
renderToCanvas() { // const {wxml, style} = args const { wxml, fnGetStyle } = args // 经过fnGetStyle办法传入屏幕与规划稿的比例,用以核算款式 const style = fnGetStyle(this.data.screenRatio) // ...省掉 }
- 修正
-
可新建一个文件进行canvas节点和款式的装备, 如
canvasConfig.js
:
// canvasConfig.js
// function 方式便于传入动态数据
export default function(info) {
const wxml = `<view class="container">
<view class="absolute mainBox"></view>
</view>`
const fnGetStyle = (screenRatio) => {
return {
// 编写款式, 称号需以驼峰命名
absolute: {
position: 'absolute'
},
container: {
width: 300*screenRatio, //经过乘以倍率,核算出在当前屏幕分辨率下的实践宽度, 其他尺寸同理
height: 471*screenRatio,
position: 'relative'
},
mainBox: {
width: 200*screenRatio,
padding: 10*screenRatio,
margin: 10*screenRatio,
color: '#eeeeee'
}
}
}
return {
wxml,
fnGetStyle
}
}
- 修正页面中的组件调用办法:
import canvasConfig from './canvasConfig.js'
// ...省掉
methods: {
opened() {
...
const info = { title: '标题' }
const obj = canvasConfig(info)
this.$refs.widget.renderToCanvas(obj).then(res => {
Toast.clear()
})
}
}
生成图片并保存到本地
页面代码中:
methods: {
//...
extraImage() {
this.$refs.widget.canvasToTempFilePath().then(res => {
this.saveImg(res.tempFilePath)
})
},
async saveImg (tempFilePath) {
const _this = this
uni.saveImageToPhotosAlbum({
filePath: tempFilePath,
success: async (res) => {
uni.showModal({
content: '图片已保存,共享给老友吧!',
showCancel: false,
confirmText: '好的',
confirmColor: '#333',
success: function (res) {
// ...
},
fail: function (res) {
// ...
}
});
},
fail: function (res) {
Toast.fail('您取消了授权')
}
});
}
}
【坑】明明添加了内容,页面却还是空白
- wxml及款式的编写需求严厉遵从运用规矩,有些固定的要求及支撑的款式,不遵从的话或许会导致烘托不出来
【坑】真机调试报错 fail canvas has not been created
- 按照上述的办法应该不会报这个问题
- 还报的话,查看是否canvas内的元素的烘托尺寸超出了canvas的实践宽高,超出则或许烘托失败
这次共享这么多,谢谢观看!
仍有无法处理的问题欢迎交流!
ps: 为了图快,本项目其实并没有用到vue3的一些新特性(懒得查文档), 就这么凑合吧哈哈