小程序 vant 项目记录总结 使用 scss 分享 订阅消息 wxs 分包 echarts图表 canvas getCurrentPages页面栈

编程入门 行业动态 更新时间:2024-10-20 05:27:10

小程序 vant 项目记录总结 使用 scss 分享 订阅消息 wxs 分包 echarts<a href=https://www.elefans.com/category/jswz/34/1770092.html style=图表 canvas getCurrentPages页面栈"/>

小程序 vant 项目记录总结 使用 scss 分享 订阅消息 wxs 分包 echarts图表 canvas getCurrentPages页面栈

小程序 + vant

vant

下载

npm init -ynpm i @vant/weapp -S --production

修改 app.json

将 app.json 中的 “style”: “v2” 去除

修改 project.config.json

{..."setting": {..."packNpmManually": true,"packNpmRelationList": [{"packageJsonPath": "./package.json","miniprogramNpmDistDir": "./"}]}
}

构建 npm 包

打开微信开发者工具,点击 工具 -> 构建 npm,并勾选 使用 npm 模块 选项,构建完成后,即可引入组件。

van-dialog

before-close 回调函数使用
不需要 confirm,cancel 事件

<van-dialog use-slot show="{{ show }}" before-close="{{ beforeClose }}"></van-dialog>
Page({onLoad() {this.setData({beforeClose: (action) => this.confirmScore(action),});},confirmScore(action) {return new Promise((resolve, reject) => {if (action === "cancel") return resolve(true);if (action === "confirm") {if (...) return resolve(false);return resolve(true);}});},
})

小程序

使用 typescript、less、sass

编译插件配置,目前支持编译插件有 typescript、less、sass
project.config.json

{"setting": {"useCompilerPlugins": ["typescript","sass"]}
}

表示项目支持直接使用 typescript 和 sass

.wxss 文件命名 .scss

setData 多种赋值写法

const index = 0;data: {list: [{page: 1,limit: 10,data: [],finished: false,},],obj: {name:'ls',},name: 'ls'
},
this.setData({name: 'xr',obj: {},'obj.name': 'xr','list[0].finished': true,`list[${index}].data`: [],[`list[${index}].data`]: []
})

getCurrentPages 页面栈使用

const pages = getCurrentPages();
const prePage = pages[pages.length - 2];// 获取上一页数据
console.log("prePage", prePage?.data.detail);
// 调用上一页方法
prePage?.save();
// 修改上一页数据
prePage.setData({"detail.name": "xr",
});

request 请求封装

封装 request
utils/http.js

import getBaseUrl from "./config";
import log from "./log";class CustomRequestInstance {static instance = null;static getInstance() {if (!this.instance) {this.instance = new CustomRequestInstance();}return this.instance;}request({ url = "", method = "get", data = {}, headers = {} }) {return new Promise((resolve, reject) => {wx.request({url: getBaseUrl() + url,header: {"content-type": "application/json",Authorization: `Bearer ${wx.getStorageSync("token")}`,...headers,},method: method.toUpperCase(),data: {...data,},success: function (res) {},fail: function (err) {log.error(`request-${url}-${err}`);reject(err);},});});}
}export default CustomRequestInstance;

封装 api
services/common.js

import Services from "../utils/http";const http = Services.getInstance();class CommonServices {// 获取城市async getCity() {const res = await http.request({ url: "/city" });return res;}
}export default new CommonServices();

使用

import CommonServices from "../../../services/common";const res = await CommonServices.getCity();

upload 封装

import getUrl from "./config";/*** uploadFile 封装* @param {*} Object { name = "file", filePath, ...rest }** @see [.chooseMedia.html](.chooseMedia.html)*/
export function customUpload({ name = "file", filePath, ...rest }) {return new Promise((resolve, reject) => {wx.uploadFile({url: `${getUrl()}/upload/image`,filePath,name,header: {Authorization: `Bearer ${wx.getStorageSync("token")}`,},...rest,success(res) {resolve(JSON.parse(res.data));},fail(error) {reject(error);},});});
}

组件

components/test/test.json

{"component": true,"usingComponents": {"van-icon": "@vant/weapp/icon/index"}
}

components/test/test.wxml

<view wx:if="{{show}}" class="mask"><van-icon class="remove" name="cross" catchtap="handleClose" />
</view>

components/test/test.js

Component({options: {// 在组件定义时的选项中启用多slot支持multipleSlots: true,// 使用全局 app.wxssaddGlobalClass: true,},/*** 组件的属性列表*/properties: {show: {type: Boolean,value: false,},},/*** 组件的初始数据*/data: {},// 监听observers: {show: function (newVal) {console.log("newVal", newVal);},},// // 生命周期函数,可以为函数,或一个在methods段中定义的方法名lifetimes: {// 可以使用 setDataattached: function () {console.log("attached");},moved: function () {console.log("moved");},detached: function () {console.log("detached");},},//  // 组件所在页面的生命周期函数pageLifetimes: {// 页面进入show: function () {console.log("show");},// 页面离开hide: function () {console.log("hide");},resize: function () {console.log("resize");},},/*** 组件的方法列表*/methods: {handleClose() {this.triggerEvent("close", { flag: false });},},
});
  • 实现默认插槽
Component({properties: {useDefaultSlot: {type: Boolean,value: false,},},
});

components/test/test.js

<view><view wx:if="{{ !useDefaultSlot }}">默认值</view><slot wx:else></slot><slot name="after"></slot>
</view>
{"usingComponents": {"x-text": "/components/test/test"}
}
<x-text useDefaultSlot><view>默认插槽</view><view slot="after">after 插槽</view>
</x-text>
  • 向外提供样式类
<view class="custom-class"></view>
Component({externalClasses: ["custom-class"],
});
<x-text custom-class="text-14px"></x-text>
  • 获取组件实例

可在父组件里调用 this.selectComponent ,获取子组件的实例对象。
父组件

Page({getChildComponent: function () {const child = this.selectComponent(".my-component");},
});

wxs 使用

在当前 wxml 中

<view wx:if="{{util.isHas(idList, userId)}}"></view><wxs module="util">
function isHas(arr, val) {return arr.indexOf(val) >= 0
}
module.exports.isHas = isHas
</wxs>

单独封装方法
utils/utils.wxs

module.exports = {formatNums: function (val) {if (val >= 1000) {val = (val / 1000) + 'K'}return val},
}<wxs module="tools" src="/utils/utils.wxs"></wxs>{{tools.formatNums(item.type)}}

获取元素信息 wx.createSelectorQuery()

如果在组件中,使用 this.createSelectorQuery()

const query = wx.createSelectorQuery();
query.select(".content").boundingClientRect();
query.exec((res) => {});

获取列表数据/加载更多/下拉刷新

data: {list: [{page: 1,limit: 10,data: [],finished: false,},],
},onReachBottom() {this.getData();
},
async onPullDownRefresh() {await this.getData(true);wx.stopPullDownRefresh();
},
async getData(refresh = false) {try {const index = 0;let { page, limit, data, finished } = this.data.list[index];if (refresh) {page = 1;finished = false;}if (finished) return;const res = await SkillServices.getFairList(page, limit);let list = [];if (res?.data?.length < limit) finished = true;else finished = false;if (refresh) list = res?.data;else list = [...data, ...res.data];this.setData({[`list[${index}].data`]: list,[`list[${index}].page`]: page + 1,[`list[${index}].finished`]: finished,});} catch (error) {console.log(error);}
},

实现文本隐藏展示查看更多功能

text-ellipsis.wxml

<view class="relative" wx:if="{{desc}}"><text class="{{showMore?'x-ellipsis--l3':''}} " style="line-height: {{lineHight}}px" ><text catchtap="handleLink">{{desc}}</text><text class="absolute primary more" bindtap="handleReadMore" wx:if="{{showMore}}">查看全部</text><text class="absolute primary more" bindtap="handleHideMore" wx:if="{{isExceed && !showMore}}">收起</text></text>
</view>
<block wx:else><slot></slot>
</block>

text-ellipsis.js

// pages/mine/visit/components/text-ellipsis/text-ellipsis.js
Component({options: {addGlobalClass: true,},properties: {lineHight: {type: Number,value: 22,},desc: {type: null,value: "",},},data: {showMore: false,isExceed: false, // 是否超过三行},observers: {desc(newValue) {// 如果当前被截断则直接返回if (this.data.showMore) return;if (newValue) this.init();},},methods: {handleLink() {this.triggerEvent("link");},handleHideMore() {this.setData({ showMore: true });},handleReadMore() {this.setData({ showMore: false });},init() {const { lineHight } = this.data;let showMore = false;let isExceed = false;var query = this.createSelectorQuery();query.select(".content").boundingClientRect();query.exec((res) => {var height = res[0]?.height;if (!height) return;var line = height / lineHight;if (line > 3) {showMore = true;isExceed = true;} else {showMore = false;isExceed = false;}this.setData({ showMore, isExceed });});},},
});
.more {bottom: 0;right: 0;background: #fff;padding-left: 10rpx;
}
.relative {position: relative;
}
.absolute {position: absolute;
}
.primary {color: var(--primary);
}

引入组件

{"usingComponents": {"x-text-ellipsis": "/components/text-ellipsis/text-ellipsis"}
}
<x-text-ellipsis desc="{{userInfo.desc}}"><view class="text-sm text-aaa">暂未填写简介</view>
</x-text-ellipsis>

订阅消息封装

export const requestSubscribeMessage = (tmplIds = ["MLCQvuq6kWY-jbH8Cxn-veoPZ6gJ8QTWiBpMV96mjs0"]) => {wx.requestSubscribeMessage({tmplIds,success(res) {console.log("requestSubscribeMessage res", res);// MLCQvuq6kWY-jbH8Cxn-veoPZ6gJ8QTWiBpMV96mjs0: "reject" 取消// MLCQvuq6kWY-jbH8Cxn-veoPZ6gJ8QTWiBpMV96mjs0: "accept" 同意tmplIds.forEach((tmplId) => {if (res[tmplId] === "accept") console.log(tmplId, "同意了");else if (res[tmplId] === "reject") console.log(tmplId, "拒绝了");});},fail(err) {console.log("requestSubscribeMessage err", err);},});
};

分享

onShareAppMessage(){return {title: '**',path: '/pages**',imageUrl: '/static/share.png'}
}

分包

others/pages/mine/mine.wxml
app.json

    ..."subPackages": [{"root": "others","pages": ["pages/mine/mine"]}],

防抖、节流

css

动画
/* pages/idea/form/form.wxss */@keyframes opacity-show {0% {opacity: 0;}to {opacity: 1;}
}
@keyframes opacity-hide {0% {opacity: 1;}to {opacity: 0;}
}@keyframes scale-show {0% {transform: scale(0);}to {transform: scale(1);}
}
@keyframes scale-hide {0% {transform: scale(1);}to {transform: scale(0);}
}
<view style="animation: opacity-show 2s ease,scale-show 2s ease;"></view>
.x-ellipsis {overflow: hidden;white-space: nowrap;text-overflow: ellipsis;
}
.x-ellipsis--l2,
.x-ellipsis--l3 {-webkit-box-orient: vertical;display: -webkit-box;overflow: hidden;text-overflow: ellipsis;
}
.x-ellipsis--l2 {-webkit-line-clamp: 2;
}
.x-ellipsis--l3 {-webkit-line-clamp: 3;
}.arrow::after {content: "";width: 15rpx;height: 15rpx;border-top: 3rpx solid ##ccc;border-right: 3rpx solid ##ccc;transform: rotate(45deg);
}/* 数字、字母过长不换行 */
.break-all {word-break: break-all;
}scroll-view::-webkit-scrollbar {width: 0;height: 0;color: transparent;
}
修改 vant css 变量
page {--van-picker-confirm-action-color: #08bebe;
}
修改 input placeholder 样式
<input value="{{ keyword }}" placeholder-class="placeholder-class" placeholder="请输入" bindinput="handleInput" />
.placeholder-class {color: #bbbbbb;
}

textarea 设置行高后,光标与 placeholder 不对齐
解决方案:使用 text 替换 placeholder

iPhone 13 pro 遇到的问题:
text 不要放在 textarea 标签内
定位后,给 text 一个事件,自动获取焦点

<view class="relative"><textareaclass="absolute left-0 top-0"focus="{{focus}}"bindblur="onBlur"model:value="{{value}}"disable-default-paddingmaxlength="{{-1}}"/><text class="text-aaa text-14px leading-28px absolute left-0 top-0" bindtap="onFocus" wx:if="{{!value}}">提示:请输入内容请输入内容请输入内容请输入内容请输入内容</text>
</view>
Page({data: {focus: false,value: "",},onFocus() {this.setData({ focus: true });},onBlur() {this.setData({ focus: false });},
});

Ios 底部安全距离

page {--ios-safe-bottom-low: constant(safe-area-inset-bottom); /* 兼容 iOS<11.2 */--ios-safe-bottom-higt: env(safe-area-inset-bottom); /* 兼容iOS>= 11.2 */
}
.safe-area-inset-bottom {padding-bottom: var(--ios-safe-bottom-low);padding-bottom: var(--ios-safe-bottom-higt);
}
setFormValue(value, num = undefined) {value = value.trim();if (num) value = value.slice(0, num);else value = value.slice(0);return value;
},

echarts-for-weixin

动态设置数据如下

echarts-for-weixin

xx.json

{"usingComponents": {"ec-canvas": "../../ec-canvas/ec-canvas"}
}

xx.wxml

<view class="container"><ec-canvas id="mychart-dom-bar" canvas-id="mychart-bar" ec="{{ ec }}"></ec-canvas></view>

xx.wxss

ec-canvas {width: 100%;height: 100%;}

xx.js

import * as echarts from '../../ec-canvas/echarts';let chart = null;
let option;
function initChart(canvas, width, height, dpr) {chart = echarts.init(canvas, null, {width: width,height: height,devicePixelRatio: dpr // 像素});canvas.setChart(chart);option = {xAxis: {type: "category",data: ["今日已完成", "本周已完成", "本月已完成", "本季度已完成"],},yAxis: {type: "value",},series: [{data: [10, 20, 150, 8],type: "bar",},],};chart.setOption(option);return chart;
}Page({data: {ec: {onInit: initChart}},onLoad() {setTimeout(() => {option.series[0].data = [10, 20, 150, 8, 70]chart.setOption(option);}, 2000);},
});

百度人脸对比

common/baidu/config.js


const configArrary = [{grant_type: 'client_credentials',client_id: 'xxx',client_secret: 'xxxx',access_token: '',},
]module.exports = configArrary

common/baidu/baidu.js

const configArrary = require("config.js");class Baidu {errorCode = {222202: "图片中没有人脸或者图片质量太差",222203: "无法解析人脸;图片质量太差",223123: "质量检测未通过 左脸遮挡程度过高",223122: "质量检测未通过 右眼遮挡程度过高",223121: "质量检测未通过 左眼遮挡程度过高",223120: "活体检测未通过",223124: "质量检测未通过 右脸遮挡程度过高",223125: "质量检测未通过 下巴遮挡程度过高",223126: "质量检测未通过 鼻子遮挡程度过高",223127: "质量检测未通过 嘴巴遮挡程度过高",223114: "人脸模糊",};getTokenAsync() {return new Promise((resolve, reject) => {const that = this;wx.request({url: ".0/token",data: {grant_type: that.config.grant_type,client_id: that.config.client_id,client_secret: that.config.client_secret,},success(res) {return resolve(res.data.access_token);},fail(err) {reject(err);},});});}async faceMatch(image) {const that = this;const newToken = await this.getTokenAsync();return new Promise((resolve, reject) => {wx.request({method: "POST",url: ".0/face/v3/match?access_token=" + newToken,data: [...image],success(res) {res = res.data;if (res.error_code !== 0) {reject(that.errorCode[String(res.error_code)]? that.errorCode[String(res.error_code)]: "人脸识别失败,请重试!" + String(res.error_code));} else {if (res.result.score < 80) {reject("人脸不匹配,请重试!");}}resolve(res);},fail(err) {reject(err);},});});}
}module.exports = Baidu;

使用

const Baidu = require("../../../common/baidu/baidu.js");let  baidu = new Baidu();await baidu.faceMatch([{image: base64Img,face_type: "LIVE",image_type: "BASE64",quality_control: "LOW",liveness_control: "NORMAL",},{image: userDetail.faceImg,face_type: "LIVE",image_type: "URL",quality_control: "LOW",liveness_control: "NONE",},
]);

更多推荐

小程序 vant 项目记录总结 使用 scss 分享 订阅消息 wxs 分包 echarts图表 canvas getCurrentPages页面栈

本文发布于:2024-03-23 19:36:13,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1741997.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:图表   消息   页面   程序   项目

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!