文章目录
- vsc 安装插件(小程序开发助手-微信小程序开发助手)
- 日常注意:
- 微信小程序WXS模块的使用
- 框架
- 1小程序结构和传统的web结构
- 2 基本的项目目录
- 3全局配置app.js
- 4.运算 => 表达式
- 5.列表循环
- 6.对象循环
- 7.block
- 8.条件渲染
- 9.input数据绑定
- 10.1样式wxss
- 10.2 样式导入
- 10.3 使用less
- 11.view 和text
- 12.image
- 13.swiper
- 14.navigator
- 15.rich-text 富文本标签
- 16.button
- 17.icon
- 18.单选框radio
- 19.checkbox
- 20.自定义组件
- 21.自定义tab样式
- 22.父向子传递数据
- 23.子向父传递数据
- 24.自定义组件-solt
- 25.引用的生命周期
- 26.本地缓存
- 27项目分包
- 27.项目笔记
- 1.需要把域名添加到小程序的后台;
- 2.:nth-last-child(-n+4) //后面4个
- 3.less 会计算
- 4.overflow: hidden; zoom: 1; 也可以清除浮动(父元素没有设高度)zoom:1; 是为了兼容
- 5.P15 的cate
- 6.calc的使用
- 7.获取path中?后面的部分会成为query,
- 8.下拉刷新成功后要关闭下拉刷新页面
- 9.ios端不支持图片webp格式;
- 11.点击轮播图 放大预览
- 12.小程序授权事件,第一次点击取消后,第二次点不了;
- 13.只有发现属性名很怪异的时候 都要使用 [ ]
- 14.获取上个页面传递过来的参数
- 15.vsc 输入 lorem会出现很像正文长度的文字,
- 16.一行或多行超出显示省略号
- 17.去掉两边空格
- 18.防抖(防止抖动) 定时器 节流
vsc 安装插件(小程序开发助手-微信小程序开发助手)
然后在vsc 里面就可以以wx-开头就会有提示了
alt + 上下箭头 移动代码
ctrl + alt + ↓ : 向下复制当前行
日常注意:
1.字符串和花括号之间一定不要存在空格,否则会导致识别失败
//以下是错误示范
<checkbox checked=" {{ischecked}}" ></checkbox>
微信小程序WXS模块的使用
- https://blog.csdn.net/k464746/article/details/107933625
框架
MINA 原生框架
1小程序结构和传统的web结构
结构 | 传统web | 微信小程序 |
---|---|---|
结构 | HTML | WXML |
样式 | CSS | WCSS |
逻辑 | Javascript | Javascript |
配置 | JSON |
通过以上的对比,微信小程序多出了一层配置json
2 基本的项目目录
-
pages 页面文件
index 首页
logs 日志页面
-
utils 第三方的js库
-
app.js 项目的全局 入口文件
-
app.json 全局配置文件
-
app.wxss 全局样式配置
-
project.config.json 项目的配置文件 如appid
-
sitemap.json 微信索引配置文件
3全局配置app.js
注: 配置app.js 的时候最好在微信开发工具里面配,会有提示
app.js 全局配置 包括小程序的所有 页面路径、界面表现、网络超时时间、底部tab等
- pages字段 用于描述当前的小程序的所有的 页面路径,让微信客户端知道小程序的页面定义在哪个目录
- window字段 定义小程序的所有的 顶部背景颜色、文字颜色定义等
//app.json
{
"pages":{
},
"window":{
}
}
4.运算 => 表达式
-
可以在花括号中加入 表达式 – “语句”
-
表达式
指的是一些简单的 运算、数字运算、字符串拼接、逻辑运算。。。
- 数字的加减
- 字符串的拼接
- 三元表达式
-
语句
- 复制的代码段
- if else
- switch
- do while …
- for …
- 复制的代码段
-
{{1+2}} //3
5.列表循环
- wx:for ="{{数组或者对象}}" wx:for-item=“循环项的名称” wx:for-index=“循环项的索引”
- wx:key=“唯一的值” 用来提高列表渲染的性能
- wx:key 绑定一个普通的字符串的时候 那么这个字符串的名称 肯定是 循环数组 中的 对象的 唯一的属性
- wx:key ="*this" 就表示你的数组是一个 ‘普通的数组’ *this 表示是 循环项
- [1,2,3,4,5]
- [“1”,“2”,“3”,“4”]
- 当出现 数组的嵌套循环的时候 尤其要注意 以下绑定的名称 不要重名
- wx:for-item=“item” wx:for-index=“index”
- 默认情况下 我们 不写
- wx:for-item=“item” wx:for-index=“index”
- 小程序也会把 循环项的名称 和 索引的名称 定义为 “item” 和 “index”
- 只有一层循环的话 (wx:for-item=“item” wx:for-index=“index”)可以省略
6.对象循环
- wx:for="{{对象}}" wx:for-item=“对象的值” wx:for-index=“对象的属性”
- 循环对象的时候 最好把 item和index 的名称换都修改一下
- wx:for-item=“value” wx:for-index=“key”
7.block
- 占位符的标签
- 写代码的时候 可以看到这些标签的存在
- 页面渲染 小程序会把它移除
8.条件渲染
-
wx:if="{{true/false}}"
-
if, else , if else
wx:if
wx:elif
wx: else
-
-
hidden
- 在标签上直接加入属性 “hidden“ vue是v-show
- hidden="{{true}}"
-
什么场景下使用哪个
-
当标签不频繁切换显示 优先使用 wx:if
直接把标签从 页面结构移除
-
当标签频繁切换显示, 优先使用wx:hidden
通过控制样式 display
-
9.input数据绑定
-
需要给input的标签绑定 input事件
绑定的关键字 bindinput
-
如何获取输入框的值
通过事件源对象来获取
e.detail.value
-
把输入框的值 赋值到data当中
不能直接
1.this.data.num= e.detail.value
2.this.num = e.detail.value
正确赋值:
this.setData({
num: e.detail.value
})
-
需要加入一个点击事件
- bindtap
- 无法在小程序当中的 事件中 直接传参
- 通过自定义属性的方式来传递参数
<button bindtap="handletap" data-num="{{num}}"></button>
bindtap(e){
//获取自定义属性 num
var num = e.currentTarget.dataset.num
//解构赋值
var {num} = e.currentTarget.dataset
}
10.1样式wxss
规定屏幕宽为750rpx
iphone6屏幕宽度为375px
375px ==750rpx
假如存在一个设计稿440px 或者 page
440px = 750rpx
推算演变
page px = 750rpx
利用一个属性calc属性 css 和wxss都支持的属性
注意750和rpx不要留空格 符号两边要留
width:calc(750rpx * 100 / 375);
10.2 样式导入
使用@import语句可以导入外联样式表,只支持相对路径。
@import “…/…/style/common.wxss”
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tugUbvA1-1643360178266)(C:\Users\Hg-huazai\AppData\Roaming\Typora\typora-user-images\image-20201214151713195.png)]
相对路径: 相对当前路径来说,从当前路径出发,
10.3 使用less
1.编辑器 vsc 插件easy less
-
在vs code 的设置中加入如下,配置 (p22 集)
"less.compile": { "outExt": ".wxss" }
重命名wxss文件为less 保存会自动生成wxss 文件
/*1.定义less变量*/ @color: pink; text { color: @color; }
11.view 和text
view:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-OvpZmKFF-1643360178269)(C:\Users\Hg-huazai\AppData\Roaming\Typora\typora-user-images\image-20201214154113858.png)]
text:
1.只能嵌套text
2.长按可以复制(只有该标签有这个功能)
3.可以对大于号、小于号、回车、空格进行编码
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BYr6cnJe-1643360178270)(C:\Users\Hg-huazai\AppData\Roaming\Typora\typora-user-images\image-20201214155055080.png)]
12.image
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1t2coU3j-1643360178271)(C:\Users\Hg-huazai\AppData\Roaming\Typora\typora-user-images\image-20201214165757766.png)]
1.图片存在默认的宽高 320 * 240
2.mode
3.小程序当中的图片 直接就支持 懒加载 lazy-load
1.lazy-load 会自己判断 当 图片 出现在 视口 上下 三屏的高度 之内的时候 自己开始加载图片
<image mode="bottom" lazy-load src=""></image>
13.swiper
-
轮播图外层容器 swiper
-
每个轮播图项 swiper-item
-
swiper标签 存在默认样式
-
width 100%
-
height 150px image 也存在默认的宽高 320* 240
-
swiper 高度 无法实现由内容撑开
-
先找出了 原图的宽高 等比例 给swiper 定 宽高
- 假如原图的宽高 1125 * 325px
- swiper宽度 / swiper高度 = 原图的宽度 / 原图的高度
- swiper高度 = swiper宽度*原图的高度 / 原图的宽度
- height: 100vw * 325 /1125
-
image 的 mode=“widthFix”
-
<swiper> <swiper-item> <image mode="widthFix" src="" /> </swiper-item> <swiper-item> <image mode="widthFix" src="" /> </swiper-item> <swiper-item> <image mode="widthFix" src="" /> </swiper-item> </swiper> swiper { width: 100%; height: calc(100vw * 325 / 1125); } image { width: 100%; }
-
14.navigator
导航组件 navigator
- 块级元素 默认会换行 可以直接加宽度和高度
- url要跳转的页面路径 绝对路径 相对路径
- target 要跳转到当前的小程序 还是其他的小程序和页面
- self 默认值 自己 小程序的页面
- miniProgram 其他的小程序页面
- open-type 跳转的方式
- navigate 默认值 保留等前页面,跳转到应用内的某个页面,但是不能跳转 tabbar 页面。
- redirect 关闭当前页面,跳转到应用内的某个页面,但是不能跳转到 tabbar页面。
- switchTab 跳转到 tabbar 页面, 并关闭其他所有非 tabbar 页面。
- reLaunch 关闭所有页面, 打开到应用内的某个页面
15.rich-text 富文本标签
html
1.nodes 属性来实现
1.接收标签字符串, 常用
2.接收对象的数组
<rich-text nodes="{{html}}"></rich-text>
js
page ({
data: {
//1.标签字符串
html: '<div class="my_div" style="color:red;"><p>hello</p> </div>'
//2.对象数组
html: [
{
//1.div标签 name属性来指定
name: "div",
//2.标签上有哪些属性
attrs: {
class: "my_div",
style: "color: red;"
},
//3.子节点 children 要接收的数据类型和 nodes 第二种渲染方式的数据类型一致
children: [
{
name: 'p',
attrs: {},
//放文本
children: [
{
type: "text",
text: "hello"
}
]
}
]
}
]
}
})
16.button
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cQAZc76F-1643360178272)(C:\Users\Hg-huazai\AppData\Roaming\Typora\typora-user-images\image-20201215153642403.png)]
文档:https://developers.weixin.qq.com/miniprogram/dev/component/button.html
button 的开发功能
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qrOkZATv-1643360178273)(C:\Users\Hg-huazai\AppData\Roaming\Typora\typora-user-images\image-20201215154738195.png)]
客服功能: 需要去 微信公众平台(https://mp.weixin.qq.com/wxamp/home/guide?lang=zh_CN&token=771833294) -> 客服 -> 添加微信号
17.icon
(https://developers.weixin.qq.com/miniprogram/dev/component/icon.html)
18.单选框radio
- radio 单标签 必须要和 父元素 radio-group 来使用
- value 选中的单选框的值
- 需要给 radio-group 绑定 bindchange 事件
<radio-group bindchange="handleChange">
<radio value="male">男</radio>
<radio value="female">女</radio>
</radio-group>
<view> {{gender}}</view>
//js
page({
data: {
gender: ''
},
handleChange(e){
//1.获取单选框中的值
let gender = e.detail.value;
//2.把值赋给 data 中的数据
this.setData({
//es6
gender
})
}
})
19.checkbox
<checkbox-groud bindchange="handleItemChange">
<checkbox value="{{item.value}}" wx:for="{{list}}" wx:key="{{item.id}}">{{item.name}}</checkbox>
</checkbox-groud>
<viwe>选中的水果{{checkboxlist}}</view>
page ({
data: {
list: [
{id: 0,naem:"苹果", value: "apple"},
{id: 1, name: "梨", value: "grape"},
{id: 2, name: "香蕉", value: "bananer"},
],
checkedlist: [],
},
//复选框选中事件
handleItemChange(e){
//获取被选中的复选框的值
const checkedlist = e.datail.value;
//赋值
this.setData({
checkedlist
})
}
})
20.自定义组件
组件的回调函数放在methods:{}中
-
创建组件
-
跟目录下新增一个文件夹 “components”,再新建对应得文件夹,然后右击,点击新建Component;
-
此时的js文件并不是page了,而是:component
-
//组件的js文件 Component({ //组件的属性列表 (接收父向子传递的数据的) properties: { }, //数据的初始化 data: { }, //组件的方法列表 methods: { } })
-
//json文件 { "component": true, //当前文件是组件 "usingComponents": {} //引用其他自定义组件 }
-
-
声明组件
-
那个文件使用组件就在哪个文件的json声明
-
{ "usingComponents":{ //键值对 "组件吗": "组件路径" "Tabs": "../../components/Tabs/Tabs" //相对路径,不用加后缀名 } }
-
-
使用组件
-
<tabs></tabs>
-
21.自定义tab样式
//html
<view
wx:for="{{tabs}}"
wx:key="id"
class="title_item {{item.isactive? 'active': ''}}"
bindtap="hanldeItemTap"
data-index="index"
>
{{item.name}}
</view>
//js
Conponenst({
data:{
tabs: [
{id:0,name:'首页',isActive:true},
{id:1,name:'原创',isActive:fales},
{id:2,name:'分类',isActive:fales},
{id:3,name:'关于',isActive:fales},
]
},
methods: {
hanldeItemTap(e){
//获取索引
const {index} = e.currentTarget.dataset;
//获取data中的数组
// let {tabs} = this.data; 最好不要直接修改this.data的数据
//最严谨的做法,深拷贝一份 数组 再对这个数组的备份进行处理
let tabs = JSON.parse(JSON.stringify(this.data.tabs))
//循环数组
//[].forEach 遍历数组 遍历数组的时候修改了 v,也会导致原数组被改变
tabs.forEach((v,i)=>i===index?v.isActive=true:v.isActive=false;)
//赋值
this.setData({
tabs
})
}
}
})
//小程序数组深拷贝
function copyArr(oldArr){
let newArr = [];
newArr = JSON.parse(JSON.stringify(oldArr));
return newArr;
}
22.父向子传递数据
-
父组件(页面) 向子组件 传递数据 通过 标签属性的方式来传递
-
<Tabs aaa="123"> </Tabs>
-
-
子组件上进行接收
-
Component({ //里面存放的是 要从父组件中接收的数据 (把prpperties当成data使用就好) properties: { //要接收数据的名称 aaa: { //type: 要接收的数据的类型 type: string, //value 默认值(如果父组件没有传值的话,就使用该值) value: "" } } })
-
23.子向父传递数据
子向父传递数据 是通过事件的方式传递
在子组件的标签上加入一个 自定义事件
<Tabs aaa="123" binditemChange="handleItemChange"> </Tabs>
-
子组件的点击事件触发的时候
-
<view bindtap="tabtap"></view>
-
触发父组件的自定义事件 同时传递数据给 父组件
-
//this.triggerEvent("父组件自定义事件的名称",要传递的参数) this.triggerEvent("itemChange",index)
-
components ({ methods: { tabtap(e){ const {index} = e.currentTarget.detaset //假如index ==2 this.triggerEvent("itemChange",{index}) } } })
-
page ({ handleItemChang(e){ console.log(e.detail.index) //2 } })
-
24.自定义组件-solt
sole 标签 其实就是一个占位符 插槽
等到 父组件调用 子组件的时候 再传递 标签过来 最终 这些被传递的标签就会替换 slot 插槽 的位置
//子组件
<view>
<sole></sole>
</view>
父组件 直接 插标签 就可以替换sole了
25.引用的生命周期
全局的入口文件app.js
APP({
})
页面
Page({
})
组件
Component({
})
全局生命周期
APP({
//1.应用第一次启动的就会催发的事件
onLaunch(){
//在应用第一次启动的时候 获取用户个人的信息
console.log("onLaunch")
},
//2应用 被用户看到
onShow(){
console.log("onshow")
},
//3.应用 被隐藏
onHide(){
//暂停或者清除定时器
console.log("hide")
},
//4.应用代码 发生了报错的时候 就会触发
onError(err){
//在应用发生的代码报错的时候,收集用户的错误信息,通过异步请求 将错误的信息发送后台去
console.log(err)
},
//5.页面找不到就会催发
//应用第一次启动的时候, 如果找不到第一个入口页面 就会触发
onPageNotFound(){
console("onPageNotFound");
}
})
组件生命周期
26.本地缓存
查看控制台的storage 可查看缓存
-
先判断一下本地存储中有没有旧的数据
-
{当前时间戳,数据长什么样} {time: Date.now(), data: [...]}
-
-
没有旧数据 直接发送新请求;
-
有旧的数据 同时 旧的数据也没有过期 就使用 本地存储中的旧数据即可
-
1.存储本地数据 getCates(){ request({ }).then(res=>{ this.Cates = res.data.message; //把接口数据存入到本地存储中 wx.setStorageSync("cates, {time:Date.now(), data:this.Cates}") }) } 2.获取本地存储中的数据 const Cates = wx.getStorageSync("cates"); if(!Cates){ //不存在 发送请求获取数据 this.getCates(); }
-
web中的本地存储 和 小程序中的本地存储的区别
- 写代码的方式不一样
- web: localStorage.setItem(‘key’,‘value’) ; localStorage.getItem(‘key’)
- 小程序中: wx.setStorageSync(‘key’, ‘value’); wx.getStorageSync(‘key’);
- 存的时候 有没有做类型转换
- web: 不管存入的是什么类型的数据, 最终都会先调用以下 toString(), 把数据变成了字符串 在存入进去
- 小程序: 不存在 类型转换的这个操作 存什么类型的数据进去, 获取的就是什么的数据类型
- 写代码的方式不一样
27项目分包
-
在app.json 的subpackaage(pages同级)节点中声明分包的结构
-
打包原则:
- 小程序回按subpackages的配置进行分包,subpackages之外的目录将被打包到主包中
- 主包也可以有自己的page(既最外层的pages字段)
- tabBar页面必须在主包内
- 分包之间不能互相嵌套
-
引用原则
- 主包无法引用分包内的私有资源
- 分包之间不能相互引用私有资源
- 分包可以引用主包内的公共资源
-
独立分包
- 独立分包本质也是分包,只不过它是比较特殊,可以独立于主包和其他分包而单独运行
-
独立分包的应用场景
开发者可以按需,将某些具有一定功能独立性的页面配置到独立分包中,原因如下
- 当小程序从普通的分包页面启动时,需要首先下载主包
- 而独立分包不依赖主包即可运行,可以很大程度上提升分包页面的启动速度
-
独立分包配置
通过independent声明独立分包
-
独立分包引用原则
独立分包和普通分包以及主包之间,是相互隔绝的,不能相互引用彼此的资源!例如:
- 主包无法引用独立分包内的私有资源
- 独立分包之间,不能相互引用私有资源
- 独立分包和普通分包之间,不能相互引用私有资源
- 特别注意:独立分包中不能引用主包内的公共资源
-
分包预下载-配置分包的预下载
预下载分包的行为,会在进入指定的页面时触发,在APP.json 中,使用PreloadRule节点定义分包的预下载
-
分包预下载的限制
同一个分包中的页面享有共同的预下载大小限额2M例如
27.项目笔记
1.需要把域名添加到小程序的后台;
1.1开发文档->介绍(点击跳转微信公众平台宽网首页(https://mp.weixin.qq.com/))->开发->开发设置->服务器域名;
2.:nth-last-child(-n+4) //后面4个
3.less 会计算
- height: 33.33vw * 386 / 232 /2;
4.overflow: hidden; zoom: 1; 也可以清除浮动(父元素没有设高度)zoom:1; 是为了兼容
5.P15 的cate
6.calc的使用
- less中使用calc的时候要注意
- height: ~‘calc(100vh - 90rpx)’;
7.获取path中?后面的部分会成为query,
- App.onLaunch、App.onShow 和 Page.onLoad的回调函数可以获取query数据;
8.下拉刷新成功后要关闭下拉刷新页面
- wx.PullDownRefresh();
- wx.shopPullDownRefresh(); (vsc: wx-shop会提示)
9.ios端不支持图片webp格式;
11.点击轮播图 放大预览
- 文档->api->图片->wx.previewImage
12.小程序授权事件,第一次点击取消后,第二次点不了;
- 获取 用户 对小程序 所授权 (地址,相机…) 权限 状态 scope (wx.getSetting({}); )
- 假设 用户 点击获取(收货地址)的提示框 确定 authSetting scope.address scope 值 true 直接调用 获取收货地址
- 假设 用户 从来没有调用过 收货地址的api scope undefined 直接调用 获取收货地址
- 假设 用户 点击获取收货地址的提示框 取消scope 值 false
- 诱导用户 自己 打开 授权设置页面(wx.openSetting({})) 当用户从新给予 与 获取地址的权限 的时候
- 获取地址
13.只有发现属性名很怪异的时候 都要使用 [ ]
-
result.authSetting["scope.address"]
14.获取上个页面传递过来的参数
-
使用小程序的页面盏
-
获取当前的小程序的页面盏-数组 长度最大是10个页面
-
数组中 索引中最大的页面就是当前的页面
-
let pages = getCuttentPages(); //pages => 所有页面盏的数组 let currentPage = pages[pages.length-1]; //数组最大的索引;
-
15.vsc 输入 lorem会出现很像正文长度的文字,
16.一行或多行超出显示省略号
-
一行超出显示省略号;
-
overflow: hidden; white-space: nowrap; text-overflow: ellipsis;
-
-
多行显示省略号;
-
overflow: hidden; display: -webkit-box; //必须结合的属性 ,将对象作为弹性伸缩盒子模型显示 。 -webkit-box-orient: vertical;//必须结合的属性 ,设置或检索伸缩盒对象的子元素的排列方式 -webkit-line-clamp: 3; //用来限制在一个块元素显示的文本的行数
-
17.去掉两边空格
-
value.trim()
18.防抖(防止抖动) 定时器 节流
-
防抖 一般 输入框中 防止重复输入 重复发送请求
-
节流 一般 是用在页面上拉和下拉(上拉刷新、下拉加载)
-
pages {( data:{ }, //定义全局的定时器 TimeId: -1, //输入框的值改变 就会触发的事件 handleInput(e){ //1.获取输入框的值 const {value} = e.detail; //2.检测合法性 (输入框去电两边空格是否有值) if(!value.trem()){ //值不合法 return; } //清楚定时器 clearTimeout(this.TimeId); //3.准备发送请求获取数据 this.TimeId = setTimeout(()=>{ this.qsearch(value); //发起请求 },1000) } )}