01-小程序起步
01-小程序是什么
- 小程序(Mini Program)是一种不需要下载安装即可使用的应用,它实现了“触手可及”的梦想,使用起来方便快捷,用完即走
- 目前常见的小程序: 微信小程序、支付宝小程序、淘宝小程序、抖音小程序、头条小程序、QQ小程序、美团小程序等
小程序与普通网页开发的区别
- 网页运行在浏览器环境中, 微信小程序在微信APP中运行
- 由于运行环境的不同,所以小程序中,无法调用 DOM 和 BOM 的 API,但是,小程序中可以调用微信环境提供的各种 API,如:地理定位,扫码,支付...
- 网页的开发模式:浏览器 + 代码编辑器
原生小程序开发
- 微信小程序(官方文档):developers.weixin.qq.com/miniprogram…
- 微信小程序主要技术包括:WXML、WXSS、JavaScript;
uni-app
- vue+原生小程序
02-注册和安装
01-注册
- 进入小程序:
02-安装
- 开发工具实例:
03-小程序的宿主环境和双线程模型
- 宿主环境(host environment)指的是程序运行所必须的依赖环境。
- 安卓手机上安装的APP,宿主环境:Android,给APP操作一些能力
- IOS手机上安装的APP,宿主环境:IOS
- 微信小程序,宿主环境:微信客户端。
- 小程序借助宿主环境提供的能力,可以完成许多普通网页无法完成的功能,例如:微信扫码、微信支付、微信登录、地理定位、etc…
- JS是单线程
小程序使用双线程通信模型:
- 渲染线程:渲染页面;逻辑线程:执行JS逻辑;中间由微信客户端进行通信。
- 小程序中没有ajax请求,ajax是位于浏览器中 ,小程序中叫网络请求。
04-配置app.json
-
在小程序中,看到json文件就是配置文件
-
page表示页面,是一个文件夹,下面有四个文件:xxx.js,xxx.json(配置文件),xxx.wxml(html),xxx.wxss(css)
app app.js 应用入口 app.json 应用的配置 页面中有配置文件,整个小程序也有配置文件 app.wxss 应用的样式 页面中有样式文件,整个小程序也有样式文件 project.config.json 项目的配置文件 sitemap.json 配置小程序或页面是否被微信索引 SEO(搜索小程序时,是否能被检索到)
-
小圆点表示未保存
-
点击左上角文件,设置自动保存
-
页面文件夹下的wxss里没写样式,但app.wxss里写了样式,也有效果(内容居中)
-
app.wxss中的注意点
小程序中为什么提供这么多的JSON配置文件?
-
保证大部分程序员开发出来的小程序都是一致的,如:导航栏,Tabbar,页面路由....
小程序中的json配置文件: app.json 整个应用的配置文件 project.config.json 项目的配置文件 sitemap.json SEO的配置文件 每个页面文件夹中的 .json 配置文件
app.json中配置的内容:
- 小程序的所有页面路径、窗口外观、界面表现、底部 tab 等。
01-app.json中的pages
创建页面:
- 方法一
- 第一步:点击pages文件夹,先创建一个Cart文件夹
- 第二步:在Cart文件夹上点击创建page,输入文件夹名Cart
- 创建后,app.json中自动加上pages。index和Cart谁在前面页面就显示谁
text就是span
- 方法二:
- 也可以在app.json中直接写配置,然后按Ctrl +S保存
02-app.json中的window
参考网址:developers.weixin.qq.com/miniprogram…
window:全局的默认窗口展示
03-app.json中的tabbar
配置tabbar:搜“小程序配置tabbar”,复制代码
-
tabBar 的 6 个组成部分
backgroundColor:tabBar 的背景色 selectedIconPath:选中时的图片路径 borderStyle:tabBar 上边框的颜色 iconPath:未选中时的图片路径 selectedColor:tab 上的文字选中时的颜色 color:tab 上文字的默认(未选中)颜色
03-app.json中的style
- 全局定义小程序组件所使用的样式版本
03-app.json中的sitemapLocation
- 用来指明 sitemap.json 的位置
05-初识数据绑定和计数器实现
-
js中的数据
-
wxml中渲染
<view class="box">{{msg}}</view> 列表渲染: vue中:v-for="" 小程序中:wx:for={{}}
实例如下:
-
方法直接写在js中,不用加methods,如下:
-
但是在小程序中,data中的数据不是响应式的,数据变了,界面不会渲染
-
需要告诉渲染层重新渲染数据,要调用setData() 就能重新渲染数据
加1减1的方法实现: // 加1 increment(){ // 在vue中data中的数据是响应式的,数据变了,界面就会重新刷新 // 但是在小程序中,data中的数据并不是响应式的,数据变了,界面不会渲染 // 需要告诉渲染层重新渲染数据 // 调用setData() 可以重新渲染数据,更新状态机 // this.data.counter += 1; // console.log(this.data.counter); // 更新状态机,数据变了 setData可以让界面重新渲染 this.setData({ // 拿到上一个数加1 counter:this.data.counter + 1 }) }, // 减1 decrement(){ this.setData({ // 拿到上一个数加1 counter:this.data.counter - 1 }) }
06-初识小程序
01-首先在app.js中配置共享数据
App({ })里可以配置多个页面共享的数据
-
定义数据:
-
触发onLaunch,往Storage中存数据(vue中叫localStorage)
// 当小程序初始化完成时,会触发 onLaunch(全局只触发一次) onLaunch: function () { // 往localstorage里存东西,存的数据在调试器中的Storage里查看 // 小程序叫Storage wx.setStorageSync('token',"u4ii90q3ir9wwru8t577856uib"); wx.setStorageSync('userInfo',{name:"wc",age:18}); } 第一次运行: onLaunch: function () { // 如果Storage中没有就往里存,存的数据在调试器中的Storage里查看 if(!token || !userInfo){ wx.setStorageSync('token',"u4ii90q3ir9wwru8t577856uib"); wx.setStorageSync('userInfo',{name:"wc",age:18}); } }
图示:
- 存入后,第二次运行直接从本地存储中拿数据
- 最后,拿到的数据赋值给globalData
02-其次index.js实现页面中拿到数据
- data给页面提供数据
- 拿数据,数据在app.js中的globalData上
- 检查是否拿到数据
- 把数据赋值给data,因为data是给页面提供数据的
- 但下方代码只能拿到数据,界面不会更新
- 等号前uesrInfo是data中定义的,等号后是拿到的globalData中的uesrInfo
- 界面更新需要调用setData,更新状态机
- 第一个uesrInfo是data中定义的,第二个是拿到的globalData中的uesrInfo
- 可以简写,如下:
03-最后数据拿到,在wxml里使用
- 效果如下:
07-数据绑定
js中定义数据,wxml中渲染
- js
- wxml
08-条件渲染
wx:if相当于vue中的v-if,wx:elif相当于vue中的v-else if
- js
- wxml,wx:if 表示是否显示
- 调试器中修改数据,界面会刷新
- 原因:修改了data中的数据,内部自动调用setData,如下:
- 调试器中的AppData
- 模拟器
09-列表渲染
以下全写在名为page的view标签里
01-循环一个字符串
02-循环一个数字
03-循环一个对象
04-循环一个数组
- js中定义数据
- wxml
05-给item和index起别名
- 利用wx:for-item、wx:for-index
10-hidden控制元素的显示与隐藏
wx:if 和 hidden区别
wx:if 控制创建和销毁
hidden 控制样式显示或隐藏
如果频繁切换,推荐使用hidden
-
wx:if
隐藏后,调试器wxml中不存在了,已销毁
-
hidden
点击按钮隐藏后,调试器wxml中还存在。只是利用样式隐藏了
11-block标签(相当于template)
- 使用wx:if,外层会多一个view标签
- 效果:
- 使用block,外层不会多东西
- 效果:
12-小程序中的书写样式
官方文档:developers.weixin.qq.com/miniprogram…
- wxs和js类似
01-行内样式
-
适配:小屏上显示小盒子,大屏上显示大盒子
px:如果是px单位的话,盒子的大小,就固定死了。不管哪个手机型号,盒子大小不变 适配:小屏上显示小盒子,大屏上显示大盒子 在小程序中,提供了一个单位:rpx 类似于rem 相对单位 在iphone6上 2rpx=1px 利用rpx就能实现适配
02-外部样式
03-全局样式
- 页面样式的优先级高于全局样式
13-text组件
- span怎么用,text就怎么用
- \n换行,类似于br标签
- decode,把>解析成 >
- 其他看官方文档:developers.weixin.qq.com/miniprogram…
14-button组件
找官方文档,组件——>表单组件
<view class="page">
<!-- size mini小尺寸-->
<button size="mini">按钮</button>
<!-- type -->
<!-- primary绿色 -->
<button size="mini" type="primary">按钮</button>
<!-- warn红色 -->
<button size="mini" type="warn">按钮</button>
<!-- default白色 -->
<button size="mini" type="default">按钮</button>
<!-- plain 镂空 -->
<button size="mini" type="primary" plain="{{true}}">按钮</button>
<!-- disabled 不能点击 -->
<button size="mini" type="primary" disabled="{{true}}">按钮</button>
<!-- loading 正在加载 -->
<button size="mini" type="primary" loading="{{true}}">按钮</button>
<!-- hover-class 点击时,指定pressed样式 -->
<button size="mini" hover-class="pressed">按钮</button>
<!-- open-type 微信提供的一些能力,别人封装好的 -->
<button size="mini" open-type="contact">客服</button>
<button size="mini" open-type="share">分享</button>
<button size="mini" open-type="getPhoneNumber">获取电话</button>
<button size="mini" open-type="getUserInfo">获取用户信息</button>
</view>
效果如下:
15-预览中生成的二维码
- 想要下方二维码成功
- 必须用注册过的小程序账号登录此网站:mp.weixin.qq.com/
- 然后打开成员管理,添加项目成员或体验成员
小程序上线
- 上传
- 版本管理下,开发版本
16-image组件
点击按钮,选择本地图片
- wxml
- js中定义imgPath状态,实现handleChoose方法
- 使用网络图片
17-progress组件
- 效果:
18-icon组件
- 效果:
19-input组件
- 效果:
20-滚动视图组件
- scroll-x 水平滚动
- 垂直滚动,需要设置高度
21-轮播组件
22-事件相关内容
01-事件绑定
- js
02-target和currentTarget
-js
- 效果:
- 小盒子距离大盒
- 大盒子距离外边的距离
03-如何传参
- js
04-tabbar案例
- js
05-事件的冒泡与捕获
- 先捕获后冒泡
- js
- 效果:
- 先捕获(从外往里)再冒泡(从里往外)
06-阻止冒泡
把bind换成catch,就可以阻止冒泡
07-另一种传参方式 mark
- js
23-小程序中组件的使用
01-内置组件的使用
<view class="page">
<button>内置组件 </button>
</view>
02-自定义组件的使用
- vue,react,ng、、都是组件化开发
- page下面放页面,组件放到components文件夹里
- 一个组件也有四个文件组成
- 组件使用前,先在index.json中注册
03-父传子
- 父index.wxml传递数据
- 父index.js中,实现定义的test方法
- 子com02.js接收数据
- 子com2.wxml中使用数据
04-子传父
- 父index.wxml,绑定wc自定义事件
- 父index.js中,实现定义的wcFn方法
- 子com03.wxml
- 子com03.js中,触发wc事件并给父传参数
24-tabbar案例
父传子
- 父index.wxml中传数据
- 父index.js中定义数据
- 子tabbar.js中接收数据
- 子tabbar.wxml中使用数据,并判断index和currentIndex是否相等,相等就加上active类
- tabaar.wxss中实现子tabbar.wxml中的方法
- tabbar.js中定义currentIndex,实现点谁让谁选中itemTap方法
子传父
- 父index.wxml,绑定点击事件
- 父index.js中实现indexChange方法,data表示子tabbar传过来的索引
25-单个插槽
- index.wxml中使用my-slot组件
- my-slot.wxml
- 效果:
插槽默认值
- index.wxml
- my-slot.wxml,插槽默认值这样写无效
- my-slot.wxml可以这样写,但这样写不管插槽有没有插入内容,都显示默认值
- 效果如下:
- my-slot.wxss 利用css实现,不往插槽内插入内容时,显示默认值
- 效果:
26-具名插槽
- index.wxml使用组件
使用具名插槽,需要在mut-slot.js中配置
- mut-slot.wxml
- mut-slot.wxss
- 效果:
27-发送网络请求
小程序网站API中网络:developers.weixin.qq.com/miniprogram…
01-发送网络请求的基本用法
-
当页面加载时,会触发load事件.在load事件中,就可以发请求
-
index.js中拿数据
-
index.js中,定义数据msg,把数据渲染到页面上
-
index.wxml中使用数据
-
效果:每次刷新,内容都会改变
02-发送网络请求传递参数
- index.js中,传参方式一
- index.js中,传参方式二
- index.js中,传参方式三,封装成一个promise
- 封装完的代码放在utils文件夹里,相当于工具
- ajax.js中,封装promise
- index.js,导入封装好的ajax文件,然后发请求
- index.js,使用async、await
28-小程序中的一些API
参考官方文档
- index.wxml
index.js
- Toast
- 效果
- Loading
- 效果
- wx.showLoading和wx.showToast 同时只能显示一个
- wx.showLoading应与wx.hideLoading 配对使用
- Madol
- 效果
- ActionSheet
- 效果
- 获取位置信息getLocation
- 需要在app.json中配置
- 获取当前手机系统信息
- 本地存储,Sync同步存储
异步操作,没有带Sync
29-小程序中的路由跳转
小程序中的路由分两类:
1)声明式路由
2)命令式路由
01-声明式路由
open-type取值:
open-type="navigate",表示保留当前页面,跳到应用中的某个页面,不能跳到tabbar页面
open-type="redirect" 表示关闭当前页面,跳到应用中的某个页面,可以跳到tabbar页面
open-type="switchTab" 只能用来跳转tabbar页面,不能跳到非tabbar页面
open-type="reLaunch" 表示关闭所有页面,打开应用中某个页面
open-type="navigateBack" 表示关闭当前页面,返回上一个页
- detail.wxml详情页
- comment.wxml评论页
- comment.js实现方法,点击按钮返回
- 默认只能返回1级,返回到详情页
传参
- index.wxml首页
- detail.js详情页,获取数据
- detail.js在data中保存uname和age
- detail.wxml中使用数据
- 效果:点击跳到详情页(传参),在详情页中收到数据name和age
30-小程序中的生命周期
01-页面的生命周期 index.js
-
onLoad 加载页面时触发
-
onReady 初始化完毕后触发
-
onShow 页面渲染出来触发,或切换至前台
-
onHide 切换到后台触发
-
onUnload 页面销毁时触发
Page({ // -------------------------1)data给页面提供状态 /* 页面的初始数据 */ data: { }, // -------------------------------2)在页面中使用到的方法 test(){}, // -------------------------------3)页面中的生命周期 /* 生命周期函数--监听页面加载 */ // 加载页面时,触发onload onLoad(options) { console.log("首页 onload...") }, / * 生命周期函数--监听页面初次渲染完成 */ // 初始化完毕后,触发onReady onReady() { console.log("首页 onReady...") }, /* 生命周期函数--监听页面显示 */ // 页面渲染出来,前台 onShow() { console.log("首页 onShow...") }, /* 生命周期函数--监听页面隐藏 */ // 切到后台触发 onHide() { console.log("首页 onHide...") }, /* 生命周期函数--监听页面卸载 */ // 页面销毁时触发 // wx.redireactTo() 关闭当前页,打开应用中另一页 // 关闭当前页就是销毁当前页 onUnload() { console.log("首页 onUnload...") }, // -------------------------------4)操作页面相关的函数 /* 页面相关事件处理函数--监听用户下拉动作 */ onPullDownRefresh() { console.log("首页 onPullDownRefresh...") }, /* 页面上拉触底事件的处理函数 */ onReachBottom() { }, /* 用户点击右上角分享 */ onShareAppMessage() { } })
02-应用的生命周期 app.js
03-组件的生命周期 components文件夹
- 页面显示时(切换前台),先执行组件里的 show,再执行页面里的 onShow...
- 切换后台时,也是先执行组件里的 hide,再执行页面里的 onHide...
31-项目笔记
01-搭建项目
01-创建项目
- 新建一个干净的项目
- app.wxss中写全局样式
- 保证小程序的版本是2.18.1,太高可能有些东西用不了
- 详情中的本地设置
02-配置vant组件库
第一步
- vant 小程序版本的官方文档:vant-contrib.gitee.io/vant-weapp/…
- 在小程序中如何使用vant,官方文档中有写,先生成一个配置文件package.json
- 在终端输入 npm init -y
- 参考文档,安装依赖 npm i @vant/weapp -S --production
第二步
- 如下:
第三步
- 如下:
第四步:构建 npm 包
- 测试vant组件在小程序中是否可以使用,代码如下:
按钮的注册
按钮的使用
效果如下:
到此,vant组件库就配置成功了
03-配置自定义tabbar
- 在app.json中,配置默认的tabbar(系统内置的)
- 创建一个topic专题页面
- 配置tabbar
- 效果如下:
- 使用vant提供的tabbar,也就是自定义tabbar
- 首先,在tabbar中配置custom:true
- 此时,系统内置好的tabbar就没了
- 创建一个组件(component),就是自定义的tabbar
- 使用vant中的tabbar
注:如果没有样式就清一下缓存,重新编译
- 把tabbar用到的数据,提供出来
- 在wxml中使用
- 给上面的item绑定change事件
实现方法
- 使用active,点击哪个哪个被选中
- 生成其他的tabbar,准备数据如下:
- 在app.json中配置
- 把对应的页面创建出来
- 点击样式可以切换,但页面不能切换
- 配置样式的颜色
- 实现页面的切换
- 但点击切换时,active有问题。需要在每一个页面显示的时候,重新给active赋值
- home
- topic
- category
- 购物车
- 我的
04-配置less
-
vscode中下载插件Easy-Less插件,找到插件所在位置复制(正常路径为:C:\Users\用户名.vscode\extensions),找不到可以全局搜索“easy-less”
-
复制到微信开发者工具的插件文件夹中,路径一般如下:(一定要查看隐藏的文件夹)
C:\用户\用户名\AppData\Local\微信开发者工具\User Data\97c2c3ed9e9b4a343745d4ac3603eef1\Default\Editor\User\extensions
然后重启微信开发者工具
3. 微信开发者工具菜单栏点击设置-编辑器设置,然后点击打开页面底部更多编辑器设置
4. 点击后,添加如下代码:
"less.compile":{
"outExt": ".wxss"
}
- 测试
- less
- 看看wxss中有没有less中的代码,如下:
以上的所有配置目的:为了让less转换成wxss,效果如下:
02-搜索框与轮播图
01-请求二次封装与API
- 对wx.request的二次封装,可以在网上找
- api.js中放了API接口数据地址
- 小程序只支持https,并且需要在后台配置,开发时,就不去校验域名的合法性了
- 在右上角详情的本地设置里勾选
- 到此,就可以发送http请求
02-实现搜索框
- 搜索框是假的搜索框,相当于按钮,一点击跳到另一页面(去vant里找面向小程序的搜索组件)
- 页面中使用搜索框
- 在全局添加一个背景颜色
03-实现轮播图
使用小程序自身轮播图,原生
网址:developers.weixin.qq.com/miniprogram…
- 发布ajax,得到数据,然后再去渲染轮播图 tubie.gitee.io/fe-blog/bas…
- 拿到接口,发送请求,得到数据放进banner数组里
- 渲染轮播图
- 给轮播图添加一些样式,写在home.less里
03-实现popup页面相关功能(点击搜索框,网址跳转到popup页面)
01-配置popup页面
- 点击首页面上的假的搜索框,去到popup页面,配置如下:
保存后生成popup,如下
- 点击首页假的搜索框,去popup页面。home.wxml中绑定点击事件
- home.js中实现gotoPopup方法
- 测试如下
02-绘制popup页面
- 由于每次编译,都需要点击进行跳转,添加一个编译模式
到此,再去编译,就是popup页面不再是home页
- 绘制一个搜索框(此搜索框是一个真的搜索框)
- 在页面中使用搜索框
- 网址:vant-contrib.gitee.io/vant-weapp/…
- 实现onSearch和onCancel方法
必须编译首页面,跳到popup页才有效果,在编译popup页点击取消没效果
03-创建popup页面的三个组件
经过分析,在popup页面,有三个组件:
- 历史记录与热门搜索 HistoryHot
- 提示列表 TipList
- 商品列表 ProductList
- 创建三个组件:
注意这时创建的是页面,需要把三个页面改为组件,默认最外层是一个Page函数,修改成Components函数如下:
最好在json文件中,修改如下:
- 在popup页面中,使用上面三个组件,如下:
- 注册
2.使用
上面显示三个组件显示在同一行,修改如下:
- 按上面的写法,三个组件都显示出来了,按理说,只需要显示其中某一个组件,做法:定义一个状态,控制显示哪个组件。如下:
popup.wxml中,使用如下:
04-完成历史记录和热门搜索的结构和样式
使用了vant中的两个组件:
- 开始写结构:
- 样式如下:
- 样式要写在less文件里,所以先创建一个less文件
- 样式如下:
给删除图标设置大小
- 热门搜索的结构和样式与历史记录一样,直接粘贴即可
05-完成搜索页面的数据渲染
- 发送请求,如下:
- 拿接口,定义容器
- 请求数据
res是服务器响应回来的数据,如下:
- 解构数据与赋值
- 调试器里AppData中查看是否拿到数据,如下:
- 将“520元礼包抢先领”数据放在搜索框中(给搜索框赋默认值)
数据在defaultKeyword中的keyword里。操作如下:
- 渲染出历史记录和热门搜索,需要父传子,如下:
- 父中传递数据
- 子中接收
js中拿到数据
wxml中渲染数据
- 将“520元礼包抢先领”变红
只要判断is_hot是否为1,1的话加上红色,如下:
06-清空历史记录
- 给删除图标绑定点击事件
- 给父popup身上绑定自定义事件
- 在子js文件中实现上述方法,触发父身上的方法
测试点击图标,是否触发父身上clearHistory方法
- 在clearHistory方法中,实现清空历史记录
父js中导入接口
07-点击热门标签去产品列表,实现子传父
当点击热门搜索标签时,需要去商品列表页面,还需要把点击的标签中的数据传递到商品列表页面
- 经过分析可知,需要先把tag中的数据传递给父,即子传父;再把数据传递给子,即父传子
- 给tag绑点击事件
- 实现方法
- 数据传给父:使用自定义属性,得到点击的标签中的数据,如下:
- 在方法中得到点的那个数据
- 触发自定义事件,把数据传递过去
- 在父身上绑定自定义事件
- 实现changeBlockShow方法
- 数据在detail中,得到数据就可以让商品列表显示出来,如下:
测试如下:
测试OK
- 在父中也可以得到子传递过来的关键字,如下:
定义状态
给keyword赋值,点击520元礼包抢先领标签AppData中效果如下:
到此,我们就实现了子传父,并且显示出了商品列表组件。
- 同理,点击历史记录也是一样的,代码如下:
gotoProduct方法已经实现,测试如下:
- 点击历史记录中的tag标签,去到商品列表页。
- 当点击历史记录时,也可以把数据传过来
测试成功。
08-根据传递过来的关键字,获取商品数据
- 导入商品列表api
- 调接口,获取数据
测试一下,数据是否回来了(点击标签)
数据回来了。到此,父中保存了商品列表的数据。
09-绘制商品列表页
实现目标:
- 使用vant中提供的下拉菜单,如下:
- 实现步骤:
- 在商品列表的json文件中引入
- 准备下拉菜单所用到的数据,在vant中copy
- 在HTML中使用
10-父传子,绘制商品列表组件
- 准备容器,用来接收子传过来的数据
- 给goodsList赋值
- 查看goodsList中有没有数据(点击日式标签)
- 父有数据了,传递给子
- 子中接收数据,并查看
- 接收数据
- 查看
- 接下来,把商品列表封装成一个组件
- 设置成组件,如下:
- 使用组件,如下:
- 注册
- 使用
现在我们图片的结构是这样的,如下:
- 把商品列表数据再传递一次,传到GoodsList组件中
- 在GoodsList中接收数据
测试GoodsList中有没有数据
到此,有了数据就可以写样式和结构,渲染数据。
- 结构如下:
- 样式写在less中,如下:
- 对价格进行处理,使用到wxs,类似于js,实现vue中的过滤器
11-处理下拉菜单数据
现在的下拉菜单如下:
- 数据现在还是一些假的,之前调用过一个接口,那个接口中包括下拉菜单对应的数据
解构出数据,如下:
- 下拉菜单需要的数据,如下:
- 经对比,发现需要整理数据
代码如下:
- 定义容器
-利用setData保存数据
- 在调试器中查看(点击日式标签)
- 父传子,把数据传给子,如下:
- 子接收数据,并使用
使用如下:
- 下拉菜单中,没有默认选中其中一项
- 再次分析后端返回的数据,发现checked为true时被选中
- 定义一个状态,表示选中的那一项
- 遍历客户端响应的数据
在AppData中测试,点击日式标签
- 使用上面的filterCategoryCurrentID这个数据,父传子,如下:
- 子接收数据
- 子中使用数据
测试如下:
补充:点击日式,让搜索框也显示日式
- 看一下输入框的数据,取决于什么,实现如下:
12-搜索框实现搜索功能
- 在搜索框中输入内容,按回车也需要显示商品列表,如下:
- 输入数据,按回车,触发search事件,找到对应的方法,获取输入框中输入的数据
- 拿到输入框中输入的数据后,给keyword赋值
到此,点击历史记录或热门搜索或在搜索框中输入关键字,都可以跳到商品列表页面。
13-点击下拉菜单不同选项,发送ajax请求,获取数据(子传父)
- 点击不同选项,可以得到不同的ID:
- 给选项上绑定change事件,如下:
- 实现cateChange方法
- 拿到点击的对象的ID
- 把分类ID传给父,通过自定义事件,如下:
- 在父上绑定自定义事件
- 实现categoryChange方法
- 查看父是否能拿到ID
到此,子把分类的ID传给父,父得到子传递过来的分类ID,有了分类ID,就可以发送ajax请求,获取数据了。
- 调接口,获取数据还需要其他的参数,准备其他参数,如下:
- 现在就关注分类ID,就OK。其他参数使用默认值
- 调用获取商品列表的数据,需要传递一堆的参数,如下:
- 在控制台看一下,发送请求时,参数有没有带过去
- 点击不同的分类,重新去调用接口,如下:
测试:
- 当点击了居家分类,重新去调用接口,此时分类ID就变了。按理说获取到的数据应该不一样,但实际一样,可能接口不够强大
14-价格排序
- 准备数据如下:
- 使用数据,并且绑定change事件
- 实现priceChange方法,如下:
- 把数据传递给父,如下:
- 父绑定fn2自定义事件,如下:
- 实现priceChange方法
- 控制台测试
- 测试发现小问题,默认情况下不能勾选价格由高到低
- 修改代码,如下:
再次测试
15-搜索框输入提示组件
- 输入时会触发change事件
- 实现对应的方法,如下:
- 发送ajax请求,获取数据
- 导入接口
- 使用接口
测试:
- 定义数据
- 将数据保存到容器中
在控制台中查看
- 完成tips布局在vant中找cell单元格
- 父传子,把数据传递给子组件
- 子中接收
- 子中使用,vant中复制
- 实现“没有更多数据”
16-输入框做防抖处理
- 定义timer
- 手写防抖
17-实现点击提示单元格
- 需求:
- 给每一个单元格绑定点击事件并传参
文档中叫bind:click
- 实现上面的方法,与HistoryHot.js中一样
- 还需要在父上绑定自定义事件
测试。
18-实现空组件
- 当搜索一些数据没有时,如下:
- 可实现空组件
- 导入空组件
- 使用空组件
04-用户模块实现
01-顶部实现
- 添加编译模式
- 导入对应的组件
- 准备默认图片,存到assets中
- 在data中引入并使用
- 实现对应结构,如下:
- 书写对应的样式
02-九宫格布局
- 引用对应的组件:
- 样式实现
03-弹出层实现
- 在页面中使用弹出层组件
- 定义一个状态及方法,控制弹出层显示与隐藏
- 在html中使用这个状态
- 当点击下面的登录时,就要显示出弹出层
- 实现gotoLogin方法
- 问题:弹出层没有盖住下面的tabbar
- 先尝试一下这两个组件的层叠性
04-登录表单的绘制
- 在vant中引入输入框和按钮
- js文件中,定义状态
- 绘制html结构
- 效果如下:
- 修改一点结构,加一个DIV
- 写一点样式
登录校验
- 在输入用户名和密码时,对用户名和密码进行校验,给输入框绑定input事件
- 实现updateUsername和updatePassword方法
拿到用户名和密码。
- 当输入空格时,出现提示
- 如果确实输入了用户名和密码,看一下有没有收集到
- 点击登录,如下:
- 实现goToLogin方法(直接点击登录按钮)
到此,登录表单就绘制完毕了,并带有校验功能。
05-实现登录功能(逻辑)
- 导入登录接口api
- 加入return,当用户名和密码为空时,代码不再往下走
- 发送登录请求
看一下,服务器响应的结果(服务器响应回来用户信息和token)
- 逻辑如下:
- 第三件事第四件事先不着急做,先在data中定义一个状态,叫isLogin
- 完成第三四件事
- 测试如下:
头像信息没有显示,原因是后端响应的默认头像图片失效了。
- 明明已经登录了,点击编译效果如下:
- 登录之后,用户名和头像需要从本地localStorage中获取
测试(无论怎么编译,都会有头像和用户名):
- 默认isLogin是false,表示没有登录,如果登录了,isLogin是需要有值,把token的值给isLogin
- 把本地数据删除,相当于没有登录
- 登录
头像有值、username有值、isLogin有值
- 还有一个问题:明明已经登录,点击登录又弹出登录页
- 如果登录成功,就不需要再弹出登录框了
测试OK。
06-实现退出登录
需求:
- 引入vant组件
- 使用组件,如下:
- 错误提示:将下图中的show里的isShowLoginwindow改为isShowLogoutWindow
- 定义出上面的状态和两个方法,如下:
方法1
方法2
- 给小箭头添加点击事件
- 实现gotoLogout方法
- 问题:没有登录时,dialog不能弹出。因为没有登录就不存在退出登录,所以我们还需要判断
- 尝试登录:
只有登录后,才能弹出dialog。
- 点击确定按钮,实现退出登录。不需要调用接口,直接把localStorage中的数据清空,就OK了
07-导航守卫(路由守卫)
- 在没有登录的情况下,不能访问购物车,实现守卫,守卫的代码需要写在自定义tabbar中
- 实现守卫
05-详情页实现
01-点击跳转到详情页
- 添加详情页面
- 在商品列表组件中,绑定点击事件,并传递ID
- 实现对应的方法,并获取ID
- 在详情页中获取id。点击某个商品可以到达详情页,并获取ID
02-获取详情页面数据
- 根据ID发送ajax请求,拿商品详情数据
- 引入接口API
- 发送ajax请求,获取数据
03-详情页面结构和样式替换
- 文件替换完成
04-相关产品的数据渲染
- 也就是相似商品的推荐
- 引入接口
- 准备对应的状态
- 发送ajax请求
- 查看数据
- 添加编译模式
- 实现HTML结构
05-商品导航
-
采用vant组件中的GoodsAction商品导航组件
-
引入对应的SON文件
-
使用组件
效果如下:
-
问题:详情页最后面的商品价格被导航盖住了
-
修改详情页对应样式。给商品加下边距
.about{ backgroud:#fff; padding-bottom:140rpx; }
- 点击收藏切换样式,定义一个状态
- 定义一个方法,改变上面的状态
- 再定义一个样式
- 在HTML文件中使用
06-购物车的弹出层
- 需求:点击规格弹出层
- 引入组件
- 定义一个状态控制弹出层是否显示
- 再定义两个方法,控制弹出层是否显示
- 在HTML中使用
效果:
- 默认是不显示的,所以默认值还改成false
- 给加入购物车绑定点击事件
- 实现上面的方法
测试:当点击加入购物车时,弹出层显示
- 但是它把导航栏覆盖掉了,写一点样式
- 除了上面点击加入购物车,需要弹出层之外,详情页上还有一个选择规格,点击时也需要弹出弹出层
到此,弹出层的绘制就OK了。