小程序
1. 起步 | uniapp - 黑马优购
图片裁剪组件(更改自 作者: 因吹丝挺的图片裁剪兼容版) - DCloud 插件市场 | 图片裁剪组件 |
---|---|
tmt-calendar - DCloud 插件市场 | 日历组件 |
wx.setNavigationBarTitle | 修改导航栏的字体 |
---|---|
wx.showToast | 显示消息提示框, |
uni.getSystemInfo() | 获取当前手机型号的信息 |
uni.setStorageSync('kw', JSON.stringify(存储的值)) | 存入本地存储 |
JSON.parse(uni.getStorageSync('kw') || []) | 取出本地存储, 没有的话返回一个空数组 |
uni.previewImage() | 点击图片放大效果 |
uni.setTabBarBadge({}) | 设置 tabBar 的数字徽标 |
uni.chooseAddress() | 小程序自带的地址栏 |
uni.openSetting({}) | 让用户打开授权页面 |
uni.chooseImage(OBJECT) | 从本地相册选择图片或使用相机拍照。 |
---|---|
uni.pageScrollTo() | 将页面滚动到目标位置 |
uni.createSelectorQuery().select('#dissan').boundingClientRect().exec() | 获取元素节点信息 |
uni.createAnimation() | uniapp的动画 |
// 点击图片放大效果 uni.previewImage({ // urls: this.imgMsg, current:indexx, urls:['../../static/back.png'], longPressActions: { itemList: ['发送给朋友', '保存图片', '收藏'], success: function(data) { console.log('选中了第' + (data.tapIndex + 1) + '个按钮,第' + (data.index + 1) + '张图片') }, fail: function(err) { console.log(err.errMsg) } } }) uni.showToast({ title: '数据请求失败!', duration: 1500, icon: 'none', }) uni.setTabBarBadge({ index: 2, // 索引 text: this.total + '' // text 必须是个字符串, 不能是数字 }) // 获取节点信息 const query = uni.createSelectorQuery().in(this) query.select('#id').boundingClientRect(data =>{ this.addHeight = (data.height-196) + 'px' }).exec() // 页面的滚的位置 uni.createSelectorQuery().select('#dissan').boundingClientRect(function(rect){ uni.pageScrollTo({ duration:200,scrollTop:9999999 }) }).exec()
// 获取键盘的高度 huqoujioa(e){ // 键盘高度 let { height } = e.detail // 获取键盘高度 this.xunigao = `${height}px` // 键盘高度end },
// uniapp 内置组件。 跳转到响应的网页
2
属性名 | 类型 | 默认值 | 说明 | 试用 |
---|---|---|---|---|
navigationBarTitleText | String | 字符串 | 导航栏标题文字内容 | 导航栏 |
navigationBarBackgroundColor | HexColor | #000000 | 导航栏背景色, 如#00000, 只支持16进制 | 导航栏 |
navigationBarTextStyle | String | white | 导航栏标题颜色 , 仅支持black/white, 黑和白 | 导航栏 |
backgroundColor | HexColor | #fffff | 窗口的背景色 | 窗口背景 |
backgroundTextStyle | String | dark | 下啦 loading 的样式,仅支持dark/light | 窗口背景 |
enablePullDownRefresh | Boolean | false | 是否开启下啦刷新 | 页面效果 |
onReachBottomDistance | Number | 50 | 页面上拉触底时页面底部距离 | 页面效果 |
backgroundColor | 16进制 | 16进制 | #292d38 | 刷新的背景色 |
"navigationStyle": "custom", | 是否有顶部导航栏页面 |
{ "globalStyle": { "navigationBarTextStyle": "white", "navigationBarTitleText": "黑马优购", "navigationBarBackgroundColor": "#C00000", "backgroundColor": "#FFFFFF" } }
注意
模拟器不能 百分之百 还原 , 有时候会有问题, 所以,一切以真机为主
类似于 PC 页面的是 SEO 优化
"action": "allow", // 允许被微信的爬虫工具搜索到 "action": "disallow", // 不允许被微信的爬虫工具搜索到 关闭后会报一个警告需要在 project.config.json 文件中的 ckeckSitemap: false 就可以 了
pages:[ // 谁在第一行, 谁就是第一个项目首页 "pages/list/list" // 添加了一个 list 文件 ] -- 文件存放路径 window :{ // -- 全局定义页面的背景色 "navigationBarBackgroundColor": "#000000" // 设置页面的背景颜色 } style: 'v2' 默认使用最新的样式 sitemapLocation: 'sitemap.json'
页面的JSON 文件中的覆盖 其他JSON 文件中的内容
"navigationBarBackgroundColor": "#000000" // 设置页面的背景颜色
试图内容
view // 类似于div// 相当于 a 标签 scroll-view // -y纵向滚动 -x横向滚动 // 可滚动的区域,常用于滚动效果 例子: { // 固定宽度需要 , scroll-top 是滚动的距离 } swiper 和 swiper-item // 轮播图的容器, 里面的item是组件 swiper 还有其他相应的属性, 如下: indicator-dots 是否显示面板指示点 indicator-dots // 加上小圆点 indicator-color 指示点颜色 indicator-active-color 激活指示点颜色 autoplay 是否自动切换 interval 自动切换时间间隔 circular 是否采用衔接滑动 :duration 总共耗费多少秒 current: 0当前显示第几个索引 text // selectable 属性可以长按复制 // 相当于 span ,只有 text 组件支持复制功能sdasdasd XXX rich-text // 富文本组件, 字符串渲染成 html 结构 button // 按钮组件, 通过open-type 属性调用微信提供的各个功能 // type 为颜色 , size 为大小, , plain 镂空的按钮 常用的事件
小程序的API
事件监听
以 on 开头, 用来监听某些事件的触发p
wx = window
事件绑定
类型 绑定方式 事件描述 tap bindtap 或 bind:tap 手指触摸后马上离开,类似于click input bindinput 或 bind:input 文本框的输入事件 change bindchange 或 bind:change 状态改变时触发, 主要用于复选框 按钮 > 事件对象的属性列表
在获取事件时, 用 e. 来获取下列的事件
属性 类型 说明 type String 时间的类型 timeStamp Integer 页面打开到触发事件的毫米数 target Object 触发事件的组件的一些属性值集合 currentTarget Object 当前组件的一些属性值集合 detail Object 额外的信息 toches Array 触摸事件, 当前停留在屏幕中的触摸点信息的数据 changeToches Array 触摸事件, 当前变化的触摸点信息的数组 target 和 currentTarget 的区别
target 是触发事件的源头组件, 而 currentTarget 则是当前事件所绑定的组件。 举例// 当点击内部按钮时, 点击事件以冒泡的方式向外进行扩散, 也会触发外层 view 的 tap 的处理函数。此时对于外层 view 来说: // e.target 指向触发事件的源头组件, 因此, e.target 是内部的按钮( button )组件 // e.currentTarget 指向是当前触发事件的那个组件, 因此e.currentTarget 是当前 view 组件 wxss 模板样式
rpx 单位, @import 导入 。 rem 和 em 不能再小程序中使用
rpx 就是把一个屏幕大小分成750份,然后会在底层自动进行来渲染适配
爱疯6 中 1rpx === 0.5px || 1px === 2rpx
750rpx = 375px = 750物理像素 1rpx = 0.5px = 1物理像素样式导入
@import '地址'; // 导入css 文件全局配置文件,在pages中
app.json
pages // 记录当前小程序的所有页面的存放路径 window // 全局设置小程序窗口的外观 tabBar // 设置小程序底部 的 tabBar 效果 style // 是否启用新版组件样式
属性名 类型 默认值 说明 试用 navigationBarTitleText String 字符串 导航栏标题文字内容 导航栏 navigationBarBackgroundColor HexColor #000000 导航栏背景色, 如#00000, 只支持16进制 导航栏 navigationBarTextStyle String white 导航栏标题颜色 , 仅支持black/white, 黑和白 导航栏 backgroundColor HexColor #fffff 窗口的背景色 窗口背景 backgroundTextStyle String dark 下啦 loading 的样式,仅支持dark/light 窗口背景 enablePullDownRefresh Boolean false 是否开启下啦刷新 页面效果 onReachBottomDistance Number 50 页面上拉触底时页面底部距离 页面效果 backgroundColor 16进制 16进制 #292d38 刷新的背景色 "navigationStyle": "custom", 是否有顶部导航栏页面 { "globalStyle": { "navigationBarTextStyle": "white", "navigationBarTitleText": "黑马优购", "navigationBarBackgroundColor": "#C00000", "backgroundColor": "#FFFFFF" } }js操作
函数,在 js 文件中与 data 平级】 e.target.dataset.名实现 tabBar 的导航栏
{ "pages":[ // 只要是 tabBar 的页面, 必须是,最前面的, 否则 不能支持 "pages/home/index", // 新建的导航栏页面 "pages/home1/index", "pages/home2/index", "pages/index/index", "pages/logs/logs" ], "tabBar": { // 若要加入导航栏, 必须配置 tabBar 最少俩个 最多6个 "selectedColor": "#C00000", // 选中的标题颜色 "list": [{ "pagePath": "pages/home/index", // 路径 "text": "首页", // 名称 "iconPath": "/images/tabs/home.png", // 未选中的icon 图标 "selectedIconPath": "/images/tabs/home-active.png" // 选中的icon 图标 },{ "pagePath": "pages/home1/index", "text": "首页", "iconPath": "/images/tabs/home.png", "selectedIconPath": "/images/tabs/home-active.png" }] } }小程序的 created 生命周期, 类似于
onLoad(){ // 页面一加载, 就 立刻请求数据 }页面导航
就是页面之间的跳转, 编程式导航, 和声明式导航
声明式导航就是通过
来进行跳转, 编程式导航是调用 API j进行页面跳转 声明式导航
// 跳转到 tabBar 页面> // open-type 跳转的方式 的 switchTab 是必须跳转 // 跳转到 非tabBar 页面 跳转到非tabBar页面 // 其中这个 open-type 可以忽略 // 后腿的导航返回上一页 // 其中这个 open-type 可以忽略 // 导航传参> // 在跳转页面地址后,进行页面的跳转传参 、 在跳转的地址后进行 ? 拼接字符串 (&) 符号进行传参的拼接 编程式导航
跳转到 tabBar 页面
属性 类型 是否必选 说明 url string 是 需要跳转到 tabBar 页面的路径, 路径后不能带参数 sucess funcation 否 接口调用成功的回调函数 fail funcation 否 接口调用失败的回调函数 complete funcation 否 接口调用结束的回掉函数(成功或者失败都会执行) // 页面结构跳转的 tabBAr 页面 > // 通过编程式导航, 跳转的 tabBAr 页面 gotoMessage() { wx.switchTab ({ url: '地址' }) } // 页面结构 跳转的 非tabBAr 页面 > // 通过编程式导航, 跳转的 非tabBAr 页面 gotoMessage() { wx.navigateTo({ url: '地址' }) } // 编程式导航进行跳转传参 跳转的 非tabBAr 页面 > gotoMessage() { wx.navigateTo({ url: '/page/info?name=zs&ganer=男' }) } 在切换页面传参后, 需要接受到当前传到页面的值时, 需要在生命周期中的 onLoad 中的生命周期函数,进行监听页面加载
onLoad: funcation(options){ // options 是跳转过来的接受的数据 this.setData({ data: options // 此时就是将 options 里的数据传入到 data 函数中 }) }后退机制
// 页面结构后退导航 > // 跳转完成后, 进行后退机制 gotoMessage() { wx.navigateBack() // 里面不需要写任何东西 } 页面事件
下啦刷新
我们开启下拉刷新通过 enablePullDownRefresh 改为 true 即可。
// 如果我们想要监听下啦刷新时通过 onPullDownRefresh 函数进行下啦刷新的监听 onPullDownRefresh { log('出发了 message 页面的下啦刷新') } // 通过下啦刷新后, 页面不会自动关闭, 我们需要 wx.stopPullDownRefresh() // 来自动关闭 这个下啦刷新的按钮 onPullDownRefresh { //通过下啦刷新后 log('出发了 message 页面的下啦刷新') wx.stopPullDownRefresh() }上拉触底事件, 例如于上拉刷新
"onReachBottomDistance": "190" 在 JSON 配置文件中进行配置, 此方法是监听距离底部区域还有多少时, 进行上拉刷新的页面。
uni-app // 在 pages.json 中的页面的 style 属性中添加 onReachBottomDistance { "path": "goods_list/goods_list", "style": { "onReachBottomDistance": 150, "enablePullDownRefresh": true, // 开启下啦刷新 "backgroundColor": #ffffff // 开启下啦刷新的颜色 }// 如果我们想要监听上啦刷新时通过 onReachBottom 函数进行上拉刷新的监听 onReachBottom() { log('出发了 message 页面的上啦刷新') }, // 通过下啦刷新后, 页面不会自动关闭, 我们需要 wx.stopPullDownRefresh() // 来自动关闭 这个下啦刷新的按钮 onPullDownRefresh { log('出发了 message 页面的下啦刷新') wx.stopPullDownRefresh() }wx.showLoading(Object object ) 是通过 展示微信的轻提示
wx.hideLoading(Object object ) 是通过关闭微信的轻提示
// 调用 wx 的轻提示来显示 fetColors() { wx.showLoading({title: '数据加载中。。。。'}) // 来展示 loading 的效果 wx.request({ complate: () =>{ // 接口无论成功还是失败, 都会调用此函数 wx.hideLoading() // 来关闭 loading 的效果 } }) } // 上拉触底进行节流的操作案例
pages/contant/contant.wxml {{item}} // js 事件 /** * 生命周期函数--监听页面加载 */ onLoad(options) { this.getDataPOST() }, getDataPOST(){ wx.showLoading({ title: 'title', }) wx.request({ url: 'https://www.escook.cn/api/color', method:"get", success:({data:res}) =>{ this.setData({ contant: [...this.data.contant, ...res.data] }) }, complete: ()=>{ wx.hideLoading() } }) }, /** * 页面上拉触底事件的处理函数 */ onReachBottom() { this.getDataPOST() },生命周期
小程序分为俩个生命周期:
应用生命周期 => 是指小程序从启动 => 运行 => 销毁的过程
页面生命周期 => 每个页面的加载 => 渲染 => 销毁的过程
这么是生命周期呢?
//生命周期函数: 是由小程序框架提供的内置函数, 会伴随着生命周期, 自动按次序执行 //生命周期函数的作用: 允许程序员在特定的时间点,执行某些特定的操作。例如, 页面刚加载的时候,可以在 onLoad 生命周期函数中初始化的数据。 //注意: 生命周期强调的是时间段, 生命周期函数强调的是时间点应用生命周期
小程序的应用生命周期函数需要在 app.js 中进行声明。 示例代码如下 :
前台就是, 小程序在当前手机展示的页面
后台就是, 小程序不在当前手机展示的页面
// app.js 文件 App({ // 小程序初始化完成时, 执行此函数, 全局只触发一次。可以做一些初始化的工作 onLaunch(options){ // 此方法可以在小程序初始化的时候,获取一些本地存储的数据 } // 小程序启动, 或从后台进入前台显示时触发 onShow(options){} // 小程序从前台进入后台实触发 onHide(){} // 页面不存在的生命周期 onPageNotFound() })页面生命周期
小程序的页面生命周期函数需要在页面的 .js 文件 中进行声明, 示例代码如下:
生命周期 参数 描述 show 无 组件页面被展示时候 hide 无 组件页面被隐藏的时候执行 resize Object Size 组件所在页面尺寸发生变化时候 // 页面的 .js 文件 Page({ // 监听页面加载, 一个页面只调用一次 onLoad(options){} // 监听页面显示 onShow(){} // 监听页面初次渲染完成,一个页面只调用一次 onReady() { wx.setNavigationBarTitle({ // 页面第一次加载完成之后, 修改导航栏的文字颜色 title: "案例详情" }) } // 监听页面隐藏 onHide(){} // 监听页面卸载, 一个页面只吊用一次 onUnload(){ getCurrentPages() // 获取当前页面的信息 } // 通过下啦刷新后, 页面不会自动关闭, 我们需要 onPullDownRefresh { //通过下啦刷新后 log('出发了 message 页面的下啦刷新') wx.stopPullDownRefresh() // 来自动关闭 这个下啦刷新的按钮 } // 上拉刷新加载下一页数据 onReachBottom(){} // 滚动的事件 onPageScroll(event){} // 监听分享的 onShareAppMessage(res) { return { title: "XXX的小程序", path: "/pages/home/home", imageUrl: "http://ss.iifaka.com/uploads/20220824/b07d91b05259c1b961ee7a2ed4a9229c.png", } }, })UNI-APP
初始化项目
全局配置 page.json
属性 类型 描述 globalStyle 设置默认页面的窗口表现 pages 设置页面对的路径一级窗口表现 easycom 组件自动引入规则 tabBar 设置底部 tab 的表现 condition 启动模式配置 subPackages 分包预下载 preloadRule 分包预下载规则 "pages" : [ // 这里是路由配置 ], "tabBar": { // 这里就是配置tabbar的地方 "color": "#8a8a8a", // 导航栏字体颜色 "selectedColor": "#d4237a", // 选中后字体的颜色 "borderStyle": "black", // 底部的border颜色,只能是“black”或者“white” "backgroundColor": "#ffffff", // 底部背景颜色 "list": [{ "pagePath": "pages/index/index", // 页面路径 "text": "首页", // 底部导航文字, "iconPath": "static/logo.png", // 没选中前的图标路径 "selectedIconPath": "static/logo.png" // 选中后的图标路径 }, { "pagePath": "pages/mine/mine", "text": "我的", "iconPath": "static/logo.png", "selectedIconPath": "static/logo.png" } ] }分包
// 独立分包谁都不可以引用,也是谁都不能引用 "subPackages": [ {"root": "subpages", "name": "p1", "pages": [ { "path" : "news/news", "style" : { "navigationBarTitleText": "", "enablePullDownRefresh": false } } ], "independent": true // independent 是开启独立分包 } // app.json "preloadRule":{ // 分包预下载的功能 "pages/contact/contact":{ // 触发分包预下载的页面路径 // network 表示在指定网络模式下进行预下载 // 可选值: all(不限制网络) 和 wifi (仅 wifi 模式下进行预下载) // 默认值: wifi "network": "all", // packages 表示进入页面后, 预下载哪些分包。 // 可以通过 root 或 name 指定预下载哪些分包 "packages": ["pkgA"] } }// 安装 vuex // 1. 在store.js 导入 Vue 和 Vuex import Vue from 'vue' import Vuex from 'vuex' import moduleCart from './module/cart' // 2. 将 Vuex 安装为 Vue 的插件 Vue.use(Vuex) // 3. 创建 Store 的实例对象 const store = new Vuex.Store({ // TODO:挂载 store 模块 modules: { moduleCart }, }) // 4. 向外共享 Store 的实例对象 export default store // 在main.js 中┌─components uni-app组件目录 │ └─comp-a.vue 可复用的a组件 ├─pages 业务页面文件存放的目录 │ ├─index │ │ └─index.vue index页面 │ └─list │ └─list.vue list页面 ├─static 存放应用引用静态资源(如图片、视频等)的目录,注意:静态资源只能存放于此 ├─main.js Vue初始化入口文件 ├─App.vue 应用配置,用来配置小程序的全局样式、生命周期函数等 ├─manifest.json 配置应用名称、appid、logo、版本等打包信息 └─pages.json 配置页面路径、页面窗口样式、tabBar、navigationBar 等页面类信息 #1.5 把项目运行到微信开发者工具giit 管理项目
在项目根目录中新建
.gitignore
忽略文件,并配置如下:# 忽略 node_modules 目录 /node_modules /unpackage/dist注意:由于我们忽略了 unpackage 目录中仅有的 dist 目录,因此默认情况下, unpackage 目录不会被 Git 追踪
此时,为了让 Git 能够正常追踪 unpackage 目录,按照惯例,我们可以在 unpackage 目录下创建一个叫做
.gitkeep
的文件进行占位
打开终端,切换到项目根目录中,运行如下的命令,初始化本地 Git 仓库:
git init
将所有文件都加入到暂存区:
git add .
本地提交更新:
git commit -m "init project"#1.6.2 把项目托管到码云
注册并激活码云账号( 注册页面地址:注册 - Gitee.com )
生成并配置 SSH 公钥
创建空白的码云仓库
把本地项目上传到码云对应的空白仓库中
配置网络请求
请参考 @escook/request-miniprogram 的官方文档进行安装、配置、使用
官方文档:@escook/request-miniprogram - npm
// 由于平台的限制,小程序项目中不支持 axios,而且原生的 wx.request() API 功能较为简单,不支持拦截器等全局定制的功能。因此,建议在 uni-app 项目中使用 @escook/request-miniprogram 第三方包发起网络数据请求。最终,在项目的
main.js
入口文件中,通过如下的方式进行配置:import { $http } from '@escook/request-miniprogram' uni.$http = $http // 配置请求根路径 $http.baseUrl = 'https://www.uinav.com' // 请求开始之前做一些事情 $http.beforeRequest = function (options) { uni.showLoading({ title: '数据加载中...', }) } // 请求完成之后做一些事情 $http.afterRequest = function () { uni.hideLoading() }async getSwiperList(){ const { data: res } = await uni.$http.get('/api/public/v1/home/swiperdata') if (res.meta.status !== 200) { return uni.showToast({ title: '数据请求失败!', duration: 1500, icon: 'none', }) } this.swiperList = res.message }配置uni-app 分包
分包可以减少小程序首次启动时的加载时间
在项目根目录中,创建分包的根目录,命名为
subpkg
在
pages.json
中,和pages
节点平级的位置声明subPackages
节点,用来定义分包相关的结构:"subPackages": [ { "root": "subpkg", // 分包的名称 "pages": [] // 分包的页面 } ]封装一个 uni。showToasr 方法 ,是请求失败的提示
当数据请求失败之后,经常需要调用
uni.showToast({ /* 配置对象 */ })
方法来提示用户。此时,可以在全局封装一个uni.$showMsg()
方法,来简化uni.showToast()
方法的调用。具体的改造步骤如下:uni.$showMsg = function (title = '数据加载失败!', duration = 1500) { uni.showToast({ title, duration, icon: 'none', }) } // 使用 async getSwiperList() { const { data: res } = await uni.$http.get('/api/public/v1/home/swiperdata') if (res.meta.status !== 200) return uni.$showMsg() this.swiperList = res.message }配置 VueX
在项目根目录中创建
store
文件夹,专门用来存放 vuex 相关的模块在
store
目录上鼠标右键,选择新建 -> js文件
,新建store.js
文件:.在
store.js
中按照如下 4 个步骤初始化 Store 的实例对象:// 1. 在store.js 导入 Vue 和 Vuex import Vue from 'vue' import Vuex from 'vuex' // 2. 将 Vuex 安装为 Vue 的插件 Vue.use(Vuex) // 3. 创建 Store 的实例对象 const store = new Vuex.Store({ // TODO:挂载 store 模块 modules: {}, }) // 4. 向外共享 Store 的实例对象 export default store在
main.js
中导入store
实例对象并挂载到 Vue 的实例上:// 1. 导入 store 的实例对象 import store from './store/store.js' // 省略其它代码... const app = new Vue({ ...App, // 2. 将 store 挂载到 Vue 实例上 store, }) app.$mount()创建 vuex 模块
在
store
目录上鼠标右键,选择新建 -> js文件
,创建购物车的 store 模块,命名为cart.js
:
在
cart.js
中,初始化如下的 vuex 模块:export default { // 为当前模块开启命名空间 namespaced: true, // 模块的 state 数据 state: () => ({ // 购物车的数组,用来存储购物车中每个商品的信息对象 // 每个商品的信息对象,都包含如下 6 个属性: cart: [], }), // 模块的 mutations 方法 mutations: {}, // 模块的 getters 属性 getters: {}, }在
store/store.js
模块中,导入并挂载购物车的 vuex 模块,示例代码如下:import Vue from 'vue' import Vuex from 'vuex' // 1. 导入购物车的 vuex 模块 import moduleCart from './cart.js' Vue.use(Vuex) const store = new Vuex.Store({ // TODO:挂载 store 模块 modules: { // 2. 挂载购物车的 vuex 模块,模块内成员的访问路径被调整为 m_cart,例如: // 购物车模块中 cart 数组的访问路径是 m_cart/cart m_cart: moduleCart, }, }) export default storevue怎么用, uni-app 怎么用
Mixins === 自定义组件的 - behaviors
注意:当我们一个代码, 需要在其他地方一起引用的时候, 我们可以用到 Mixins
此时可以使用 Vue 提供的 mixins 特性,提高代码的可维护性。
在项目根目录中新建
mixins
文件夹,并在mixins
文件夹之下新建tabbar-badge.js
文件,用来把设置 tabBar 徽标的代码封装为一个 mixin 文件:import { mapGetters } from 'vuex' // 导出一个 mixin 对象 export default { computed: { ...mapGetters('m_cart', ['total']), }, onShow() { // 在页面刚展示的时候,设置数字徽标 this.setBadge() }, methods: { setBadge() { // 调用 uni.setTabBarBadge() 方法,为购物车设置右上角的徽标 uni.setTabBarBadge({ index: 2, text: this.total + '', // 注意:text 的值必须是字符串,不能是数字 }) }, }, }修改
home.vue
,cate.vue
,cart.vue
,my.vue
这 4 个 tabBar 页面的源代码,分别导入@/mixins/tabbar-badge.js
模块并进行使用:// 导入自己封装的 mixin 模块 import badgeMix from '@/mixins/tabbar-badge.js' export default { // 将 badgeMix 混入到当前的页面中进行使用 mixins:[mixinName,SSSSmixinName], // 省略其它代码... }底部支付的模块
基于 uni-ui 提供的 GoodsNav 组件来实现商品导航区域的效果
在 data 中,通过
options
和buttonGroup
两个数组,来声明商品导航组件的按钮配置对象:判断是开发模式还是生产模式
if(process.env.NODE_ENV === 'development'){ log('开发环境') } else { log('生产环境') } // 判断平台 #ifdef H5 #endif安装 view-ui
npm i uview-ui
// 在main.js 中进行添加 import uView from 'uview-ui' Vue.use(uView) // 在 app.vue @import 'uview-ui/index.scss' // 在 uni.scss 引入 @import 'uview-ui/theme.scss' // 在 page.json 中, 按需引入 { "easycom": { // 下载安装的方式需要前面的"@/",npm安装的方式无需"@/" // 下载安装方式 "^u-(.*)": "@/uview-ui/components/u-$1/u-$1.vue" // npm安装方式 // "^u-(.*)": "uview-ui/components/u-$1/u-$1.vue" } }XXXXXXXXXXXXXXXX
XXXXXXXX
XXXXXXXX
XXXXXXXX
XXXXXXXX
XXXXX1XXX
XXXXXXXX
XXXXXXXX
XXXXXXXXX1XXXXXXX
XXXXXXXX
小程序
1. 起步 | uniapp - 黑马优购
API
wx.setNavigationBarTitle 修改导航栏的字体 wx.showToast 显示消息提示框, uni.getSystemInfo() 获取当前手机型号的信息 uni.setStorageSync('kw', JSON.stringify(存储的值)) 存入本地存储 JSON.parse(uni.getStorageSync('kw') || []) 取出本地存储, 没有的话返回一个空数组 uni.previewImage() 点击图片放大效果 uni.setTabBarBadge({}) 设置 tabBar 的数字徽标 uni.chooseAddress() 小程序自带的地址栏 uni.openSetting({}) 让用户打开授权页面
uni.chooseImage(OBJECT) 从本地相册选择图片或使用相机拍照。 uni.pageScrollTo() 将页面滚动到目标位置 uni.createSelectorQuery().select('#dissan').boundingClientRect().exec() 获取元素节点信息 // 点击图片放大效果 uni.previewImage({ current:i , // 当前展示的图片索引 urls: this.Asrray.map(item => { // 把图片的数组返回出去 return item.url }) }) uni.setTabBarBadge({ // 底部导航栏徽标文字 index: 2, // 索引 text: this.total + '' // text 必须是个字符串, 不能是数字 }) // 页面的滚的位置 uni.createSelectorQuery().select('#dissan').boundingClientRect(function(rect){ uni.pageScrollTo({ duration:200,scrollTop:9999999 }) }).exec()组建
// uniapp 内置组件。 跳转到响应的网页注意
模拟器不能 百分之百 还原 , 有时候会有问题, 所以,一切以真机为主
了解目录结构
JSON文件简介
app.json
project.config.json
项目配置文件
setting 保存了相关编译的配置, 例如打开 es6 的模板 projectname 保存的是项目名称 appid 保存的小程序账号idsitemap.josn
类似于 PC 页面的是 SEO 优化
"action": "allow", // 允许被微信的爬虫工具搜索到 "action": "disallow", // 不允许被微信的爬虫工具搜索到 关闭后会报一个警告需要在 project.config.json 文件中的 ckeckSitemap: false 就可以 了页面的.json配置文件
app.json
pages:[ // 谁在第一行, 谁就是第一个项目首页 "pages/list/list" // 添加了一个 list 文件 ] -- 文件存放路径 window :{ // -- 全局定义页面的背景色 "navigationBarBackgroundColor": "#000000" // 设置页面的背景颜色 } style: 'v2' 默认使用最新的样式 sitemapLocation: 'sitemap.json'页面的JSON 文件中的覆盖 其他JSON 文件中的内容
"navigationBarBackgroundColor": "#000000" // 设置页面的背景颜色WXSS === CSS
// 微信新增了 rpx 的尺寸单位, 他将会自动的进行, 尺寸不同的变化。 app.wxss 是全局的css样式, 页面的wxss文件,是只支持自己也面的css 文件样式 // 支持 .class 和 #id element 元素选择器 并集选择器, 后代选择器 ::after 和 ::before 等伪类选择器js文件
app.js // 是整个小程序项目的入口文件, 通过App() 函数来启动整个小程序 页面的.js 文件 // 是通过调用 Page() 函数来创建并运行页面 普通的.js 文件 // 是通过功能模块文件, 用来封装公共的函数或者属性提供页面使用组件 XXML === HTML
试图内容
view // 类似于div> // 相当于 a 标签 scroll-view // -y纵向滚动 -x横向滚动 // 可滚动的区域,常用于滚动效果 例子: { // 固定宽度需要 , scroll-top 是滚动的距离 } swiper 和 swiper-item // 轮播图的容器, 里面的item是组件 swiper 还有其他相应的属性, 如下: indicator-dots 是否显示面板指示点 indicator-dots // 加上小圆点 indicator-color 指示点颜色 indicator-active-color 激活指示点颜色 autoplay 是否自动切换 interval 自动切换时间间隔 circular 是否采用衔接滑动 :duration 总共耗费多少秒 current: 0当前显示第几个索引 text // selectable 属性可以长按复制 // 相当于 span ,只有 text 组件支持复制功能sdasdasd XXX rich-text // 富文本组件, 字符串渲染成 html 结构 button // 按钮组件, 通过open-type 属性调用微信提供的各个功能 // type 为颜色 , size 为大小, , plain 镂空的按钮 Mustache 语法 , 差值表达式
// index.wxml // 在小程序中无论是绑定文本, 还是绑定属性都是使用 message 语法{{message}} {{message * 100}} // 进行算数运算{{message === 'string' ? 4 : 9}} // 进行三元表达式 // index.js data:{ message: 'hello word' }常用的事件
小程序的API
事件监听
以 on 开头, 用来监听某些事件的触发p
wx = window
同步API
特点1:以 Sync 结尾的 API 都是同步 API 特点2:同步 API 的执行结果,可以通过函数返回值直接获取,如果执行出错会抛出异常 举例: wx.setStorageSync('key', 'value') 向本地存储中写入内容异步 API
特点:类似于 jQuery 中的 $.ajax(options) 函数,需要通过 success、fail、complete 接收调 用的结果 举例: wx.request() 发起网络数据请求,通过 success 回调函数接收数据事件绑定
类型 绑定方式 事件描述 tap bindtap 或 bind:tap 手指触摸后马上离开,类似于click input bindinput 或 bind:input 文本框的输入事件 change bindchange 或 bind:change 状态改变时触发, 主要用于复选框 按钮 > 事件对象的属性列表
在获取事件时, 用 e. 来获取下列的事件
属性 类型 说明 type String 时间的类型 timeStamp Integer 页面打开到触发事件的毫米数 target Object 触发事件的组件的一些属性值集合 currentTarget Object 当前组件的一些属性值集合 detail Object 额外的信息 toches Array 触摸事件, 当前停留在屏幕中的触摸点信息的数据 changeToches Array 触摸事件, 当前变化的触摸点信息的数组 target 和 currentTarget 的区别
target 是触发事件的源头组件, 而 currentTarget 则是当前事件所绑定的组件。 举例// 当点击内部按钮时, 点击事件以冒泡的方式向外进行扩散, 也会触发外层 view 的 tap 的处理函数。此时对于外层 view 来说: // e.target 指向触发事件的源头组件, 因此, e.target 是内部的按钮( button )组件 // e.currentTarget 指向是当前触发事件的那个组件, 因此e.currentTarget 是当前 view 组件 bindtap 语法格式
因为小程序中没有,形参和实参。 所以小程序以 data-* 来编写, 具体请看下方
定义一个事件处理函数 , 他与 data 函数平级 例如:bindinput 语法格式
index.wxml > // 通过 bindinput 来响应input 的事件, 里面的value 为 data 中的变量 index.js Page({ inputhandle(e) { // 通过 e.detail.value 来拿到输入的数值 log(e.detail.value) } })条件渲染
wx:if="" wx:elif="" wx:else // 或者 hidden hidden 属性, true 为隐藏, false 为显示 // 相当于 v-if , v-elif, v-else // 如若一次性要渲染多个标签, 可以用 block 进行渲染, 他只是一个容器aa > bb > > 总结 wx:if 和 hidden 的区别? wx:if // 以动态创建和移除元素的方式, 控制元素的展示和隐藏, 直接删除dom 节点,频繁切换 hidden // 以切换样式的方式,(display: none/block), 控制元素的显示和隐藏, 在dom元素上显示。 相当于, v-if === wx:if 和 v-show ==== hidden for 循环
wx:for=“{{ 数组的名字 }}” wx:key="id", 对应 vue 中的 :key
如若要更改索引和 item 项,则需要用到 wx:for-index="idx" ; wx:for-item="itemName"
索引是: {{ index }}, item 项是 {{ item }} > // 如果 不想用 index 或者 item 的话 // index 替换成了 idx , itemName 替换成了 item wxss 模板样式
rpx 单位, @import 导入 。 rem 和 em 不能再小程序中使用
rpx 就是把一个屏幕大小分成750份,然后会在底层自动进行来渲染适配
爱疯6 中 1rpx === 0.5px || 1px === 2rpx
750rpx = 375px = 750物理像素 1rpx = 0.5px = 1物理像素样式导入
@import '地址'; // 导入css 文件window
全局配置文件,在pages中
app.json
pages // 记录当前小程序的所有页面的存放路径 window // 全局设置小程序窗口的外观 tabBar // 设置小程序底部 的 tabBar 效果 style // 是否启用新版组件样式
属性名 类型 默认值 说明 试用 navigationBarTitleText String 字符串 导航栏标题文字内容 导航栏 navigationBarBackgroundColor HexColor #000000 导航栏背景色, 如#00000, 只支持16进制 导航栏 navigationBarTextStyle String white 导航栏标题颜色 , 仅支持black/white, 黑和白 导航栏 backgroundColor HexColor #fffff 窗口的背景色 窗口背景 backgroundTextStyle String dark 下啦 loading 的样式,仅支持dark/light 窗口背景 enablePullDownRefresh Boolean false 是否开启下啦刷新 页面效果 onReachBottomDistance Number 50 页面上拉触底时页面底部距离 页面效果 backgroundColor 16进制 16进制 #292d38 刷新的背景色 "navigationStyle": "custom", 是否有顶部导航栏页面 { "globalStyle": { "navigationBarTextStyle": "white", "navigationBarTitleText": "黑马优购", "navigationBarBackgroundColor": "#C00000", "backgroundColor": "#FFFFFF" } }js操作
函数,在 js 文件中与 data 平级】 e.target.dataset.名修改响应式数据
需要用到this.setData() , 函数 // 例子 this.setData({ count : this.data.count + 1 // count 是要响应式数据 })事件传参
dasda > // info 代表参数的名字, 2 为参数的值, {{}} 里面为数字, 要想为字符串则不加{{}} 全局的 tabBar
最少包含俩个, 最多包含5个
实现 tabBar 的导航栏
{ "pages":[ // 只要是 tabBar 的页面, 必须是,最前面的, 否则 不能支持 "pages/home/index", // 新建的导航栏页面 "pages/home1/index", "pages/home2/index", "pages/index/index", "pages/logs/logs" ], "tabBar": { // 若要加入导航栏, 必须配置 tabBar 最少俩个 最多6个 "selectedColor": "#C00000", // 选中的标题颜色 "list": [{ "pagePath": "pages/home/index", // 路径 "text": "首页", // 名称 "iconPath": "/images/tabs/home.png", // 未选中的icon 图标 "selectedIconPath": "/images/tabs/home-active.png" // 选中的icon 图标 },{ "pagePath": "pages/home1/index", "text": "首页", "iconPath": "/images/tabs/home.png", "selectedIconPath": "/images/tabs/home-active.png" }] } }网络请求
小程序只能请求 https 开头的网络请求
如果要用到合法域名,先将域名配置到信任列表中
微信小程序管理后台 => 开发 => 开发设置 => 服务器域名 => 修改 request 合法域名
// get 请求 wx.request({ url: '地址', method: 'GET', data:{ name: 'ZW', age: 22 }, success:(res) =>{ // 成功之后的回掉函数 log(res) } }) // POST 请求 wx.request({ url: '地址', method: 'POST', data:{ name: 'ZW', age: 22 }, success:(res) =>{ // 成功之后的回掉函数 log(res) } })详细请看下面 uniAPP
import { $http } from '@escook/request-miniprogram' uni.$http = $http // 配置请求根路径 $http.baseUrl = 'https://www.uinav.com' // 请求开始之前做一些事情 $http.beforeRequest = function (options) { uni.showLoading({ title: '数据加载中...', }) } // 请求完成之后做一些事情 $http.afterRequest = function () { uni.hideLoading() }const {data: res} = await uni.$http.get('地址')封装的请求
import { $http } from '@escook/request-miniprogram' uni.$http = $http $http.baseUrl = 'https://www.escook.cn' // 请求开始之前做一些事情 $http.beforeRequest = function (options) { uni.showLoading({ title: '数据加载中...', }) } // 请求完成之后做一些事情 $http.afterRequest = function (options) { console.log(options) const { data, statusCode, errMsg } = options if(statusCode === 200){ uni.hideLoading() return data } else{ uni.showToast({ title: errMsg, duration: 1500, icon: 'none', }) // return Promise.reject((new Error(errMsg))) } uni.hideLoading() } uni.$showMsg = function(title = '数据请求失败!', duration = 1500) { uni.showToast({ title, duration, icon: 'none' }) } import request from './request' export const api = (a) =>{ return uni.$http.get('/apsi/get', query: a) } async qing(){ await api(a) }小程序的 created 生命周期, 类似于
onLoad(){ // 页面一加载, 就 立刻请求数据 }页面导航
就是页面之间的跳转, 编程式导航, 和声明式导航
声明式导航就是通过
来进行跳转, 编程式导航是调用 API j进行页面跳转 声明式导航
// 跳转到 tabBar 页面> // open-type 跳转的方式 的 switchTab 是必须跳转 // 跳转到 非tabBar 页面 跳转到非tabBar页面 // 其中这个 open-type 可以忽略 // 后腿的导航返回上一页 // 其中这个 open-type 可以忽略 // 导航传参> // 在跳转页面地址后,进行页面的跳转传参 、 在跳转的地址后进行 ? 拼接字符串 (&) 符号进行传参的拼接 编程式导航
跳转到 tabBar 页面
属性 类型 是否必选 说明 url string 是 需要跳转到 tabBar 页面的路径, 路径后不能带参数 sucess funcation 否 接口调用成功的回调函数 fail funcation 否 接口调用失败的回调函数 complete funcation 否 接口调用结束的回掉函数(成功或者失败都会执行) // 页面结构跳转的 tabBAr 页面 > // 通过编程式导航, 跳转的 tabBAr 页面 gotoMessage() { wx.switchTab ({ url: '地址' }) } // 页面结构 跳转的 非tabBAr 页面 > // 通过编程式导航, 跳转的 非tabBAr 页面 gotoMessage() { wx.navigateTo({ url: '地址' }) } // 编程式导航进行跳转传参 跳转的 非tabBAr 页面 > gotoMessage() { wx.navigateTo({ url: '/page/info?name=zs&ganer=男' }) } 在切换页面传参后, 需要接受到当前传到页面的值时, 需要在生命周期中的 onLoad 中的生命周期函数,进行监听页面加载
onLoad: funcation(options){ // options 是跳转过来的接受的数据 this.setData({ data: options // 此时就是将 options 里的数据传入到 data 函数中 }) }后退机制
// 页面结构后退导航 > // 跳转完成后, 进行后退机制 gotoMessage() { wx.navigateBack() // 里面不需要写任何东西 } 页面事件
下啦刷新
我们开启下拉刷新通过 enablePullDownRefresh 改为 true 即可。
// 如果我们想要监听下啦刷新时通过 onPullDownRefresh 函数进行下啦刷新的监听 onPullDownRefresh { log('出发了 message 页面的下啦刷新') } // 通过下啦刷新后, 页面不会自动关闭, 我们需要 wx.stopPullDownRefresh() // 来自动关闭 这个下啦刷新的按钮 onPullDownRefresh { //通过下啦刷新后 log('出发了 message 页面的下啦刷新') wx.stopPullDownRefresh() }上拉触底事件, 例如于上拉刷新
"onReachBottomDistance": "190" 在 JSON 配置文件中进行配置, 此方法是监听距离底部区域还有多少时, 进行上拉刷新的页面。
uni-app // 在 pages.json 中的页面的 style 属性中添加 onReachBottomDistance { "path": "goods_list/goods_list", "style": { "onReachBottomDistance": 150, "enablePullDownRefresh": true, // 开启下啦刷新 "backgroundColor": #ffffff // 开启下啦刷新的颜色 }// 如果我们想要监听上啦刷新时通过 onReachBottom 函数进行上拉刷新的监听 onReachBottom() { log('出发了 message 页面的上啦刷新') }, // 通过下啦刷新后, 页面不会自动关闭, 我们需要 wx.stopPullDownRefresh() // 来自动关闭 这个下啦刷新的按钮 onPullDownRefresh { log('出发了 message 页面的下啦刷新') wx.stopPullDownRefresh() }wx.showLoading(Object object ) 是通过 展示微信的轻提示
wx.hideLoading(Object object ) 是通过关闭微信的轻提示
// 调用 wx 的轻提示来显示 fetColors() { wx.showLoading({title: '数据加载中。。。。'}) // 来展示 loading 的效果 wx.request({ complate: () =>{ // 接口无论成功还是失败, 都会调用此函数 wx.hideLoading() // 来关闭 loading 的效果 } }) } // 上拉触底进行节流的操作案例
pages/contant/contant.wxml {{item}} // js 事件 /** * 生命周期函数--监听页面加载 */ onLoad(options) { this.getDataPOST() }, getDataPOST(){ wx.showLoading({ title: 'title', }) wx.request({ url: 'https://www.escook.cn/api/color', method:"get", success:({data:res}) =>{ this.setData({ contant: [...this.data.contant, ...res.data] }) }, complete: ()=>{ wx.hideLoading() } }) }, /** * 页面上拉触底事件的处理函数 */ onReachBottom() { this.getDataPOST() },生命周期
小程序分为俩个生命周期:
应用生命周期 => 是指小程序从启动 => 运行 => 销毁的过程
页面生命周期 => 每个页面的加载 => 渲染 => 销毁的过程
这么是生命周期呢?
//生命周期函数: 是由小程序框架提供的内置函数, 会伴随着生命周期, 自动按次序执行 //生命周期函数的作用: 允许程序员在特定的时间点,执行某些特定的操作。例如, 页面刚加载的时候,可以在 onLoad 生命周期函数中初始化的数据。 //注意: 生命周期强调的是时间段, 生命周期函数强调的是时间点应用生命周期
小程序的应用生命周期函数需要在 app.js 中进行声明。 示例代码如下 :
前台就是, 小程序在当前手机展示的页面
后台就是, 小程序不在当前手机展示的页面
// app.js 文件 App({ // 小程序初始化完成时, 执行此函数, 全局只触发一次。可以做一些初始化的工作 onLaunch(options){ // 此方法可以在小程序初始化的时候,获取一些本地存储的数据 } // 小程序启动, 或从后台进入前台显示时触发 onShow(options){} // 小程序从前台进入后台实触发 onHide(){} // 页面不存在的生命周期 onPageNotFound() })页面生命周期
小程序的页面生命周期函数需要在页面的 .js 文件 中进行声明, 示例代码如下:
生命周期 参数 描述 show 无 组件页面被展示时候 hide 无 组件页面被隐藏的时候执行 resize Object Size 组件所在页面尺寸发生变化时候 // 页面的 .js 文件 Page({ // 监听页面加载, 一个页面只调用一次 onLoad(options){} // 监听页面显示 onShow(){} // 监听页面初次渲染完成,一个页面只调用一次 onReady() { wx.setNavigationBarTitle({ // 页面第一次加载完成之后, 修改导航栏的文字颜色 title: "案例详情" }) } // 监听页面隐藏 onHide(){} // 监听页面卸载, 一个页面只吊用一次 onUnload(){ getCurrentPages() // 获取当前页面的信息 } // 通过下啦刷新后, 页面不会自动关闭, 我们需要 onPullDownRefresh { //通过下啦刷新后 log('出发了 message 页面的下啦刷新') wx.stopPullDownRefresh() // 来自动关闭 这个下啦刷新的按钮 } // 上拉刷新加载下一页数据 onReachBottom(){} // 滚动的事件 onPageScroll(event){} // 监听分享的 onShareAppMessage(res) { return { title: "XXX的小程序", path: "/pages/home/home", imageUrl: "http://ss.iifaka.com/uploads/20220824/b07d91b05259c1b961ee7a2ed4a9229c.png", } }, })WXS脚本 // 不能用于回掉函数, 不能调用js 文件 和 API
wxs 就是 wxs 的脚本
wxs 不支持es6 以上的语法形式, 支持 var 定义变量, 普通函数。
wxs 遵循了 CommonJS 规范, module 对象、 require() 对象、 module.exports 对象
内嵌 wxs 脚本
// 类似于 wxs 的标签, 就像 jasascript 代码可以编写在html 中的文件{{m1.toUpper(username)}} > // 必写 module.exports.toUpper = funcation(str){ return str.toUpperCase() // 将字符串转换成大写的 } > 外联的 wxs 脚本
需要新建一个 .wxs 的脚本文件
funcation toLower(str){ retutn toLowerCase() // 将字符串转换成小写的 } module.exports ={ // 向外导出来, 这个函数 toLower: toLower // 因为 微信不支持 es6 的语法 所以不能简写,只能写全了 } // 使用{{m2.toLower(country)}}> > // module 必写, 路径必须是相对路径 小程序组件
自定义组件
创建组件
新建 components => test 文件夹 下在新建 Component 就会创建好 .js .json .wxml .wxss
// 在组件中的 .json 文件中需要设置 "compontent": true 属性。 此方法是说明他是个组件
局部引入
// 在 页面的 .json 文件中引入组件 { "usingComponents" : { "my-test1": "/compontents/test1/test1" } } // 再页面中的 .wxml 文件中,使用组件> 全局引入
// 在 app.json 文件中, 引入组件 { "pages":[], "window":{}, "usingComponents":{ 'my-text2': "/compontents/test1/test1" } } // 再页面中的 .wxml 文件中,使用组件> 组件中的文件区别
组件带有样式隔离, but 只隔离 class 选择器,id/标签等其他选择器不隔离
// 在组件中的 .json 文件中需要设置 "compontent": true 属性。 此方法是说明他是个组件 // 组件中的 .js 文件中调用的是 Compontent() 函数, 页面的是要写入 Page 函数中 // 组件的事件处理函数需要定义到的 methods 节点中, 页面的是写入与data 平级的即可如果想要组件里的样式和页面的样式互相影响,执行以下操作
// 在组件的 .js 文件中新增以下配置 Compontent({ options:{ stylesolation: 'isolared' // isolared 是组件与页面互不影响 } }) //或者在 .json 中新增如下配置 { "styleIsolation": "isolated" } // isolated : 启用样式隔离,使用class 类名互不影响 //apply-shared : 表示 页面的样式可以影响到组件, 但组件不可以影响到页面 //shared : 表示,可以相互影响// 组件的 data 数据,和 vue 的 data 函数一样 // 组件的 methods 和 vue 的 methods 一样组件的 properties 属性传递方法, 类似于组建之间的传值
Compontent({ properties:{ // 这个方法不和 view 一样可读不可写。他是可读可写的 max:{ type: Number, // 定义的数据类型 vaalue: 10 // 属性的默认值 } } }) // 使用> // 组件的获取 {{max}} > // js 文件 showInfo showInfo() { this.setData({ max: this.properties.max - 1 }) }数据监听器和 watch 一样
Compontent({ observers:{ // 监听器 '字段A, 字段B': funcation(字段A的新值, 字段B的新值){ } } }) // 监听对象的属性变化 Compontent({ observers:{ // 监听器 '对象.属性A, 对象.属性A': funcation(属性A的新值, 属性B的新值){ // 为属性 A 赋的新值,就会触发 // 为属性 B 赋的新值,就会触发 // 整个对象变化, 也会触发 } } }) // 如果要监听对象下面所有的属性变化可以用 ** 来代替, 任何属性变化都会,执行 observers:{ 'rgb.**': funcation(obj) { this.setDate({ fullColor:`${r}, ${g},${b}` }) } }纯数字字段
就是 当一个变量不会在 页面中展示, 也不会传递给其他组件,仅仅在当前页面中展示时候,此时可以把此变量存入到 纯数据字段
可以提升性能
// 在 Compontent 构造器中的 options 节点中, 指定 pureDataPattern 为一个正则表达式, 字段名符合这个正则将会成为纯数字字段 Compontent({ options:{ // 指定所有以 _开头的变量,存储为纯数字字段 pureDataPattern: /^_/ }, data:{ a: true, // 普通数据字段 _b: true // 纯数字字段 } })组件的生命周期
注意小程序的生命周期要全部写入 lifetimes: {} 对象中
生命周期函数 参数 描述说明 created 无 在组件刚刚被创建时执行, 组件的 DOM 树没有被执行 attached 无 在组件实例进入页面节点树时执行, 就是页面的组件刚被放入节点树的时候 ready 无 在组件在制图层布局完成后执行, 就是组件刚被渲染完成 moved 无 在组件实例被移动到节点树另一个位置时执行, 组件的位置被移动 detached 无 在组件实例被从页面节点树移除时执行, 组件实例在页面移除时候 error Object Error 每当组件方法抛出错误时执行, 只要报错就会触发 // created 生命周期是组件刚刚被创建好 // 此时不能创建 setData 。通常在这个生命周期中, 只能应用该组建内的 this 添加一些自定义的属性字段 // attached, 是指组件完全初始化完毕, 进入页面节点树后, attached 生命周期函数会被触发 // 此时, this.data 已被初始化完毕了。此时,可以干很多事情,例如发送请求组件所在页面的生命周期, 写入组件页面
生命周期 参数 描述 show 无 组件页面被展示时候 hide 无 组件页面被隐藏的时候执行 resize Object Size 组件所在页面尺寸发生变化时候 组件所在页面的生命周期函数, 需要定义在 pageLifetimes 节点中, 示例代码’
Compontent({ pageLifetimes:{ hide(){}, show() {}, resize() {} } })插槽
和 vue 一样
// 组件> > // 页面调用的组件 // 如果要启用多个插槽时,需要在 当前的 js 文件进行如下配置 Compontent({ options:{ multipleSlorts: true // 此方法可以定义多个 slot 插槽 } }) // 然后就可以, 定义了 > // 只需要加个名字就好 > 组件通信
// 属性绑定 用于父组件向子组建的指定属性设置数据, 仅能设置 JSON 兼容的数据 // 事件绑定 用于子组建向父组件传递数据, 可以传递任意数据 // 获取组件实例 父组件可以通过 this.selectCompontent() 获取子组建实例对象, 这样就可以直接访问子组建的任意数据和方法// 父组件向子组建传值, 和vue 一样父组件中的值 {{count}} // js properties:{ // 接收 count:{ type: Number } }, 子组建更改了,父组建传来的值, 但要在父组件中回显
// 事件绑定用于实现子向父传值, 可以传递任何类型的数据。 在父组件的 js 文件中, 定义一个函数,这个函数即将通过自定义事件的形式, 传递给子组建 在父组件的 wxml 文件中, 通过自定义事件的形式,将步骤1 中定义的函数引用, 传递给子组建 在子组建中, 通过调用 this.triggerEvent('自定义事件名称', {'/* 参数对象 */'}),将数据发到父组件 在父组件的 js 中, 通过 e.detail 获取子组建传递过来的数据代码
// 父组件 // js syncCount(e){ // e 就是子组建,传递来的值 log(e.detail) // e.detail 就是子传递来的值 this.setDat({ count: e.detail.value }) } // wxml> // 通过自定义事件的方式 // 子组件 // js addCount(){ this.setData({count: this.properties.count + 1}) // 子组建通父组件的值 // 触发自定义事件, 将数值同步给父组件 this,triggerEvent('sync', {value: this.properties.count}) // sync 就是父组件传递来的自定义事件, value 是把修改的值,传递给父组件 } 父子组件之间的通信 - - 实例
// 可在父组件里调用 this.selectComponent("id或class选择器"),获取子组建的实力对象,从而直接访问子组建的任意数据和方法。调用一个选择器,例如 this.selectComponent(".my-compontent")代码
// wxml 结构> 获取子组建的实例 > // js 结构 getChild(){ const child = this.selectComponent(".custmA") // 也可以传递id 选择器 child.setDate({count: child.properties.count + 1}) // 调用子组建 setData 的方法 child.子组建的方法() // 调用子组建的 addCount 方法 } // 切记子组建要写如 bind:sync="syncCount" 来进行双向绑定 addCount(){ this.setData({count: this.properties.count + 1}) // 子组建通父组件的值 // 触发自定义事件, 将数值同步给父组件 this,triggerEvent('sync', {value: this.properties.count}) // sync 就是父组件传递来的自定义事件, value 是把修改的值,传递给父组件 } 自定义组件的 - behaviors
behaviors 是小程序中, 用于实现组件间代码共享的特性, 类似于 Vue.js 中的 ‘mixins’
behaviors 里的东西都是共享的。behaviors 可以引用 behaviors ,组件也可以引用多个behaviors
创建
// 调用 Behavior(Object object) 方法即可创建一个共享的 begavior 实例对象, 给所有组件共享 // 先创建一个 behaviors 的文件,my-behaviors.js 文件 module.exports = Behavior({ data:{ username: 'zs' }, properties:{} // 属性节点 methods: {} // 方法 })导入
// js const myBehavior = require('地址') Compontent:{ behavior: [myBehavior] } //在 wxml 文件中和普通的用法没区别
可用节点 类型 是否必填 描述 propertoes Object Map 否 同组建的属性 data Object 否 同组建的数据 meethods Object 否 同自定义组件的方法 behaviors String Array 否 引入其他的 behavior created Funcation 否 生命周期函数 attached Funcation 否 生命周期函数 ready Funcation 否 生命周期函数 moved Funcation 否 生命周期函数 detached Funcation 否 生命周期函数 使用 npm 包
不支持依赖于 Node.js 内置库的包
不支持依赖于 浏览器内置对象的包
不支持依赖于C++ 插件的包
Vant Weap的 开源协议是 MIT 的协议, MIT协议是可以商用的 @1.3.3
// 快速 上手 https://vant-ui.github.io/vant-weapp/#/quickstart 1. npm init -y 2.npm i @vant/[email protected] -S --production引入 Vant 组件
// 在app.json或index.json中引入组件,详细介绍见快速上手。 "usingComponents": { "van-button": "@vant/weapp/button/index" }定义CSS 变量
element { --main-bg-color: 222 // 定义了个 css 变量。 // 引用 css 变量 color: var(--main-bg-color) } // 定制 Vant 的主题颜色 // app.wxss page({ // 定制警告按钮的背景色和边框颜色 --button-danger-background-color: #000000; //背景色 --button-danger-border-color: #222222; // 边框颜色 // 如何查看其他的主题颜色呢, 可以通过 Vant 自定义主题中的配置文件查找 })小程序 API Promise 化
// 因为小程序官方提供的 API 都是基于回调函数实现的, 例如网络请求 的 API wx.request({ method: '', url: '', data:{}, success:() => {}, // 成功的回掉函数 fail: () => {}, // 失败的回掉函数 complate: () => {} // 请求完成的会掉函数 }) // 那么我们需要把 异步的 API 改成 Promise 化 1. 安装 npm i --save [email protected] - 下载完成,我们不能直接使用,而是需要再次重新构建npm包 // 因为 npm 会把包下载到 node-module 文件下, 小程序无法识别。 我们需要吧 包移动到 miniprogram_npm 下 2. 先删除掉 miniprogram_npm 文件, 点击 工具 => 构建 npm 包 3. // app.js 文件下 import { promisifyAll } from 'miniprogram-api-promise' const wxp = wx.p = {} // 将小程序的对象, 挂载到 wx.p 空对象上 promisifyAll(vx, wxp) // wx 是顶级对象, 把对象挂载到 wxp 4. // 如何调用呢?vant按钮> async getInfo() { const {data: res} = await wx.p.request({ method: "GET", url: '地址', data:{name: 'za', age: 20} }) log(res) } 全局数据共享
又叫: 状态管理, 是为了解决组件之间数据共享的问题,
好比 vuex
// mobx-miniprogram 是用来创建 Store 实例对象 // mobx-miniprogram-bindings 用来 Store 中的共享数据或者方法, 绑定到组件或者页面中使用 1.npm install --save [email protected] [email protected] 2.// 创建 Store 实例对象,并将其导出 // 创建 sotre 文件 => store.js import { observable, action } from 'mobx-miniprogram' export const store = observable({ nameA: 1, // 创建了俩个共享的数据 nameB: 2, // 定义计算属性, 必须以 get 开头, 他是只读的 get sum() { return this.numA + this.numB }, // actions 方法, 用来修改 store 中的数据 // 若要修改 action 的值, 则可以利用 action 的会掉函数 updateNum1: action(function(stop)){ this.numA += step } }) // 在页面中绑定 Store 的成员 // 页面文件 {{nameA}} + {{nameB}} = {{sum}}nameA + 1 // 页面的 .js 文件 import { createStoreBindings } from 'mobx-miniprogram-bindings' import { store } from '地址' Page({ nameAJIA(e){ this.updateNum1(e.target.dataset.setup) // updateNum1 是挂载的内容个 }, onLoad(){ this.storeBindings = createStoreBindings(this, { // 把他绑定到一个方法中 store, // 数据源 fields: ['numA', 'numB', 'sum'], // store 里面的变量,绑定过来 actions: ["updateNum1"] // store 绑定过来的方法 }) }, onUnload: funcation(){ // 页面卸载 后清除这个方法 this.storeBindings.destroyStoreBindings() } })分包
可以优化启动时间, 多协作共同开发时可以更好的解耦协作
//小程序可以把包,分成一个主包,若干个分包。 //主包: 一般由当前项目的启动页面或TabBar页面, 以及一些公共资源 //分包: 只包含当前分包的页面或者私有资源 //当用户进入页面,先下载主包, 在进入到其他页面才会下载页面 //切记: 所有包的大小不能超过 16MB ,单个分包的大小不能超过 2MB配置分包
// 打包原则 小程序是按 subpackages 的配置进行分包的, subpackages 之外的目录将被打包到主包 主包也有自己的 pages (就是最外层的 pages 字段) tabBar 页面必须在主包内 分包之间不能互相嵌套 // 引用原则 主包无法引用分包的私有资源 分包之间不能相互引用 分包可以引用主包内的公共资源独立分包
独立分包, 本质上也是一个包, 正常情况下只能通过主包才能进入分包。 而独立分包,可以独立于主包和其他页面的分包进行单独运行
// 独立分包谁都不可以引用,也是谁都不能引用 "subpackages": [ { "root": "pkgA", "name": "p1", "pages": [ "pages/cat/cat", "pages/dog/dog" ] }, { "root": "pkgB", // 分包 "name": "p2", // 分包名称 "pages": [ // 分包的页面 "pages/apple/apple" ], "independent": true // independent 是开启独立分包 } ],分包预下载
表示小程序在某个页面时候, 由框架自动预下载可能依赖的分包,从而提升进入分包页面的启动速度。
// app.json "preloadRule":{ // 分包预下载的功能 "pages/contact/contact":{ // 触发分包预下载的页面路径 // network 表示在指定网络模式下进行预下载 // 可选值: all(不限制网络) 和 wifi (仅 wifi 模式下进行预下载) // 默认值: wifi "network": "all", // packages 表示进入页面后, 预下载哪些分包。 // 可以通过 root 或 name 指定预下载哪些分包 "packages": ["pkgA"] } }mo
import { storeBindingsBehavior } from 'mobx-miniprogram-bindings' import { store } from '../store/store' behaviors:[storeBindingsBehavior],// 与 data 同级 storeBindings:{ store, // 数据源 fields:{ // nameA: () => store.nameA, // nameB: () => store.nameB, sum: 'sum' }, actions:{ // updateNum1: 'updateNum1' }Vant
在自定义组件中使用 Vant Weapp 组件时,需开启, js 文件 styleIsolation: 'shared' options:{ styleIsolation: 'shared' }, 选项