当前位置: 首页 > news >正文

小程序 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 [https://developers.weixin.qq.com/miniprogram/dev/api/media/video/wx.chooseMedia.html](https://developers.weixin.qq.com/miniprogram/dev/api/media/video/wx.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);},
});
http://www.lryc.cn/news/125655.html

相关文章:

  • 关于Power Query中一些忽略的细节
  • QML与C++交互
  • Microsoft ISA服务器配置及日志分析
  • Openlayers 实战 - 地图视野(View)- 图层 -(layer)- 资源(source)显示等级设置。
  • Linux:shell脚本 正则表达式与AWK
  • Android UI自动化测试框架—SoloPi简介
  • Android Studio Giraffe 正式版下载地址
  • 【C语言】调试技巧
  • MySQL SUBSTRING_INDEX() 函数的详细介绍
  • 开源数据库Mysql_DBA运维实战 (DML/DQL语句)
  • 【LangChain】Memory
  • Java并发编程(六)线程池[Executor体系]
  • macOS CLion 使用 bits/stdc++.h
  • PS出现的问题——为什么PS另存的格式少了很多
  • 【Linux】进程通信篇Ⅱ:共享内存、消息队列、信号量
  • 8.14 校招 内推 面经
  • 阿里云服务器安装部署Docker使用教程
  • WebRTC | ICE详解
  • 网络设备(防火墙、路由器、交换机)日志分析监控
  • 2023年国赛数学建模思路 - 复盘:人力资源安排的最优化模型
  • Compute shader SV 理解图
  • 生信豆芽菜-多种算法计算免疫浸润
  • 逆向破解学习-单机斗地主
  • matplotlib绘制位置-时序甘特图
  • 数据库概述、部署MySQL服务、必备命令、密码管理、安装图形软件、SELECT语法 、筛选条件
  • 概率论与数理统计:第四章:随机变量的数字特征
  • 解决饿了么ui的对话框缩放和移动
  • Linux 中复制文件并保持修改时间等属性
  • Hugging News #0814: Llama 2 学习资源大汇总
  • ​可视化绘图技巧100篇进阶篇(五)-阶梯线图(Step Chart)