app.json配置
管理页面路由,窗口设置,tabBar配置
JSON
{
"pages": [
"pages/index/index",
"pages/logs/logs",
"pages/list/list",
"pages/profile/profile"
],
"window": {
"backgroundTextStyle": "dark",
"navigationBarBackgroundColor": "#f00",
"navigationBarTitleText": "云和商城",
"navigationBarTextStyle": "black",
"enablePullDownRefresh": true
},
"tabBar": {
"color": "#f96677",
"selectedColor": "#567788",
"list": [
{
"pagePath": "pages/index/index",
"text": "首页",
"iconPath": "/images/icon1.png",
"selectedIconPath": "/images/icon0.png"
},
{
"pagePath": "pages/profile/profile",
"text": "个人中心"
},
{
"pagePath": "pages/list/list",
"text": "列表"
},
{
"pagePath": "pages/logs/logs",
"text": "日志"
}
]
},
"style": "v2",
"sitemapLocation": "sitemap.json"
}
如果是tabbar页面,在全局page.json的navbar也设置了
注意:如果tabBar中添加的有index,shopcar,日志页面,那么只有这三个页面带有tabBar,其他页面为空
1.2 常用样式
"backgroundTextStyle":"light", 下拉 loading 的样式,仅支持 dark / light
"backgroundColor":"#fff000", 窗口的背景色
"navigationBarBackgroundColor": "#fff", 导航栏背景颜色,
"navigationBarTitleText": "Weixin", 导航栏标题文字内容
"navigationBarTextStyle":"black" 导航栏标题颜色,仅支持 black / white
"enablePullDownRefresh":true 是否开启全局的下拉刷新。
"onReachBottomDistance": 100 页面上拉触底事件触发时距页面底部距离,单位为 px。
1.3 注意事项
-
json文件中不能写注释
-
backgroundTextStyle, backgroundColor这两条配置都必须开启下拉刷新才有效果
-
tabBar最少2个,最多5个
1.4 style的作用
微信客户端 7.0 开始,UI 界面进行了大改版。小程序也进行了基础组件的样式升级。app.json 中配置 "style": "v2"可表明启用新版的组件样式。
app.js中全局数据的访问
定义
JSON
globalData: {
city: '郑州'
}
在page中获取
JavaScript
const app = getApp()
console.log(app.globalData.city)
设置
JavaScript
app.globalData.city = '洛阳'
page中响应式数据的访问
定义
JSON
data: {
msg: 'hello'
}
获取
JavaScript
let msg = this.data.msg
更改
JavaScript
this.setData({
msg: '新值'
})
WXML语法
插值语法:{{ }}
HTML
//属性和内容的数据绑定
<view id="item-{{num}}" hidden="{{isShow}}">{{title}}</view>
//类名的数据绑定
<view class="{{flag?'red':'blue'}}">红色或蓝色</view>
//布尔值
<view hidden="{{true}}">红色或蓝色</view>
wx:if wx:elif wx:else
HTML
<view wx:if="{{score<= 60}}">及格</view>
<view wx:elif="{{ score < 75}}">良好</view>
<view wx:else>优秀</view>
hidden属性
wx:for
HTML
//item,index为默认属性
<view wx:for="{{list}}" wx:key="*this">{{item}}-----{{index}}</view>
//自定义item,index
<view wx:for="{{list}}" wx:key="*this" wx:for-item="color" wx:for-index="idx">{{color}}-----{{idx}}</view>
用wx:for遍历复杂数据
数据
JavaScript
list: [
{
"title": "图书",
"data": [
{
"id": 3,
"goodsName": "西游记"
},
{
"id": 8,
"goodsName": "水湖"
},
]
},
{
"title": "手机",
"data": [
{
"id": 9,
"goodsName": "华为"
},
{
"id": 18,
"goodsName": "vivo"
},
{
"id": 28,
"goodsName": "小米"
},
]
}
]
模板
HTML
<view class="list">
<view class="bigItem" wx:for="{{list}}" wx:key="*this">
<view class="title">{{item.title}}</view>
<block wx:for="{{item.data}}" wx:for-item="smallItem" wx:key="id">
<view class="smallItem">
<view class="id">{{smallItem.id}}</view>
<view class="goodsName">{{smallItem.goodsName}}</view>
</view>
</block>
</view>
</view>
在页面中使用阿里巴巴矢量图
-
图标添加到我的项目中
-
下载自己项目中的样式
![[3980b3e2-c87a-4719-9360-1cab0096d8b4.png]]
-
在pages同级的位置创建assets文件夹
里面创建css - iconfont.wxss
直接把在线的样式,粘贴进入
-
需要引入 iconfont.wxss[注意:只能在wxss中引入当前文件]
CSS
@import "/assets/css/iconfont.wxss"
- 在wxml中使用icon标签引入小图标
HTML
<icon class="iconfont icon-fangdajing"></icon>
<icon class="iconfont icon-shouye"></icon>
轮播图
swiper.js
JavaScript
Page({
data: {
background: ['demo-text-1', 'demo-text-2', 'demo-text-3'],
indicatorDots: true,
vertical: false,
autoplay: true,
circular: false,
interval: 2000,
duration: 500,
previousMargin: 0,
nextMargin: 0
}
})
swiper.wxml
HTML
<view class="page-body">
<view class="page-section page-section-spacing swiper">
<swiper indicator-dots="{{indicatorDots}}" autoplay="{{autoplay}}" circular="{{circular}}" vertical="{{vertical}}" interval="{{interval}}" duration="{{duration}}" previous-margin="{{previousMargin}}px" next-margin="{{nextMargin}}px">
<block wx:for="{{background}}" wx:key="*this">
<swiper-item>
<view class="swiper-item">{{item}}</view>
</swiper-item>
</block>
</swiper>
</view>
</view>
关闭sitemap的索引提示
sitemap 的索引提示是默认开启的 如需要关闭 sitemap 的索引提示,可在小程序项目配置文件 project.config.json 的 setting 中配置字段 "checkSiteMap": false
Vant Weapp UI组件库的使用
对于小程序中的ui组件库有很多,比如说:vant,tdesign,WeUI
WeUI套同微信原生视觉体验一致的基础样式库,由微信官方设计团队为微信内网页和微信小程序量身设计,令用户的使用感知更加统一。
Vant 是有赞前端团队开源的移动端组件库
官网地址: https://vant-contrib.oschina.io/vant-weapp/#/home 使用步骤
- 打开终端,初始化,生成package.json
项目目录不能有中文,必须是规范的nodejs项目目录
Bash
npm init -y
- 通过npm安装vant weapp
Bash
npm i @vant/weapp -S --production
- 修改 app.json
JavaScript
将 app.json 中的 "style": "v2" 去除,小程序的新版基础组件强行加上了许多样式,难以覆盖,不关闭将造成部分组件样式混乱。
- 修改 project.config.json
JSON
{
...
"setting": {
...
"packNpmManually": true,
"packNpmRelationList": [
{
"packageJsonPath": "./package.json",
"miniprogramNpmDistDir": "./"
}
]
}
}
- 构建npm包
打开微信开发者工具,点击 工具 -> 构建 npm,构建完成后,即可引入组件。
- 引入组件
以 Button 组件为例, 在app.json或page.json中
JSON
"usingComponents": {
"van-button": "@vant/weapp/button/index"
}
- 使用组件
引入组件后,可以在 wxml 中直接使用组件
HTML
<van-button type="primary">按钮</van-button>
weUI的地址:https://wechat-miniprogram.github.io/weui/docs/
链接:https://wechat-miniprogram.github.io/weui/docs/quickstart.html#使用之前
表单组件的使用
input组件
wxml
HTML
<input placeholder="请输入用户名" bindinput="onInput" />
js
JavaScript
onInput(e){
console.log(e.detail.value);
},
checkbox组件
wxml
HTML
<checkbox-group bindchange="onCheck">
<checkbox value="a" checked="{{true}}">a</checkbox>
<checkbox value="b">b</checkbox>
</checkbox-group>
js
JavaScript
onCheck(e){
console.log(e.detail.value);
},
radio组件
wxml
HTML
<radio-group bindchange="onRadio">
<radio value="1">1</radio>
<radio value="2">2</radio>
</radio-group>
js
JavaScript
onRadio(e){
console.log(e.detail.value);
}
点餐页面
menu.wxml
HTML
<view class="main">
<view class="left">
<scroll-view scroll-y="true" >
<view
wx:for="{{list}}"
wx:key="index"
class="{{activeIndex === index ? 'active':''}}"
data-index="{{index}}"
bindtap="toggle"
>{{item.name}}</view>
</scroll-view>
</view>
<view class="right">
<scroll-view scroll-y="true" bindscroll="scroll" scroll-into-view="wrapper{{curIndex}}"
scroll-with-animation="{{true}}">
<view class="wrapper" wx:for="{{list}}" wx:key="index" id="wrapper{{index}}">
<view class="title">{{item.name}}</view>
<view
class="item"
wx:for="{{item.foods}}"
wx:for-item="food"
wx:for-index="idx"
wx:key="idx"
>
<view>{{food.name}}</view>
<view>{{food.price}}</view>
</view>
</view>
</scroll-view>
</view>
</view>
menu.wxss
CSS
.main {
display: flex;
position: absolute;
left: 0;
bottom: 0;
right: 0;
top: 0;
}
.bg {
background-color: #f00;
}
.left {
width: 250rpx;
background: rgb(224, 209, 67);
overflow: hidden;
}
.right {
flex: 1;
overflow: hidden;
}
scroll-view {
height: 100%;
overflow: hidden;
}
.left view {
height: 300rpx;
border: 1px solid #eee;
}
.right .title {
height: 60rpx;
background-color: rgb(236, 133, 133);
}
.right .item {
height: 300rpx;
border: 1px solid #aaa;
margin: 10rpx;
}
.left .active {
background-color: rgb(61, 218, 210);
}
menu.js
JavaScript
Page({
data: {
list: [],
activeIndex: 0,
curIndex: 0,
listHeight: []
},
onLoad() {
this.getData()
},
// 获取数据
getData() {
wx.request({
url: 'http://localhost:3000/goods',
success: (res) => {
this.setData({
list: res.data
})
this.getListHeigth()
}
})
},
//切换菜单
toggle(e) {
let index = e.currentTarget.dataset.index;
this.setData({
activeIndex: index,
curIndex: index
})
},
//监听滚动的位置
scroll(e) {
let scrollTop = e.detail.scrollTop
console.log(scrollTop);
let flag = true;
let index;
for (let i = 0; i < this.data.listHeight.length - 1; i++) {
if (scrollTop >= this.data.listHeight[i] && scrollTop < this.data.listHeight[i + 1]) {
flag = false;
index = i;
break;
}
}
if (flag) {
index = this.data.listHeight.length - 1;
}
this.setData({
activeIndex: index
})
},
//获取列表高度
getListHeigth() {
//获取 SelectorQuery 对象实例,可以得到类似dom操作中的属性值
const query = wx.createSelectorQuery();
// 查询相关的节点及属性值
query.selectAll(".wrapper").boundingClientRect();
//执行上面定义的查询
query.exec(res => {
// 返回了每一个节点的top值及其它属性值
console.log('res', res);
let tempArr = res[0].map(item => {
return item.top
})
this.setData({
listHeight: tempArr
})
})
}
})
wx.createSelectorQuery()如果在自定义组件中使用,要把wx改为this. this.createSelectorQuery()
授权信息
app.json
JSON
{
"pages":[
"pages/index/index",
"pages/logs/logs",
"pages/menu/menu",
"pages/auth/auth"
],
"window":{
"backgroundTextStyle":"light",
"navigationStyle":"custom",
"navigationBarBackgroundColor": "#fff",
"navigationBarTitleText": "Weixin",
"navigationBarTextStyle":"black"
},
"permission": {
"scope.userLocation": {
"desc": "你的位置信息将用于小程序位置接口的效果展示"
}
},
"style": "v2",
"sitemapLocation": "sitemap.json"
}
auth.wxml
HTML
<view><button type="primary" bindtap="getAuth">获取授权信息</button></view>
<view><button type="primary" bindtap="getUserInfo">获取用户信息</button></view>
<view><button type="primary" bindtap="getLocation">获取地理定位信息</button></view>
<map longitude="{{longitude}}" latitude="{{latitude}}"></map>
auth.wxss
CSS
view {
margin: 30rpx;
}
map {
width: 100%;
height: 600rpx;
}
auth.js
JavaScript
Page({
data:{
longitude:'',
latitude: ''
},
//页面加载时获取经纬度
onLoad: function () {
wx.getLocation({
type: 'gcj02',
success:(res)=>{
const latitude = res.latitude
const longitude = res.longitude
let key = "6ESBZ-MQECU-BVFVV-4O5A3-J3ZH2-OUBDU"
this.getCityInfo(latitude, longitude, key)
},
fail(error) {
throw new Error("获取位置信息失败...")
}
})
},
getCityInfo(lat, lng, mapKey, callback) {
// 逆位置解析
// https://lbs.qq.com/webservice_v1/guide-gcoder.html
wx.request({
// SDK
url:
https://apis.map.qq.com/ws/geocoder/v1/?location=${lat},${lng}&key=${mapKey}
,
success: res => {
console.log(res.data.result);
}
})
}
,
//获取授权信息
getAuth() {
wx.getSetting({
success: res => {
// console.log(res.authSetting["scope.userInfo"]);
console.log(res.authSetting);
}
})
},
// 获取用户信息
getUserInfo() {
wx.getUserProfile({
desc: '用于完善会员资料', // 声明获取用户个人信息后的用途,后续会展示在弹窗中,请谨慎填写
success: (res) => {
//可获取头像,昵称,地区等信息
console.log(res);
}
})
},
getLocation() {
console.log(1);
wx.getLocation({
type: 'gcj02',
success: (res)=> {
let {longitude,latitude} = res
// console.log(res);
this.setData({
longitude,
latitude
})
}
});
}
})
小程序API封装
api/config.js
JavaScript
const httpServiceURL = "http://localhost:3000"; //测试环境
//post请求头
const formHeader = {
'content-type': 'application/x-www-form-urlencoded;charset=utf-8'
};
const jsonHeader = {
'content-type': 'application/json;charset=utf-8'
};
module.exports = {
httpServiceURL,
formHeader,
jsonHeader
}
api/http.js
JavaScript
const config = require("./config")
const requestUrl = {
scan: '/qrcode/scan', //扫码记录接口
login: '/miniapp/user/login', //登录
// register: '/miniapp/user/register', //注册
register: '/goods', //注册
recentMall: '/webank/mall/recentMall', //最近门店
getCityByFirstChar: '/webank/mall/getCityByFirstChar', //城市列表
allMall: '/webank/mall/allMall', //门店列表
getOperationInfo: '/operation/operationInfo/get', //品类管理:banner轮播、超值领券
getUserCouponCount: '/coupon/getUserCouponCount', //banner轮播
recommend: '/coupon/recommend', //优惠券推荐列表
couponReceive: '/coupon/receive', //领取优惠券接口(知而行优惠券)
sendCouponStock: '/coupon/sendCouponStock', //发放单品券接口
getCouponInfo: '/coupon/getCouponInfo', //超值领券-优惠券详情
getUserShopCoupon: '/coupon/getUserShopCoupon', //我的当前门店的优惠券列表
getUserCoupon: '/coupon/getUserCoupon', //获取用户优惠券(当前门店、未使用、已使用、已过期)
getMemberCardInfo: '/miniapp/user/getMemberCardInfo', //查询会员卡信息接口
verifyCoupon: '/coupon/verifyCoupon', //优惠券核销接口
};
module.exports = {
// 接口标识符
get: (method, data) => {
return new Promise((resolve, reject) => {
data = data || {};
wx.request({
url: config.httpServiceURL + requestUrl[method],
method: 'GET',
data: data,
success: res => {
resolve(res);
},
fail: res => {
reject(res);
}
});
});
},
// postForm
post: (method, data) => {
return new Promise((resolve, reject) => {
data = data || {};
wx.request({
// http://localhost:3000/miniapp/user/register"
url: config.httpServiceURL + requestUrl[method],
method: 'POST',
data: data,
header: config.formHeader,
success: res => {
resolve(res);
},
fail: res => {
reject(res);
}
});
})
}
}
在组件中使用:
JavaScript
const http = require("../../api/http.js")
Page({
data: {
color: ['#f00', '#0f0', '#00f'],
list: [111, 222, 333],
cur: 'demo0'
},
// 页面初始化时,请求注册接口
onLoad() {
this.getData()
},
async getData() {
try {
let res = await http.get("register", {
user: 'aa',
pw: '123'
})
console.log(res,);
}catch(err){
console.log(err);
}
}
})
用swiper组件实现tab切换
tab.wxml
HTML
<view class="tab">
<button type="primary" bindtap="toggle" data-id="0">冬奥会</button>
<button type="primary" bindtap="toggle" data-id="1">新冠疫情</button>
<button type="primary" bindtap="toggle" data-id="2">娱乐八卦</button>
</view>
<!-- current决定当前显示哪个swiper-item -->
<swiper indicator-dots="{{indicatorDots}}" autoplay="{{autoplay}}" interval="{{interval}}" duration="{{duration}}" current="{{current}}">
<swiper-item class="s1">
冬奥会内容
</swiper-item>
<swiper-item class="s2">
新冠疫情内容
</swiper-item>
<swiper-item class="s3">
娱乐八卦内容
</swiper-item>
</swiper>
tab.js
JavaScript
Page({
data: {
vertical: false,
autoplay: false,
interval: 2000,
duration: 500,
current: 0
},
toggle(e){
let {id} = e.target.dataset
this.setData({
current: id
})
}
})
在微信小程序中用sass写wxss
在Visual Studio Code中安装插件Easy Sass
![[b11f9863-5cef-44b8-ad33-37e52fd11588.png]]
微信开发者工具中导入已安装的vscode插件!
选择vscode下的sass文件夹
![[4e3eb873-26af-40a6-9847-6ef7f3451f49.png]]
![[04f4ad40-feb9-46fd-9297-801b7c7f7434.png]]
编辑---> 打开编辑器扩展目录--->找到spook.easysass-0.0.6文件夹
![[ea74190c-0d96-4d77-a964-5ddaa3f4c44f.png]]
进入文件夹中修改package.json
![[8d481782-db01-41d1-ae3e-edbe8e3c49d3.png]]
![[7f4374f2-a91b-484b-bbd1-a1d269bb3b45.png]]
重启微信开发者工具
在页面中创建page.scss, 保存时即会编译为wxss
![[46f1cb8a-467a-4bb4-a523-cb08e8933a50.png]]
微信小程序登录流程
面试回答
小程序可以通过微信官方提供的登录能力方便地获取微信提供的用户身份标识,快速建立小程序内的用户体系。
-
首先需要调用小程序api接口 wx.login() 获取 临时登录凭证code ,然后将这个code回传到开发者服务器
-
开发者服务器调用微信的登录接口,把appid, app密钥,code码,传给微信后台
-
微信后台验证成功后,返回给开发者服务器用户的唯一标识(openid)及本次登录的会话密钥(session_key))
-
开发者服务器会与openid相关联生成token,并传回小程序端
-
小程序端把token存入缓存
-
当小程序端请求服务器接口数据时,会携带token, 服务器验证token后会返回小程序所需的业务数据
流程图
![[3c4b15cd-5941-4033-a0a1-48b36d0de3be.png]]
案例代码
小程序端
JavaScript
login() {
//获取code码
wx.login({
success: (res) => {
let {code } = res
//请求开发者服务器
wx.request({
url: 'http://localhost:3000/login',
data: {
code
},
success: (res)=>{
let {token} = res.data
wx.setStorageSync('token', token)
wx.showToast({
title: '登录成功',
})
}
})
}
})
}
服务器端 app.js
JavaScript
// 服务器后端 app.js
const express = require("express")
const axios = require("axios")
const app = express()
/**
微信登录
*/
app.get('/login', (req, res) => {
let { code } = req.query;
// 小程序的AppSecret密钥
let secret = "8a7d670324c37538cb15c4971cee0eb0"
let appid = "wxf7177a507a7fc69a"
let url =
https://api.weixin.qq.com/sns/jscode2session?appid=${appid}&secret=${secret}&js_code=${code}&grant_type=authorization_code
// 向微信的授权接口发送请求
axios.get(url)
.then(res1 => {
console.log(res1);
let { openid } = res1.data;
let token = "ererereteteterdvdgtgrtgrtrtrtrdfrdter"
res.send({
token,
msg: '登录成功'
})
})
})
app.listen(3000,()=>{
console.log('服务器已开启在3000端口');
})
微信支付
参考链接: https://pay.weixin.qq.com/wiki/doc/apiv3_partner/open/pay/chapter2_8_0.shtml
面试回答
简答 : 下单后,后台接口返回一些参数,我用wx.requestPayment向微信发起支付请求,携带后台的参数,成功后,显示成功页面即可
Plain
1.打开小程序,点击直接下单。
2.wx.login获取用户临时登录凭证code,发送到后端服务器换取openId。
3.在下单时,小程序需要将购买的商品Id,商品数量,以及用户的openId传送到开发者服务器。
4.开发者服务器在接收到商品Id、商品数量、openId后,生成服务器订单数据(存入订单表),同时经过一定的签名算法,向微信支付发送请求,获取预付单信息(prepay_id),同时将获取的数据再次进行相应规则的签名,向小程序端响应必要的信息。
5.小程序端在获取对应的参数后,调用wx.requestPayment()发起微信支付,唤醒支付工作台,进行支付。
6.接下来的一些列操作都是由用户来操作的包括了微信支付密码,指纹等验证,确认支付之后执行鉴权调起支付。
7.鉴权调起支付:在微信后台进行鉴权,微信后台直接返回给前端支付的结果,前端收到返回数据后对支付结果进行展示。
8.推送支付结果:微信后台在给前端返回支付的结果后,也会向后台(商家后台)也返回一个支付结果,后台通过这个支付结果来更新订单的状态。
示例代码
小程序代码 以下参数皆为开发者服务器下单接口响应的数据
JavaScript
wx.requestPayment({
// 时间戳
timeStamp: '',
// 随机字符串
nonceStr: '',
// 统一下单接口返回的 prepay_id 参数值
package: '',
// 签名算法,应与后台下单时的值一致
signType: '',
// 签名
paySign: '',
// 调用成功回调
success () {},
// 失败回调
fail () {},
// 接口调用结束回调
complete () {}
})
微信小程序支付流程图
![[93bf79d9-d90c-4059-bd9a-b14e2a703743.png]]
![[3a0dfebd-7beb-442d-be0e-9644c7267bf6.png]]
![[07025962-69ca-4bbb-845f-5395c3b199c2.png]]
webView
参考链接: https://developers.weixin.qq.com/miniprogram/dev/component/web-view.html 承载网页的容器。会自动铺满整个小程序页面,个人类型的小程序暂不支持使用。
需求
-
小程序启动,即在小程序的index页面全屏显示h5页面index.html
-
在h5页面index.html中单击按钮跳转到小程序的list页面
-
在小程序的list页面中单击按钮跳转至H5页面的h5.html
-
在H5页面的h5.html中单击按钮返回list页面
创建h5页面index.html 和h5.html
index.html
HTML
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<h1>我是小程序的index页面中使用webview显示的h5页面</h1>
<p><button class="btn">跳转到小程序的列表页</button></p>
<!-- web-view网页中可使用JSSDK 1.3.2提供的接口返回小程序页面。 -->
<!--
接口名 说明
wx.miniProgram.navigateTo 参数与小程序接口一致 1.6.4
wx.miniProgram.navigateBack 参数与小程序接口一致 1.6.4
wx.miniProgram.switchTab 参数与小程序接口一致 1.6.5
wx.miniProgram.reLaunch 参数与小程序接口一致 1.6.5
wx.miniProgram.redirectTo 参数与小程序接口一致 1.6.5
wx.miniProgram.postMessage 向小程序发送消息,会在特定时机(小程序后退、组件销毁、分享)触发组件的message事件 1.7.1
wx.miniProgram.getEnv 获取当前环境 1.7.1 -->
<script src="https://res.wx.qq.com/open/js/jweixin-1.3.2.js"></script>
<script>
let btn = document.querySelector(".btn")
btn.onclick = function () {
wx.miniProgram.navigateTo({
url: "/pages/list/list"
})
}
</script>
</body>
</html>
h5.html
HTML
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<p>我是从小程序跳过来的h5页</p>
<p><button class="btn">跳回小程序</button></p>
<script src="https://res.wx.qq.com/open/js/jweixin-1.3.2.js"></script>
<script>
let btn = document.querySelector(".btn")
btn.onclick = function () {
wx.miniProgram.navigateTo({
url: "/pages/list/list"
})
}
</script>
</body>
</html>
利用json-server把h5页面运行在服务器上
-
在h5根目录,创建一个db.json, 放入符合json-server规则的数据
-
注意: index.html和h5.html都放在h5的根目录
-
在cmd运行json-server -w db.json -s ./
-
在浏览器输入 localhost:3000/index.html可以看到index.html即可
小程序的代码
index.wxml
HTML
<web-view src="http://localhost:3000/"></web-view>
list.wxml
HTML
<view hidden="{{url}}">
<view> 我是小程序的list页面</view>
<view><button bindtap="goPage" type="primary">跳至h5页</button> </view>
</view>
<web-view src="{{url}}" wx:if="{{url}}"></web-view>
list.js
JavaScript
Page({
data: {
url: ''
},
goPage(){
this.setData({
url: 'http://localhost:3000/h5.html'
})
}
})
注意事项
一定要在小程序中勾选: 不校验合法域名、web-view(业务域名)、TLS版本以及HTTPS证书
自定义tabBar
将tabBar作为自定义组件,在需要添加的文件中进行引入
去掉系统生成的tabBar
在 app.json 中的 tabBar 项指定 custom 字段,同时其余 tabBar 相关配置也补充完整。
JSON
"tabBar": {
"custom": true, // 重要
"color": "#567788",
"selectedColor": "#f96677",
"list": [
{
"pagePath": "pages/index/index",
"text": "首页",
"iconPath": "/images/icon0_0.png",
"selectedIconPath": "/images/icon0_1.png"
},
{
"pagePath": "pages/shop/shop",
"text": "商城",
"iconPath": "/images/icon1_0.png",
"selectedIconPath": "/images/icon1_1.png"
},
{
"pagePath": "pages/promotion/promotion",
"text": "活动",
"iconPath": "/images/icon2_0.png",
"selectedIconPath": "/images/icon2_1.png"
},
{
"pagePath": "pages/mine/mine",
"text": "我的",
"iconPath": "/images/icon3_0.png",
"selectedIconPath": "/images/icon3_1.png"
}
]
},
在单个页面中添加自定义导航栏
wxml
HTML
<view class="tab-bar">
<navigator url="/pages/index/index" open-type="switchTab">
<view>
<image src="/images/icon0_1.png"></image>
</view>
<view>首页</view>
</navigator>
<navigator url="/pages/shop/shop" open-type="switchTab">
<view>
<image src="/images/icon1_0.png"></image>
</view>
<view>商城2</view>
</navigator>
<navigator url="/pages/promotion/promotion" open-type="switchTab">
<view>
<image src="/images/icon2_0.png"></image>
</view>
<view>活动</view>
</navigator>
<navigator url="/pages/mine/mine" open-type="switchTab">
<view>
<image src="/images/icon3_0.png"></image>
</view>
<view>我的</view>
</navigator>
</view>
wxss
CSS
.top {
width: 100%;
height: 300rpx;
outline: 1px solid #000;
}
.tab-bar {
position: fixed;
display: flex;
justify-content: space-around;
left: 0;
bottom: 0;
width: 100%;
height: 150rpx;
background-color: #c8e44a;
}
.tab-bar image {
width: 80rpx;
height: 80rpx;
}
用自定义组件实现自定义tabBar
根目录创建components/tabBar文件夹,并新建ComponenttabBar.wxml
HTML
<view class="tab-bar">
<block wx:for="{{tabBar.list}}" wx:key="text">
<navigator url="/{{item.pagePath}}" open-type="switchTab">
<view>
<image src="{{cur === index? item.selectedIconPath : item.iconPath}}" class="img"></image>
</view>
<view style="color:{{cur === index ? tabBar.selectedColor : tabBar.color}}">{{item.text}}</view>
</navigator>
</block>
</view>
tabBar.js
JavaScript
Component({
properties: {
cur: {
type: Number
}
},
data: {
"tabBar": {
"color": "#567788",
"selectedColor": "#f96677",
"list": [{
"pagePath": "pages/index/index",
"text": "首页",
"iconPath": "/images/icon0_0.png",
"selectedIconPath": "/images/icon0_1.png"
},
{
"pagePath": "pages/shop/shop",
"text": "商城",
"iconPath": "/images/icon1_0.png",
"selectedIconPath": "/images/icon1_1.png"
},
{
"pagePath": "pages/promotion/promotion",
"text": "活动",
"iconPath": "/images/icon2_0.png",
"selectedIconPath": "/images/icon2_1.png"
},
{
"pagePath": "pages/mine/mine",
"text": "我的",
"iconPath": "/images/icon3_0.png",
"selectedIconPath": "/images/icon3_1.png"
}
]
},
},
methods: {
}
})
在各个tabBar页面的wxml中引入 *.json
JSON
{
"usingComponents": {
"tab-bar":"/components/tabBar/tabBar"
},
"navigationBarBackgroundColor": "#c8e44a",
"navigationBarTitleText": "首页"
}
*.wxml
HTML
<view class="top">
首页
</view>
<tab-bar cur="{{0}}"></tab-bar>
注意:自定义tabBar在初次渲染时会有闪动,可以把所有tabBar页面做成一个页面,而所谓的页面只是不同组件的切换
方法二:自动将custom-tab-bar中的内容渲染为tabBar
在app.json文件中,编辑代码
JSON
"tabBar":{
"custom": true,
"list":[
{
"pagePath":"pages/index/index",
"text":"首页"
},{
"pagePath":"pages/my/my",
"text":"我的"
}
]
创建自定义tabBar
点击加号,在根目录新建一个custom-tab-bar文件夹【注意:文件夹的名称必须为custom-tab-bar】
然后右键该文件夹,点击新建components,输入index,回车,就会自动创建四个文件
此时我们可以看到小程序底部出现,就代表创建成功了。因为他自动识别了tabBar页面。
custom-tab-bar下的代码
index.wxml
HTML
<cover-view class="tab-bar">
<cover-view wx:for="{{list}}" wx:key="index" class="tab-bar-item" data-path="{{item.pagePath}}" data-index="{{index}}" bindtap="switchTab">
<cover-image src="{{selected === index ? item.selectedIconPath : item.iconPath}}"></cover-image>
</cover-view>
</cover-view>
index.wxss
CSS
.tab-bar {
position: fixed;
bottom: 0;
left: 0;
right: 0;
height: 80rpx;
background: white;
display: flex;
padding-bottom: env(safe-area-inset-bottom);
justify-content: center;
}
.tab-bar-item {
text-align: center;
display: flex;
flex-direction: column;
/* border: 1px solid #f00; */
}
.tab-bar-item cover-image {
width: 80rpx;
height: 80rpx;
}
.tab-bar-item cover-view {
font-size: 10px;
}
index.js
JavaScript
Component({
/**
组件的属性列表
*/
properties: {
},
/**
组件的初始数据
*/
data: {
selected: 0,
color: "#7A7E83",
selectedColor: "#3cc51f",
list: [{
"pagePath": "/pages/index/index",
"iconPath": "/images/index1.png",
"selectedIconPath": "/images/index2.png",
"text": "首页"
}, {
"pagePath": "/pages/my/my",
"iconPath": "/images/my1.png",
"selectedIconPath": "/images/my2.png",
"text": "我的"
}]
},
/**
组件的方法列表
*/
methods: {
switchTab(e) {
const data = e.currentTarget.dataset
console.log("执行跳转", e);
const url = data.path
wx.switchTab({
url
})
this.setData({
selected: data.index
})
}
}
})
这样就可以了,也就是在custom-tab-bar下的文件中添加自己想要的tabBar样式就行
自定义tabBar底部安全区域问题
参考:https://blog.csdn.net/zy1281539626/article/details/128358755
参考:https://blog.csdn.net/qq_52507367/article/details/125534919
问题描述:
在项目页面开发过程中,有些页面的按钮是需要固定在页面底部的(比如电商项目的确认订单页);如果直接设置bottom:0,那么在iphonex,xr,12等机型,就会出现下面左图的问题,按钮区域距离底部太近了,用户体验就会很差,按钮也不好点击。
解决思路:
为了适配所有的手机机型,我们需要获取到底部小黑条的高度,给固定在底部的view设置padding-bottom,增加高度;(有些手机默认是没有底部这个区域的,没有的话padding-bottom就设置为0)
![[59e38264-c703-4687-bdbf-b6694cd9c460.png]]
底部安全区域的问题解决方案有两种:
第一种:使用getSystemInfo
- 首先,通过getSystemInfo方法获取设备信息,在app.js里面,获取到底部小黑条区域的高度(小黑条区域高度=屏幕高度-安全区域的bottom值,安全区域指的是内容可见区域)
app.js
JavaScript
App({
globalData: {
bottomLift: 0
},
onLaunch() {
//获取当前设备信息
wx.getSystemInfo({
success: res => {
this.globalData.bottomLift = res.screenHeight - res.safeArea.bottom;
},
fail(err) {
console.log(err);
}
})
}
})
- 在shopcar购物车页面进行设置
shopcar.wxml页面
HTML
<view class="tab-bar" style="padding-bottom:{{bottomLift}}px">
<navigator url="/pages/index/index" open-type="switchTab">
<view>首页</view>
</navigator>
<navigator url="/pages/shopcar/shopcar" open-type="switchTab">
<view>购物车</view>
</navigator>
<navigator url="/pages/video/video" open-type="switchTab">
<view>视频</view>
</navigator>
</view>
shopcar.js页面
JavaScript
const app = getApp()
Page({
data: {
bottomLift: app.globalData.bottomLift
}
})
shopcar.wxss
CSS
.tab-bar{
width: 100%;
display: flex;
justify-content: space-around;
text-align: center;
position: absolute;
left: 0;
bottom: 0;
height: 100rpx;
background-color: rosybrown;
align-items: flex-end;
}
方法二:使用env()和 constant()
env()和constant(),是IOS11新增特性,Webkit的css函数,用于设定安全区域与边界的距离,有4个预定义变量:
-
safe-area-inset-left:安全区域距离左边边界的距离
-
safe-area-inset-right:安全区域距离右边边界的距离
-
safe-area-inset-top:安全区域距离顶部边界的距离
-
safe-area-inset-bottom :安全距离底部边界的距离
1)设置高度,在添加padding值
利用IOS新增的 env()和 constant()特性即可解决,开发者不需要自己动态计算高度,只需将如下CSS代码添加至样式中:
CSS
.tab-bar{
width: 100%;
height: 100rpx;
background-color: rosybrown;
display: flex;
justify-content: space-around;
align-items: flex-end;
text-align: center;
position: absolute;
left: 0;
bottom: 0;
padding-bottom: constant(safe-area-inset-bottom);
padding-bottom: env(safe-area-inset-bottom);
}
2)将高度和padding值使用calc直接相加
内容区域设置 padding-bottom,如果底部固定定位元素的高度是 50px ,那么只需要设置css:
CSS
.tab-bar{
width: 100%;
background-color: rosybrown;
display: flex;
justify-content: space-around;
align-items: flex-end;
text-align: center;
position: absolute;
left: 0;
bottom: 0;
padding-bottom: calc(constant(safe-area-inset-bottom) + 50px);
padding-bottom: calc(env(safe-area-inset-bottom) + 50px);
}
自定义导航栏
了解更多参考网址:https://blog.csdn.net/little_shallot/article/details/110205652
json文件里面加入"navigationStyle":"custom"即可去掉原生导航栏
既可在app.json中去掉,也可以在页面中json去掉
获取导航栏高度
用固定高度加定位,发现在不同设备下尺寸不对,就比如iPhone X那个刘海屏
![[c9ff4707-135f-421a-810b-fa7428241e2f.png]]
![[1280X1280 (55).PNG]]
Object wx.getMenuButtonBoundingClientRect()
获取菜单按钮(右上角胶囊按钮)的布局位置信息。坐标信息以屏幕左上角为原点。获取值的单位为px,所以设置的时候也需要使用px进行设置
bottom: 56 屏幕顶部到按钮底部之间的距离
height: 32 按钮高度
left: 226 屏幕左边到按钮左侧之间的距离
right: 313 屏幕左边到按钮右侧之间的距离
top: 24 屏幕顶部到按钮顶部之间的距离
width: 87 胶囊按钮宽度
但是切换到不同尺寸的屏幕,获取到的菜单按钮的数据是不一样的,特别是top值,所以,当我们想要添加一个跟胶囊按钮同位置的input框的时候,可以通过getMenuButtonBoundingClientRect获取距离顶部的高度,再将值设置给input框
![[02a07ebb-b782-47e2-8fc1-e2adc672cb6a.png]]
json配置
JavaScript
{
"usingComponents": {},
"navigationBarTitleText": "购物车",
"navigationStyle": "custom",
"navigationBarTextStyle": "white"
}
wxml
HTML
<view class="search" style="height:{{num2}}px; top: {{num1}}px;">
<input type="text" class="inp" placeholder="郑州耀莱成龙影城" placeholder-class="pinput"/>
</view>
<view class="banner">
<image class="img" src="/file/banner.jpeg"></image>
</view>
wxss
CSS
/* pages/shopcar/shopcar.wxss */
.search{
height: 90rpx;
position: absolute;
}
.inp{
width: 400rpx;
height: 32px;
border-radius: 40rpx;
margin-left: 20rpx;
padding-left: 20rpx;
background-color: rgba(255, 255, 255, 0.6);
}
/* 设置placeholder的样式 */
.pinput{
color: #000;
}
.banner{
height: 400rpx;
}
.img{
height: 100%;
width: 100%;
}
js
JavaScript
Page({
/**
页面的初始数据
*/
data: {
// 距离顶部的高度
num1:0,
// 胶囊的高度
num2:0
},
onLoad(options) {
let that = this;
//获取胶囊信息
let obj = wx.getMenuButtonBoundingClientRect();
this.setData({
num1:obj.top,
num2:obj.height
})
console.log(obj);
}
})
效果
![[59238e74-be97-426e-a5cc-749d1cac7680.png]]
线上字体图标的使用
注意:小程序中不能引入本地的字体图标,需要引入在线的字体图标,或者将图片直接下载为base64位的格式
方法一:使用在线路径地址
-
https://www.iconfont.cn/ 从该网站下载图标库到本地 (选Font class类型)
-
在该网站再选类型为Unicode, 并复制在线链接代码
CSS
/* CDN 服务仅供平台体验和调试使用,平台不承诺服务的稳定性,企业客户需下载字体包自行发布使用并做好备份。 */
@font-face {
font-family: 'iconfont'; /* Project id 3269565 */
src: url('//at.alicdn.com/t/c/font_3269565_hglnrx368an.woff2?t=1661919019667') format('woff2'),
url('//at.alicdn.com/t/c/font_3269565_hglnrx368an.woff?t=1661919019667') format('woff'),
url('//at.alicdn.com/t/c/font_3269565_hglnrx368an.ttf?t=1661919019667') format('truetype');
}
- 把解压后的iconfont.css拷入小程序项目,并修改为 .wxss格式
CSS
@font-face {
font-family: "iconfont"; /* Project id 3269565 */
src: url('iconfont.woff2?t=1661919754447') format('woff2'),
url('iconfont.woff?t=1661919754447') format('woff'),
url('iconfont.ttf?t=1661919754447') format('truetype');
}
.iconfont {
font-family: "iconfont" !important;
font-size: 16px;
font-style: normal;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.icon-arrow-up-circle:before {
content: "\e665";
}
.icon-duoyun-xian:before {
content: "\e834";
}
- 用复制的@font-face代码替换iconfont.wxss中的@font-face,并完善域名,添加https:
CSS
@font-face {
font-family: 'iconfont'; /* Project id 3269565 */
src: url('https://at.alicdn.com/t/c/font_3269565_hglnrx368an.woff2?t=1661919019667') format('woff2'),
url('https://at.alicdn.com/t/c/font_3269565_hglnrx368an.woff?t=1661919019667') format('woff'),
url('https://at.alicdn.com/t/c/font_3269565_hglnrx368an.ttf?t=1661919019667') format('truetype');
}
-
在小程序后台配置域名: https://at.alicdn.com/
-
在app.wxss中引入
CSS
@import "./assets/css/iconfont.wxss";
- 在模板中使用
HTML
<view class="icon-duoyun-xian iconfont">aa</view>
方法二:将字体格式转为base64的格式后使用
- 下载需要的字体图:
打开阿里巴巴矢量图标库,选择自己需要的图标添加到购物车,然后点击购物车下载代码:
![[b4c053c9-0af2-44bb-a834-1651e3814340.png]]
- 转换iconfont.ttf文件为base64格式
然后将下载的包解压,你会看到一个格式为ttf的文件,注意,我们转换的就是这个文件,此处我们将解压的文件夹叫"原始文件夹",打开Transfonter网站,按如下步骤操作:点击add fonts按钮添加我们之前提到的ttf文件 ------> 打开以及勾选下图中框红框的选项 ------> 点击Convert转换按钮(稍等片刻)------> 下载转换好的文件(会有个Download选择,点就行了),到这里,我们就可以拿到转换完的文件了。
![[c5d9a408-6343-48d9-9f7e-0701e1c77776.png]]
- 在微信小程序中使用字体图标
打开微信小程序,默认我们让index页面显示刚刚下载的图标,所以要先打开index.wxss文件,然后将刚才转换后下载的文件夹解压,找到stylesheet.css文件,打开文件,复制所有样式到index.wxss文件中:
CSS
/
**index.wxss**
/
@font-face {
font-family: 'iconfont';
src: url(data:font/truetype;charset=utf-8;base64,AAEAAAANAIAAAwBQRkZUTYcD80UAAB8AAAAAHEdERUYAKQAMAAAe4AAAAB5PUy8yPG9H+QAAAVgAAABWY21hcOYh6bsAAAHEAAABSmdhc3D//wADAAAe2AAAAAhnbHlmoQ/4zQAAAyAAABjkaGVhZBU0EFwAAADcAAAANmhoZWEIfwNaAAABFAAAACRobXR4DKwAbQAAAbAAAAAUbG9jYQ3UCCIAAAMQAAAADm1heHABvAR7AAABOAAAACBuYW1lKeYRVQAAHAQAAAKIcG9zdP06GuMAAB6MAAAASQABAAAAAQAAWPAGv18PPPUACwQAAAAAANiv5h4AAAAA2K/mHgAV/70EoANmAAAACAACAAAAAAAAAAEAAAOA/4AAXAQAAAD/1QSgAAEAAAAAAAAAAAAAAAAAAAAEAAEAAAAGBG8ArAAAAAAAAgAAAAoACgAAAP8AAAAAAAAAAQQAAZAABQAAAokCzAAAAI8CiQLMAAAB6wAyAQgAAAIABQMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUGZFZABA5gHmBwOA/4AAXAOAAIAAAAABAAAAAAAABAAAAAAAAAAEAAAABAAAFQCsAFgAAAADAAAAAwAAABwAAQAAAAAARAADAAEAAAAcAAQAKAAAAAYABAABAALmAeYH//8AAOYB5gb//xoCGf4AAQAAAAAAAAAAAQYAAAEAAAAAAAAAAQIAAAACAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAWIIIgxyAAAAFAAV//wEHQNmAAYAEgAzAEAASwBUAF0AZgBvAHsAhACNAJYAoACsALUAvgDHANAA2QAANxQEJSwBJxMWBgcGJicmNjc2FhMnBxQWFw4BBwYmNwYWFx4BNzY/ATY3Nj8BNjcGBzcWNgceAjI+ATQuASIOARceARc+ATcjBw4BNxY2NzYGByY2MyY2NzYGFxY2FwYWFxYmJzYWJx4BNgYHLgE/ASYGBx4BNy4BNz4BARY2NzYCBwY2Ny4BNzYGFxY2FxQWFxYkJyYWJzoBNzYGBy4BPwEmBhceATciJjc+AQceAT4BLgEOAScWDgEuAT4BFhMWDgEuAT4BFgceAT4BLgEOAQEeAT4BLgEOAX4BTQFHAQv9+DxqOjxobN5AOjxpbN5RTR4FCBc4FL2mAg8OHTKoWxQUBxMTFRIEHBQOEhAbFpsBQHOAckBAcoBzQDkiXzlihwkJMwLErAVfHhg+QzoaDAMDKx+EEh4LCgEtPS2sCwgYOQEcGA4cDwMBXQhoBQgfAgMNFBgu/pgHfBsWLFxUHxEGFjAimig4BxFYXkX+/B8DKFYCKhEQDCcYCwFvDIwJES8CAx4UGzxOAhUbEAQUGxBxAyA1JwYfNSj0BxAnJA4QJyMwAwsLBAULCwT+5QMUGAwGExgM8BLiEy+cCQGAYdlGQSZeYtlGQSb+81YXATAgD0g/Cd8RNGsvSzcZBggECAwOEAMZHgMGLQJRxDpgOjpgc2A6OmDCIycBAm1UEg2AkgEvPi2uDAcYBGs1KIFBMyMNBWAfGUFDOxsRAQUEIwYQGwFVAxpBHA4BAS0iIBIBDgFbXkf++iEFKQMFl1ZB11k/Mw8Hfh0XMVxVIAkHBDQPEiUCjgM+XSUMAjw1MyWtDxIDFh4TBBZ/Eh0JECIeCRD+wQwgFgEZIBYBVQQBBwoIAQcKATYJBggREQYIEAAAfQCs/70DfwMOAAsAFQAZAB0AIQAlACkALQA2ADsARgBMAFIAVwBdAGQAagBvAHkAfAB/AIkAkwCpAMAA1gDtAQMBBgEKAQ4BEgEWARsBHwEjAScBKwEvATMBOAE8AUABRAFIAUwBUAFUAVgBXAFgAWQBaAFsAXABdAF4AXwBgAGEAYgBjAGQAZQBmAGcAaABpAGoAa0BsQG1AbkBvQHBAcUByQHNAdEB1QHZAd0B4gHmAeoB7gHyAfYB+gH+AgECFwIuAkQCWwJxAogCngK1AswC4wL5AxADJgM9A0QDSQNfA3cDjQOkA7sD0gPpBAAECgQUBBwELQQ9BEcETwRaBGUEbgAAJRYENzYmBwYmBw4BAxMxHgEyNjcxEwUTJwMBNxMrARMzAzMTFwMhAzMTIwM3EwEiLwEmNh8BFiciJjYWATETDgEnHgEzPgEHNj8BBg8BFhcnBgcDFhcnIxMWMycGByETBg8BNjcHNwYPATYBFhcnIyceASA2Ny4BIAYFNQcFNRcnHgEgNjcuASAGFx4BMjY3LgEiBjcyFz4BMhYUBxYUBiMiJicGIy4BNDY3Mhc+ATMyFyYiBgcmIyIGFRQXJic0NgUyFz4BMhYUBxYUBiMiJicGIyImNDYzMhc+ATMWFyYiBgcmIw4BFRQXJic0NjcyFz4BMhYUBxYUBiMiJicGIy4BNDYHFyM1FyMnNRcjJzUXIyc1FyMnNRcHIyc1FwcnNRcHJzUXByc1FwcnNRcHJzUXByc1MRcHJzU3FwcnNxcHJzcXByc3FwcnNxcHJzcXByc3FwcnNxcHJzcXByc3FwcnNxcHJzcXByc3FwcnNxcHJzcXByc3FwcnNxcHJzcXByc3FwcnNxcHJzcXByc3FwcnNxcHJzcXByc3FwcnNxcHJzcXByc3FwcnMTMXBycXByczFwcnMxcHJzMXByczFwcnMxcHJzMXByczFwcnMxcHJzMXByczFwcnMxcHJzMXFQcnMxcVJzMXFSczFxUnMxcVJzMXFSczFxUnMxcVJxcnMwc2NyY+AR4BBx4BBgcGJicGBwYuATY3NjcmNjc2FyYOARcGBw4BFxYXJicmNicyFz4BMhYUBxYUBiMiJicGIy4BNDYzMhc+ATcWFyYiBgcmIyIGFRQXJic+ARcyFz4BMhYUBxYUBgcuAScGIyImNDYzMhc+ATcWFyYiBgcmIw4BFRQXJic0Njc2MyY+AR4BBx4BBgcGJicGBwYuATY3NjMmNjc2FyYOARUiBw4BFxYXJicmNjcyFz4BNx4BFAcWFAYjIiYnBiMiJjQ2NzIXPgE3FhcmIgYHJiMiBgcUFyYnPgEXMhc+ATIWFAcWFAYjIiYnBiMiJjQ2MzIXPgEzFhcmIgYHJiMOARUUFyYnPgEHMhc+ATIWFAcWFAYjIiYnBiMiJjQ2NzIXPgEzMhcmIgYHJiMiBhUUFyYnNDYnFjI2Jg4BFxY2JgYDMhc+Ah4BBx4BBgciJicGIwYuATY3Mhc+ATcyFyYOAQcmBw4BFxQXJic0NjcFNjcmPgEeAQceAQYHBiYnBgcGLgE2NzY3JjY3NhcmDgEXBgcOARcWFyYn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) format('truetype');
font-weight: normal;
font-style: normal;
}
- 使用字体图标
HTML
<!--index.wxml-->
<text class="iconfont icon-shengnvguo">圣女果</text>
<text class="iconfont icon-baomihua">爆米花</text>
<text class="iconfont icon-dangao">蛋糕</text>
添加视频
添加插件
个人小程序账号中添加视频,可以使用express搭建后端,使用video引入后端视频链接;
参考链接:https://blog.csdn.net/qzw752890913/article/details/118197408
video标签可以添加视频控件,弹幕
但是不能使用腾讯的视频,想要添加腾讯视频,必须是企业账号,添加第三方腾讯视频插件
![[f6dddecb-9cde-47c8-ba07-a65140bf7af5.png]]
添加成功之后,点击详情,查看该插件的具体信息。
![[1e7f84e6-8781-469c-a3de-7a6b7ffbb2b1.png]]
拿到该插件的appid以及版本号。
使用步骤
微信小程序:小程序的app.json里声明使用插件
JavaScript
"plugins": {
"tencentvideo": {
"version": "2.0.5",
"provider": "wxa75efa648b60994b"
}
},
在使用插件的页面的js文件里
JavaScript
const txvContext = requirePlugin("tencentvideo");
使用插件的自定义组件,在json中定义需要引入的自定义组件。使用plugin://协议
JavaScript
"usingComponents": {
"txv-video": "plugin://tencentvideo/video"
}
页面中使用
HTML
<txv-video vid="xxxxxxxx" playerid="txv1"></txv-video>
暂停方法:
JavaScript
this.txvContext = txvContext.getTxvContext('txv1');
this.txvContext.pause()
uniapp:manifest.json添加:
JavaScript
"mp-weixin" : {
"appid" : "",
"setting" : {
"urlCheck" : false
},
"usingComponents" : true,
"plugins": {
"tencentvideo": {
"version": "2.0.5",
"provider": "wxa75efa648b60994b"
}
}
},
在page.json中的对应页面的 style中添加
JavaScript
"usingComponents": {
// #ifdef MP-WEIXIN
"txv-video": "plugin://tencentvideo/video"
// #endif
}
页面实现:
HTML
<txv-video vid="xxxxxx" playerid="txv1"></txv-video>
如何获取vid
HTML
https://v.qq.com/x/page/n0041aa087e.html
n0041aa087e即为vid。