赞
踩
第一章=>
1、如何创建项目
2、项目的基本结构
3、页面组成(wxss可以不用)
4、组件的使用
5、协同开发与发布
第二章=>
6、WXML页面结构渲染
7、style样式美化
8、app.json全局配置
9、page.json页面个性化
10、发起网络请求
第三章=>
11、本地生活案例
12、页面间导航跳转
13、下拉刷新
14、上拉加载
15、生命周期函数
16、本地生活案例扩展
第四章=>
17、自定义组件
18、behaviors作用
19、vant-weapp组件库
20、MobX实现全局数据共享
21、API实现Promise化
第五章=>
22、分包
23、自定义tabBar
24、小程序大项目(uni-app)
****************************************************************************************************************************************************************************
- 1、如何创建项目(重新认识下小程序:结构化学习)
- 【1】概述
- 运行环境不同:浏览器 VS 微信环境
- ************************************************************************************
- API不同:DOM DOM API VS 地理定位+扫码+支付
- ************************************************************************************
- 开发者模式不同:浏览器+代码编辑器 VS 小程序账号+小程序开发工具+配置项目
- 【2】第一个小程序
- 我的账号已经有了,扫码即可!!!!
- ************************************************************************************
- https://developers.weixin.qq.com/miniprogram/dev/devtools/download.html
- 下载与安装开发工具(推荐稳定版)
- ************************************************************************************
- https://mp.weixin.qq.com/wxamp/devprofile/get_profile?token=692889462&lang=zh_CN
- 登录获取AppID,在管理后台-开发管理-开发设置里
- ************************************************************************************
- 扫码登录微信小程序即可
- ************************************************************************************
- 设置-外观设置-可以设置颜色 字号18 行距12号。
- @代理设置为不使用任何代理
- ************************************************************************************
- 新建程序页面,注意几个细节点:
- 目录指定:放到E 项目 WXL/LittlePro
- 不使用云服务,语言使用JS(别搞错了!!!!!!!!!)
- ************************************************************************************
- 查看项目效果:可以点击编译按钮(刷到最新,模拟器展示:用的最多)
- 手机上看:项目上的预览按钮,弹出二维码扫下就行了,真机预览
- ************************************************************************************
- 帮助!!!!!!!!!!!!!的使用 (P403 10分钟)
- 区域功能概述(使用iPhone 6 7 8)
- ************************************************************************************
- 代码编辑器、调试功能区域、主要使用Console控制台打印看内容!!!

****************************************************************************************************************************************************************************
- 2、项目的基本结构
- 【1】代码构成
- pages用来存放所有小程序的页面
- ************************************************************************************
- utils用于存放工具类的
- ************************************************************************************
- app.js(入口) / app.json(全局配置) / app.wxss(全局样式文件)
- ************************************************************************************
- project.config.json项目配置文件
- ************************************************************************************
- sitemap.json用来配置小程序及其页面是否允许被微信索引
- ************************************************************************************
- @小程序页面重点概述
- index 【 index.js函数 index.json配置 index.wxml页面结构 index.wxss页面样式 】
- index.wxss可以用style代替的!!!!!!!!!!!!!!
- ************************************************************************************
- json配置文件的作用:app.json(全局配置) project.config.json sitemap.json
- 每个页面xxx.json
- ************************************************************************************
- app.json:全局配置。
- {
- "pages":[ // 有几个页面
- "pages/index/index",
- "pages/logs/logs"
- ],
- "window":{ // 窗口颜色
- "backgroundTextStyle":"light",
- "navigationBarBackgroundColor": "#fff",
- "navigationBarTitleText": "Weixin",
- "navigationBarTextStyle":"black"
- },
- "style": "v2", // 全局定义小程序所有页面背景色、文字颜色 可以删除或保留
- "sitemapLocation": "sitemap.json"
- }
- ************************************************************************************
- project.config.json:项目配置
- {
- "description": "项目配置文件",
- "packOptions": {
- "ignore": [],
- "include": []
- },
- "setting": { // 开发者工具的配置记录 在开发工具里可以配置
- "bundle": false,
- "userConfirmedBundleSwitch": false,
- "urlCheck": true,
- "scopeDataCheck": false,
- "coverView": true,
- "es6": true,
- "postcss": true,
- "compileHotReLoad": false,
- "lazyloadPlaceholderEnable": false,
- "preloadBackgroundData": false,
- "minified": true,
- "autoAudits": false,
- "newFeature": false,
- "uglifyFileName": false,
- "uploadWithSourceMap": true,
- "useIsolateContext": true,
- "nodeModules": false,
- "enhance": true,
- "useMultiFrameRuntime": true,
- "useApiHook": true,
- "useApiHostProcess": true,
- "showShadowRootInWxmlPanel": true,
- "packNpmManually": false,
- "enableEngineNative": false,
- "packNpmRelationList": [],
- "minifyWXSS": true,
- "showES6CompileOption": false,
- "minifyWXML": true,
- "babelSetting": {
- "ignore": [],
- "disablePlugins": [],
- "outputPath": ""
- }
- },
- "compileType": "miniprogram",
- "libVersion": "2.19.4",
- "appid": "wx775c2214e34aa966", // 小程序的appid 可以修改
- "projectname": "miniprogram-92", // 这个项目不等于小程序名称!!!!!
- "condition": {},
- "editorSetting": {
- "tabIndent": "insertSpaces",
- "tabSize": 2
- }
- }
- ************************************************************************************
- sitemap.json
- 小程序内搜索,效果类似于PC网页的SEO。
- {
- "desc": "关于本文件的更多信息,请参考文档 https://developers.weixin.qq.com/miniprogram/dev/framework/sitemap.html",
- "rules": [{
- "action": "allow", // 允许被微信索引 disallow 是不允许被索引
- "page": "*" // 所有页面
- }]
- }
- ************************************************************************************
- 页面的.json配置文件(个性化配置会覆盖全局json配置)
- {
- "pages":[
- "pages/index/index",
- "pages/logs/logs"
- ],
- "window":{
- "backgroundTextStyle":"light",
- "navigationBarBackgroundColor": "#fff", // 全局是白色
- "navigationBarTitleText": "Weixin",
- "navigationBarTextStyle":"black"
- },
- "style": "v2",
- "sitemapLocation": "sitemap.json"
- }
- ****************
- {
- "usingComponents": {},
- "navigationBarBackgroundColor":"#00B26A" // 局部是绿色,最终显示是绿色
- }

****************************************************************************************************************************************************************************
- 3、页面组成(wxss可以不用)
- 【1】如何新建小程序页面
- {
- "pages":[
- "pages/index/index",
- "pages/list/list", // !!!!!!!!!!!!!!操作这个即可
- "pages/logs/logs"
- ],
- "window":{
- "backgroundTextStyle":"light",
- "navigationBarBackgroundColor": "#fff",
- "navigationBarTitleText": "Weixin",
- "navigationBarTextStyle":"black"
- },
- "style": "v2",
- "sitemapLocation": "sitemap.json"
- }
- ************************************************************************************
- 修改项目首页:
- "pages":[
- "pages/list/list", // 这里
- "pages/index/index",
- "pages/logs/logs"
- ],
- 【2】WXML和HTML区别:
- 标签名称不同、属性节点不同、提供了类似于VUE中的模板语法!!!!!
- HTML( div span img a)
- WXML(view text image navigator)
- ************************************************************************************
- 属性节点不同
- <a herf="#">百度</a>
- <navigator url="/pages/index/index">主页</navigator>
- ************************************************************************************
- 提供数据绑定、列表渲染、条件渲染和VUE一样!!!!!!!!!!!!
- ************************************************************************************
- WXSS与CSS
- 区别:新增了rpx尺寸单位、提供全局样式和局部样式、wxss仅支持部分css选择器
- ************************************************************************************
- app.wxss全局样式表。xx页面.wxss局部样式
- ************************************************************************************
- wxss仅支持部分css选择器:比如id选择器,类选择器,元素选择器
- 【3】具体文件配置
- .js文件:点击、获取用户位置
- app.js 整个小程序的入口文件,通过App()函数来启动整个小程序。
- xx页面.js通过调用Page()函数来创建并运行页面。
- 普通的.js文件,用来封装工具类或者公共属性供项目使用。
- 【4】宿主环境
- 小程序运行所必须依赖的环境。就是手机微信!!!!!没有微信,就没有小程序
- ************************************************************************************
- 小程序宿主环境提供的支持:通行模型、运行机制、组件、API
- ************************************************************************************
- 通信的主体:渲染层WXML WXSS、逻辑层JS。
- ************************************************************************************
- 通信模型:渲染层WXML与逻辑层JS通信(微信客户端)。逻辑层JS与三方服务API器之间的通信(微信客户端)。
- ************************************************************************************
- 运行机制:
- 小程序启动过程:小程序代码包下载到本地--->解析app.json全局配置文件--->执行app.js入口文件调用App()
- --->渲染首页、小程序启动完成。
- 页面渲染过程:.json--->wxml/wxss---->.js调用Page()函数--->页面渲染完成。

****************************************************************************************************************************************************************************
- 4、组件的使用
- 【1】组件的分类:
- 视图容器(view scroll-view swiper swiper-item)、基础内容、表单组件、导航组件!!!!
- +媒体组件、map地图组件、canvas画布组件、开放能力、无障碍方向。
- 【2】view的使用
- <!-- 分割线,这是下面的内容... 我先都用style写,快速上手目的是-->
- <view style="display: flex;justify-content: space-around;">
- <view style="width: 100px;height: 100px;text-align: center;line-height: 100px;background-color: lightgreen;">1</view>
- <view style="width: 100px;height: 100px;text-align: center;line-height: 100px;background-color: lightskyblue;">2</view>
- <view style="width: 100px;height: 100px;text-align: center;line-height: 100px;background-color: lightcoral;">3</view>
- </view>
- 【3】scroll-view的使用:height: 120px;" scroll-y
- <!-- 分割线,这是下面的内容... -->
- <scroll-view style="display: flex;justify-content: space-around;height: 120px;" scroll-y>
- <view style="width: 100px;height: 100px;text-align: center;line-height: 100px;background-color: lightgreen;">1</view>
- <view style="width: 100px;height: 100px;text-align: center;line-height: 100px;background-color: lightskyblue;">2</view>
- <view style="width: 100px;height: 100px;text-align: center;line-height: 100px;background-color: lightcoral;">3</view>
- </scroll-view>
- 【4】轮播图样式实现:swiper和swiper-item组件的基本使用。用style真是真清晰,上手块,牛批呀
- <!-- 分割线,这是下面的内容... -->
- <swiper style="height: 150px;" indicator-dots>
- <swiper-item>
- <view style="height:100%;line-height: 150px;text-align: center;background-color: green;">A</view>
- </swiper-item>
- <swiper-item>
- <view style="height:100%;line-height: 150px;text-align: center;background-color: yellow;">B</view>
- </swiper-item>
- <swiper-item>
- <view style="height: 100%;line-height: 150px;text-align: center;background-color: blue;">C</view>
- </swiper-item>
- </swiper>
- 【5】其他自定义属性:
- indicator-dots是否展示小圆点
- <swiper style="height: 150px;" indicator-dots indicator-color="white" indicator-active-color="red"
- autoplay interval="2000" circular>
- ************************************************************************************
- 基础内容组件text 、rich-text
- text支持长按选中
- <view>
- 长按选中
- <text selectable> // !!!!!!!!!!!!!!!!!!
- 1592129198
- </text>
- </view>
- ************************************************************************************
- rich-text,感觉用的不多吧!!!!!!!!!!!!!!!!!!!!!
- <view>
- <rich-text nodes="<h1 style='color:red'>示例</h1>">
- </rich-text>
- </view>
- 【6】其他常用组件
- button
- <!-- 分割线,这是下面的内容...和VUE好像 -->
- <button>默认按钮</button>
- <button type="primary">主要按钮</button>
- <button type="warn">主要按钮</button>
- <button type="primary" size="mini">主要小按钮</button>
- <button type="primary" plain="true">主要镂空按钮</button>
- ************************************************************************************
- image使用(同时优化了自己的服务器,作为图片上传与预览的功能,牛批)
- <!-- 分割线,这是下面的内容...和VUE好像 -->
- <image src="https://wdfgdzx.top/document/pre_see/f75ffca9d133429c97622a5093ff6a80.jpg"></image>
- <image src="https://wdfgdzx.top/document/pre_see/f75ffca9d133429c97622a5093ff6a80.jpg" mode="aspectFit"></image>
- <image src="https://wdfgdzx.top/document/pre_see/f75ffca9d133429c97622a5093ff6a80.jpg" mode="aspectFill"></image>
- <image src="https://wdfgdzx.top/document/pre_see/f75ffca9d133429c97622a5093ff6a80.jpg" mode="widthFix"></image>
- <image src="https://wdfgdzx.top/document/pre_see/f75ffca9d133429c97622a5093ff6a80.jpg" mode="heightFix"></image>
- ************************************************************************************
- 【7】小程序的宿主环境API:事件监听类API、同步API、异步API
- 事件监听类API:以on开头,wx.onWindowResize
- 同步API:Sync结尾的API wx.setStorageSync("key","value")
- 异步API:需要通过success、fail、complete来接收结果的。wx.request()发起网络请求,通过success接收

****************************************************************************************************************************************************************************
- 5、协同开发与发布
- 【1】权限管理需求
- 项目权限:管理、产品、设计、开发、测试
- 【2】成员管理
- https://mp.weixin.qq.com/wxamp/user/manage?action=index&use_role=1&token=1582776250&lang=zh_CN
- 【3】可惜了了,我是全栈,我就是管理员,我什么都需要。哈哈哈
- 项目成员、体验成员
- 【4】小程序成员管理
- 开发者权限:对小程序功能进行开发。
- 体验者权限:体验小程序
- 登录权限:登录小程序后台,无需管理员确认
- 开发设置。
- 腾讯云管理。
- 【5】成员的添加
- 主要在成员管理操作!!!!!!!!!!!!!!!!!!!
- 【6】小程序的版本
- 开发版本--->体验版本--->审核中的版本--->发布正式版
- **************************************************************************************
- 上传按钮进行上传。
- https://mp.weixin.qq.com/wxamp/wacodepage/getcodepage?token=1582776250&lang=zh_CN
- 这里找到开发版本后进行审核!!!!!!!!!!!!!
- 【7】基于小程序码的推广
- https://mp.weixin.qq.com/wxamp/basicprofile/index?token=1582776250&lang=zh_CN
- 可以下载对应的小程序码
- **************************************************************************************
- 查看运营数据:
- https://wedata.weixin.qq.com/mp2/basic-data/realtime-data
- 点击移动端查看数据--->可以扫描二维码,查看相关数据

****************************************************************************************************************************************************************************
- 6、WXML页面结构渲染
- 【1】数据绑定
- data中定义、wxml中使用
- ***************************************************************************************
- data: {
- list: {
- name: "默认名称"
- }
- },
- ***************************************************************************************
- <text>数据详情:{{list.name}}</text> // 胡子语法
- 【2】胡子语法使用:内容绑定、绑定属性、三元运算
- 绑定属性:和VUE有点不同了
- data: {
- list: {
- name: "默认名称",
- src: "https://wdfgdzx.top/document/pre_see/fe78f50f0dee49569735e9c4ab608708.jpg"
- }
- },
- ***************************************************************************************
- <image src="{{list.src}}"></image>// 成功调用
- <image src="{{list.src}}" mode="widthFix"></image>
- ***************************************************************************************
- 三元运算:
- data: {
- list: {
- name: "默认名称",
- src: "https://wdfgdzx.top/document/pre_see/fe78f50f0dee49569735e9c4ab608708.jpg",
- randomNum1: Math.random() * 10
- }
- },
- ***************************************************************************************
- <!-- 分割线,这是下面的内容...和VUE好像 -->
- <text>数据详情:{{list.name}}{{list.randomNum1}}</text>
- <image src="{{list.src}}" mode="widthFix"></image>
- <text>\n{{list.randomNum1>=5?'大于等于5':'小于5'}}</text>
- 【3】算术运算
- data: {
- list: {
- name: "默认名称",
- src: "https://wdfgdzx.top/document/pre_see/fe78f50f0dee49569735e9c4ab608708.jpg",
- randomNum1: Math.random().toFixed(2) // 生成一个随机的两位小数
- }
- },
- ***************************************************************************************
- <text>数据详情:{{list.randomNum1}}----{{list.randomNum1*100}}</text>
- 【4】事件绑定:tap input change
- event:type事件类型、target触发事件的组件、detail额外的信息
- ***************************************************************************************
- target和currentTarget的区别:
- target是触发事件的源头组件,而currentTarget是当前事件所绑定的组件
- show() {
- wx.showToast({
- title: '点击了按钮',
- })
- },
- ***************************************************************************************
- <view bindtap="show" style="background-color: aquamarine;"> //currentTarget
- <button type="primary">按钮</button> // target
- </view>
- 【5】bindtap的语法格式
- <button type="primary" bindtap="show">点击我能响应</button>
- ***************************************************************************************
- show(e) {
- console.log(e)
- console.log(e.target)
- wx.showToast({
- title: '点击了按钮',
- })
- },
- 【6】为data中数据赋新值
- giveNewVal(e) {
- this.setData({
- list: {
- name: '新值'
- }
- })
- },
- ***************************************************************************************
- <!-- 分割线,这是下面的内容...和VUE好像 -->
- <text>{{list.name}}</text>
- <button type="primary" bindtap="giveNewVal">重新赋值</button>
- ***************************************************************************************
- giveNewVal(e) {
- this.setData({
- list: {
- count: this.data.list.count + 1 // 主要是这里!!!!!!!!!!!!!!!!!!
- }
- })
- },
- ***************************************************************************************
- <text>{{list.count}}</text>
- <button type="primary" bindtap="giveNewVal">重新赋值</button>
- 【7】事件传参
- <button type="primary" bindtap="showVal" data-info="{{'大家好'}}">传参调用</button>
- ***************************************************************************************
- showVal(e) { // 说明小程序中e很重要的,都能通过它传参了,卧槽 日你大爷
- //console.log(e.target.dataset.info)
- wx.showToast({
- title: e.target.dataset.info,
- })
- },
- ***************************************************************************************
- <button type="primary" bindtap="showVal" data-info="{{2}}">传参调用</button>// 传的是数值
- <button type="primary" bindtap="showVal" data-info="{{'2'}}">传参调用</button> // 传的是字符串
- ***************************************************************************************
- 注意:小程序不能直接在括号里传参,日尼玛反人类!!!!!!!!!!!!!!!!
- 【8】bindinput的语法格式
- showVal(e) {
- console.log(e.detail.value) // 这里拿到的方式注意!!!!!!!!!
- },
- ***************************************************************************************
- <input bindinput="showVal" style="background-color: aquamarine;border: 1px solid gray;"></input>
- 【9】实现文本框和data之间的数据同步,太简单了
- showVal(e) {
- console.log(e.detail.value)
- this.setData({
- list: {
- name: e.detail.value
- }
- })
- },
- ***************************************************************************************
- <input bindinput="showVal" style="background-color: aquamarine;border: 1px solid gray;"></input>
- {{list.name}}
- ***************************************************************************************
- 不管wxss确实省事很多了,集中精力放在重点的事情上,后面自己一统江山就靠这个了,起飞!!!
- 【10】条件渲染
- data: {
- list: {
- name: '默认值',
- flag: false
- }
- },
- ***************************************************************************************
- <text wx:if="{{list.flag}}">true</text>
- <text wx:else>false</text>
- ***************************************************************************************
- 结合<block>使用wx:if,实现整体的显示切换,能够避免在页面渲染不必要的元素。
- <block wx:if="{{list.flag}}">
- <text>true</text>
- <text>\ntrue显示2</text>
- </block>
- <block wx:else>
- <text>false</text>
- <text>\nfalse显示2</text>
- </block>
- 【11】hidden的使用
- <view hidden="{{list.flag}}">false</view>
- <view hidden="{{!list.flag}}">true</view>
- 【12】wx:if与hidden的比对
- wx:if是创建和移出、hidden是加样式。和VUE好像呀!!!!!频繁切换用hidden.....
- 【13】列表渲染wx:for
- data: {
- test: {
- list: ['陈翔', '球球', '蘑菇头', '米线儿', '闰土']
- }
- },
- ***************************************************************************************
- <view wx:for="{{test.list}}">
- 索引是:{{index}} 当前项:{{item}}
- </view>
- ***************************************************************************************
- wx:key的使用,可以提高渲染效率
- <view wx:for="{{test.list}}" wx:key="index">
- 索引是:{{index}} 当前项:{{item}}
- </view>
- ***************************************************************************************
- data: {
- test: {
- list: [
- {id:1,name:'陈翔'},
- {id:2,name:'球球'},
- {id:3,name:'米线儿'},
- ]
- }
- },
- ***************************************************************************************
- <view wx:for="{{test.list}}" wx:key="id"> // 数据库查询的基本都有id
- 索引是:{{index}} 当前项:{{item.name}}
- </view>

****************************************************************************************************************************************************************************
- 7、style样式美化
- 【1】wxss和css的关系
- wxss具有大部分css属性,扩展了rpx @import样式导入
- *****************************************************************************************
- 行了初期,我只用style="xxxx",哈哈哈哈哈!!!!!!!!!!
- 【2】rpx概述
- 屏幕总宽度为750份,小程序会自动把rpx换算成像素单位渲染,从而实现屏幕适配
- *****************************************************************************************
- rpx与px换算。750rpx=375px=750物理像素,不同的设备还不同,了解即可。
- iphone6开发比较合适
- 【3】样式导入@import
- .globalColor {
- color: red
- }
- *****************************************************************************************
- /* pages/test/test.wxss */
- @import "/common/common.wxss";
- *****************************************************************************************
- <view wx:for="{{test.list}}" wx:key="id" class="globalColor"> // 名字显示就是红色
- {{item.name}}
- </view>
- *****************************************************************************************
- 哪有style来的直接呢?哈哈哈
- <view wx:for="{{test.list}}" wx:key="id" style="color: green;">
- {{item.name}}
- </view>
- 【4】全局样式与局部样式
- /**app.wxss**/ 这是全局样式!!!!!!!!!!!!!!!!
- *****************************************************************************************
- /* pages/test/test.wxss */ 局部样式,他的配置会覆盖全局样式的配置
- *****************************************************************************************
- 有这个功夫不如,用style 卧槽,搞的这么复杂。

****************************************************************************************************************************************************************************
- 8、app.json全局配置
- 【1】app.json就是全局配置文件!!!!!!!!!!!!!!!!!!
- **********************************************************************************************
- @pages 记录当前小程序所有页面的存放路径
- @window 全局设置小程序窗口的外观
- @设置小程序底部的tabBar效果
- @style 是否启用新版组件样式
- 【2】window常用配置
- navigationBar开头的都是配置导航栏效果的
- backgroundColor开头的都是配置窗口背景的
- 下拉刷新页面效果的选项
- **********************************************************************************************
- "navigationBarTitleText": "物品回收", 配置标题文本的
- **********************************************************************************************
- 设置导航栏的背景色
- "navigationBarBackgroundColor": "#2b4b6b",
- "navigationBarBackgroundColor":"#00B26A"
- **********************************************************************************************
- 设置标题文字颜色
- "navigationBarTextStyle": "white"
- **********************************************************************************************
- 全局开启下拉刷新功能
- "window": {
- "backgroundTextStyle": "light",
- "navigationBarBackgroundColor": "#2b4b6b",
- "navigationBarTitleText": "物品回收",
- "navigationBarTextStyle": "white",
- "enablePullDownRefresh": true //!!!!!!!!!!!!!!!!!!!这个点!!!!!!
- },
- 这个下拉刷新,会作用全局所有页面。
- 模拟器并不能100%还原真机,发布的时候还是用真机测试下!!!!!!!!!
- **********************************************************************************************
- "backgroundColor": "#efefef" 配置下拉刷新区域的颜色值。
- **********************************************************************************************
- 设置下拉刷新时,loading效果
- "window": {
- "backgroundTextStyle": "dark", // !!!!!!!!!!!!!!!!!!!!!
- "navigationBarBackgroundColor": "#2b4b6b",
- "navigationBarTitleText": "物品回收",
- "navigationBarTextStyle": "white",
- "enablePullDownRefresh": true,
- "backgroundColor": "#efefef"
- },
- **********************************************************************************************
- 设置上拉触底的距离:上拉滑动操作,来加载更多数据的问题。
- onReachBottomDistance 默认是50px加载下一页,如果希望改变。不建议改,50px即可
- "window": {
- "backgroundTextStyle": "dark",
- "navigationBarBackgroundColor": "#2b4b6b",
- "navigationBarTitleText": "物品回收",
- "navigationBarTextStyle": "white",
- "enablePullDownRefresh": true,
- "backgroundColor": "#efefef",
- "onReachBottomDistance": 100 // 知识说明下这个知识点
- },
- 【3】tabBar:实现多页面的快速切换,一般是底部tabBar(2-5项标签)
- 6个组成部分:backgroundColor tabBar的背景色。
- selectedIconPath:选中时图片路径
- borderStyle 上边框颜色
- iconPath:未选中的图片路径
- selectedColor:选中的时候的颜色
- color:未选中时候的颜色
- **********************************************************************************************
- 配置tabBar效果!!!!!!!!!!!!!!!!
- {
- "pages": [
- "pages/index/index",
- "pages/test/test",
- "pages/logs/logs"
- ],
- "window": {
- "backgroundTextStyle": "dark",
- "navigationBarBackgroundColor": "#2b4b6b",
- "navigationBarTitleText": "物品回收",
- "navigationBarTextStyle": "white",
- "enablePullDownRefresh": true,
- "backgroundColor": "#efefef"
- },
- "style": "v2",
- "sitemapLocation": "sitemap.json",
- "tabBar": { // !!!!!!!!!!!!!!!!
- "list": [{
- "pagePath": "pages/index/index", // !!!!!!!!!!!!!!!!
- "text": "主页"
- },
- {
- "pagePath": "pages/test/test", // !!!!!!!!!!!!!!!!
- "text": "测试"
- }
- ]
- }
- }
- **********************************************************************************************
- 有了云服务器真方便,自己的七牛云呀,嘿嘿嘿!!!必须放在本地,emmm 有意思!!!!!
- "tabBar": {
- "list": [{
- "pagePath": "pages/index/index",
- "text": "主页",
- "iconPath": "/common/主页1.png",
- "selectedIconPath": "/common/主页2.png"
- },
- {
- "pagePath": "pages/test/test",
- "text": "测试",
- "iconPath": "/common/测试1.png",
- "selectedIconPath": "/common/测试2.png"
- }
- ]
- }

****************************************************************************************************************************************************************************
- 9、page.json页面个性化
- 【1】页面配置文件的作用
- 用来配置当前页面的窗口外观、页面效果的。感觉可以但没必要!!!!!
- ******************************************************************************************
- 页面配置和全局配置的关系。
- 如果想覆盖,就把全局配置的内容复制一份,到页面配置重新指定下颜色。
- 【2】页面配置中常用配置项:和全局的一样 emmm !!!!!!!!!
****************************************************************************************************************************************************************************
- 10、发起网络请求
- 【1】网络数据请求,只能请求https类型的接口
- 必须将接口的域名添加到信任列表中,我就信任https://wdfgdzx.top 哈哈
- https://mp.weixin.qq.com/wxamp/devprofile/get_profile?token=1582776250&lang=zh_CN
- 上述地址添加
- **********************************************************************************************
- 不能用localhost,而且还必须备案,emmm
- 【2】发起get请求
- getInfo() {
- wx.request({
- url: 'https://wdfgdzx.top/wx_test', // 请求的地址接口,必须基于https协议
- method: 'GET', // 请求的方式
- data: { // 发送到服务器的数据
- page: 1
- },
- success: res => {
- wx.showToast({
- title: res.data,
- icon: 'success',
- duration: 2000
- }); // 请求成功之后的回调函数
- }
- })
- },
- **********************************************************************************************
- getInfo() {
- let thisA = this; // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
- wx.request({
- url: 'https://wdfgdzx.top/wx_test', // 请求的地址接口,必须基于https协议
- method: 'GET', // 请求的方式
- data: { // 发送到服务器的数据
- page: 1
- },
- success: res => {
- thisA.setData({ // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
- "test": {
- "name": res.data
- }
- })
- }
- })
- },
- 【3】发起post请求 P34 16分
- postInfo() {
- let thisA = this;
- wx.request({
- url: 'https://wdfgdzx.top/wx_post',
- method: "post",
- data: {
- name: "接口必将返回---陈翔六点半"
- },
- success: (res) => {
- thisA.setData({
- "test": {
- "name": res.data
- }
- })
- }
- })
- },
- **********************************************************************************************
- <button type="primary" bindtap="postInfo">发起网络请求</button>
- <view>{{test.name}}</view>
- 【4】页面加载时,请求数据
- onLoad(options) {
- wx.showToast({
- title: '执行了!',
- })
- this.wx_post()
- },
- 【5】跳过request合法域名校验
- 合法域名校验只提供了https
- ***************************************************************************************
- 但是为了方便开发,可以在:设置-项目设置-不校验合法域名!
- 注意只能在开发与调试阶段使用。
- ***************************************************************************************
- 关于跨域问题,小程序是不存在的,吼吼牛批!!!!!!!!!
- ***************************************************************************************
- Ajax技术依赖于XMLHttpRequest,小程序的请求是自带的,是叫发起网络请求!

****************************************************************************************************************************************************************************
- 11、本地生活案例
- 【1】步骤
- 新建项目--->配置导航栏效果--->配置tabBar效果--->实现轮播图--->九宫格效果--->图片布局
- 【2】项目备份+项目结构改变
- "pages": [
- "pages/home/home",
- "pages/message/message",
- "pages/contact/contact"
- ],
- 【3】配置导航栏的效果
- "window": {
- "backgroundTextStyle": "dark",
- "navigationBarBackgroundColor": "#2b4b6b",
- "navigationBarTitleText": "本地生活",
- "navigationBarTextStyle": "white",
- "enablePullDownRefresh": true,
- "backgroundColor": "#efefef"
- },
- 【4】配置tabBar
- "tabBar": {
- "list": [{
- "pagePath": "pages/home/home",
- "text": "首页",
- "iconPath": "/common/主页2.png",
- "selectedIconPath": "/common/主页1.png"
- },
- {
- "pagePath": "pages/message/message",
- "text": "消息",
- "iconPath": "/common/消息2.png",
- "selectedIconPath": "/common/消息1.png"
- },
- {
- "pagePath": "pages/contact/contact",
- "text": "联系",
- "iconPath": "/common/联系2.png",
- "selectedIconPath": "/common/联系1.png"
- }
- ]
- }
- 【5】实现轮播图
- <!-- 轮播图区域 -->
- <swiper style="height: 350rpx;" indicator-dots="true" circular="true">
- <swiper-item wx:for="{{home.list}}" wx:key="id">
- <image src="{{item.preview}}" style="width: 100%;height: 100%;"></image>
- </swiper-item>
- </swiper>
- 【6】实现九宫格数据
- <!-- 九宫格数据 -->
- <view style="display: flex;flex-wrap: wrap;border-left: 1rpx solid #efefef;border-top: 1rpx solid #efefef;">
- <view wx:for="{{home.list}}" wx:key="id" style="width: 33.33%;height: 200rpx;display: flex;flex-direction: column;align-items: center;justify-content: center;border-right: 1rpx solid #efefef;border-bottom: 1rpx solid #efefef;box-sizing: border-box;">
- <image src="{{item.preview}}" style="width: 60rpx;height: 60rpx;"></image>
- <text style="font-size: 24rpx;margin-top: 10rpx;">{{item.name}}</text>
- </view>
- </view>
- 【7】底部图片的展示
- <!-- 图片区域 -->
- <view style="display: flex;padding: 20rpx 10rpx;justify-content: space-around;">
- <image src="{{home.list[0].preview}}" mode="widthFix" style="width: 45%;"></image>
- <image src="{{home.list[1].preview}}" mode="widthFix" style="width: 45%;"></image>
- </view>
- ***************************************************************************************************
- 发现没?当wxss融入了wxml,逻辑非常清晰,就是样式的调整而已,还不简单吗!!!!哈哈
- ***************************************************************************************************
- data: {
- home: {
- list: []
- }
- },
- selectHomeList() {
- // let thisA = this;
- wx.request({
- url: 'https://localhost/document/list_page',
- method: 'post',
- data: {
- currentPage: 1,
- pageSize: 9
- },
- success: (res) => {
- // console.log(res.data.object.data)
- this.setData({
- home: {
- list: res.data.object.data
- }
- })
- // console.log(this.data.home.list)
- }
- })
- },

****************************************************************************************************************************************************************************
- 12、页面间导航跳转
- 【1】页面之间的相互跳转
- 传统HTML:<a>链接跳转、localtion.href跳转
- *********************************************************************************************
- 小程序实现跳转的两种方式:
- @声明式导航:<navigator>
- @编程式导航:调用小程序的导航API,实现页面的跳转
- *********************************************************************************************
- <navigator url="/pages/contact/contact" open-type="switchTab" style="background-color: aqua;">跳转联系页面</navigator>
- open-type="switchTab"这个必须指定,不然不能跳转对应的tabBar页面。
- 注意点!!!!!!!!!!!!!!!!!!!!
- *********************************************************************************************
- 跳转非tabBar页面
- <navigator url="/pages/info/info" style="background-color: aqua;">跳转info页面</navigator>
- 这个自己前面用了很多了!!!!!!!!!!!!!!!
- 【2】后退导航
- <navigator open-type="navigateBack" delta="1" style="background-color: aqua;">返回上一页</navigator>
- open-type="navigateBack" 注意!!!!!!!!!!!!!!!!!!!!
- delta="1" 注意!!!!!!!!!!!!!!!!!!!!
- 【3】编程式导航
- 跳转tabBar页面:
- <button bindtap="goContact">跳转联系页面</button> 这个就是在js方法里用函数调转了
- *********************************************************************************************
- goContact() {
- wx.switchTab({ // 注意!!!!!!!!!!!!!
- url: '/pages/contact/contact',
- })
- },
- *********************************************************************************************
- 跳转到非tabBar页面
- <button bindtap="goInfo">跳转info页面</button>
- goInfo() {
- wx.navigateTo({ // 注意!!!!!!!!!!!!!
- url: '/pages/info/info',
- })
- },
- *********************************************************************************************
- 后退导航:
- <button bindtap="goBack">后退</button>
- goBack() {
- wx.navigateBack()
- },
- 感觉学会声明式就行了。
- 【4】声明式导航传参
- <navigator url="/pages/info/info?name='陈翔'&age=20">跳转到info页面</navigator>
- *********************************************************************************************
- goInfo() { // 编程式导航传参
- wx.navigateTo({ // 注意!!!!!!!!!!!!!
- url: '/pages/info/info?name='陈翔'&age=20',
- })
- },
- *********************************************************************************************
- 在onLoad中接收导航参数
- data: {
- name: '',
- age: ''
- },
- /**
- * 生命周期函数--监听页面加载
- */
- onLoad(options) {
- console.log(options) // 这里接收了
- this.setData({
- "name": options.name,
- "age": options.age
- })
- },
- *********************************************************************************************
- data: {
- query: {} // 老师还是牛批,封装的思想
- },
- /**
- * 生命周期函数--监听页面加载
- */
- onLoad(options) {
- console.log(options)
- this.setData({
- query: options // 老师还是牛批,封装的思想
- })
- },

****************************************************************************************************************************************************************************
- 13、下拉刷新
- 【1】概述
- 就是下拉开启刷新效果;
- "enablePullDownRefresh": true,
- **********************************************************************************
- 建议在页面的.json配置文件中开启"enablePullDownRefresh": true,
- {
- "usingComponents": {},
- "enablePullDownRefresh": true // 这里!!!!!!!!!!!!!!!
- }
- **********************************************************************************
- 设置样式:我是在app.json中统一配置的!!!!
- "navigationBarTextStyle": "white",
- "backgroundColor": "#efefef"
- 【2】监听页面的下拉刷新事件,主要实现下拉后count的值置为0
- <view>count的值是:{{count}}</view>
- <button bindtap="addCount">自增+1</button>
- **********************************************************************************
- onPullDownRefresh() {
- console.log("触发下拉刷新");
- this.setData({
- count: 0
- })
- },
- **********************************************************************************
- 解决下拉刷新后,没有自动关闭刷新效果的问题:
- onPullDownRefresh() {
- // console.log("触发下拉刷新");
- this.setData({
- count: 0
- })
- wx.stopPullDownRefresh() // !!!!!!!!!!!!!!!!!!这里是重点
- },

****************************************************************************************************************************************************************************
- 14、上拉加载
- 【1】上拉触底概念
- 这个操作往往是实现分页功能的。
- 【2】监听上拉触底事件
- <view style="height: 2000rpx;background-color: aqua;"></view>
- *******************************************************************************************
- // 需要做节流处理,访问非法的数据请求
- onReachBottom() {
- console.log("触发了上拉触底事件")
- },
- *******************************************************************************************
- 配置上拉触底的距离,一般不需要配置
- {
- "usingComponents": {},
- "onReachBottomDistance": 100
- }
- 【3】上拉触底案例介绍
- 定义获取随机颜色的方法-在页面加载时获取初始数据-渲染UI结构美化页面效果
- -在上拉触底时调用获取随机颜色的方法-添加loading提示效果-对上拉触底节流
- *******************************************************************************************
- data: {
- photoList: []
- },
- getPhotoList() {
- wx.request({
- url: 'https://localhost/document/list_page',
- method: 'post',
- data: {
- currentPage: 1,
- pageSize: 18
- },
- success: (res) => {
- // console.log(res.data.object.data)
- this.setData({
- // 新旧数据拼接,得到大数组
- photoList: [...this.data.photoList, ...res.data.object.data] // 这里是个关键点
- })
- // console.log(this.data.home.list)
- }
- })
- },
- *******************************************************************************************
- 果然什么都要用自己的数据,这样才能知道底层的一些东西,是怎么用的,怎么提供的!!!!
- UI结构的渲染:
- <view wx:for="{{photoList}}" wx:key="id">
- <image src="{{item.preview}}" style="width: 100%;border-radius: 10rpx;"></image>
- </view>
- *******************************************************************************************
- 上拉触底后再次调用getPhotoList()函数
- onReachBottom() {
- // console.log("执行了")
- this.getPhotoList() // 会再次发起wx.request请求
- },
- *******************************************************************************************
- 添加loading效果
- getPhotoList() {
- wx.showLoading({
- title: '数据加载中...', // 本地的网络太好了,效果一闪而过
- })
- wx.request({
- url: 'https://localhost/document/list_page',
- method: 'post',
- data: {
- currentPage: 1,
- pageSize: 18
- },
- complete: (res) => {
- wx.hideLoading()
- },
- *******************************************************************************************
- 解决上拉处理节流的问题:!!!!!!!!!!!!!!!!!!!
- 定义节流阀--->修改loadingFlag的值--->判断loadingFlag从而实现节流(红绿灯)
- getPhotoList() { // VUE的语法也能用呀 哈哈哈哈哈!!!!!!!!!!!!
- wx.showLoading({
- title: '数据加载中...',
- })
- this.data.loadingFlag = true
- wx.request({
- url: 'https://localhost/document/list_page',
- method: 'post',
- data: {
- currentPage: 1,
- pageSize: 18
- },
- complete: (res) => {
- wx.hideLoading()
- this.data.loadingFlag = false
- },
- *******************************************************************************************
- onReachBottom() {
- // console.log("执行了")
- if (!this.data.loadingFlag) {
- this.getPhotoList()
- } else {
- return
- }
- },
- 【4】自定义编译模式
- 在普通编译-添加编译模式-里面来改变,方便直接看当前修改页面的效果!!!!!!!
- 提高开发效率是最根本的目的!!!!!!!!!!!!!

****************************************************************************************************************************************************************************
- 15、生命周期函数
- 【1】概述
- 生命周期:创建---运行---销毁的整个阶段。强调的是一个时间段。
- *****************************************************************************************
- 小程序从开始运行,到程序结束关闭的阶段。
- 【2】分类
- 应用生命周期:小程序的启动-运行-销毁的过程
- 页面生命周期:页面的加载---渲染---销毁的过程
- 应用生命周期>页面生命周期
- 小程序启动---页面A的生命周期---页面B的生命周期---...---小程序结束
- 【3】生命周期函数
- 作用:允许程序员在特定的时间点,执行某些特定的操作
- onLoad:页面初始化数据
- 生命周期函数:强调的是时间点。
- 【4】生命周期函数分类:
- 应用的生命周期函数、页面的生命周期函数
- 应用的生命周期函数
- *******************************************************************************************
- 需要再app.js中声明:
- onLaunch、onShow、onHide
- console.log("触发了onLaunch...")
- *******************************************************************************************
- onShow 从手机进入小程序
- onHide 从手机退出小程序
- 【5】页面声明周期函数
- onLoad() // 初始化页面 仅调用一次!!!!!!!!!!!!!!!!!
- onShow() // 页面展示
- onReady() // 初次渲染完毕后,可以修改页面的UI结构了!!!!!!!!
- onHide()// 页面被隐藏了
- onUnload()// 一个页面调用一次
- 【6】wxs脚本概述
- wxs典型应用场景是”过滤器“
- *******************************************************************************************
- wxs类似于js,不支持ES6及以上语法、wxs遵循了CommonJS规范
- *******************************************************************************************
- wxs内嵌使用语法:可以内嵌到wxml中
- 可以用于封装方法呀 感觉!!!!!!!!!!!
- <!--pages/message/message.wxml-->
- <text>pages/message/message.wxml</text>
- <view>count的值是:{{count}}</view>
- <button bindtap="addCount">自增+1</button>
- {{name}}
- {{m1.toUpperCase(name)}} // 使用!!!!!!!!!!!!!!!!
- <wxs module="m1"> // 定义!!!!!!!!!!!!!!!!!!!
- module.exports.toUpperCase = function (str) {
- return str.toUpperCase()
- }
- </wxs>
- *******************************************************************************************
- 定义外联的wxs脚本!!!!!!!!!!!!!!!!!!!!!!
- /* tools.wxs */
- function toUpperCase(str) {
- return str.toUpperCase()
- }
- module.exports = {
- toUpperCase: toUpperCase // 和VUE不一样,不能使用简写!!!!!!!!!!
- }
-
- <!--pages/message/message.wxml-->
- <text>pages/message/message.wxml</text>
- <view>count的值是:{{count}}</view>
- <button bindtap="addCount">自增+1</button>
- {{name}}
- {{m1.toUpperCase(name)}}
-
- <wxs src="../../utils/tools.wxs" module="m1"></wxs> // !!!!!!!!!!这里是重点
- *******************************************************************************************
- wxs特点,wxs和js是两种语言。
- wxs典型场景就是过滤器,要配合胡子语法使用!!!!!!有很大局限性呀
- 隔离性:wxs运行环境和其他js代码是隔离的
- wxs不能调用js中定义的函数,也不能调用小程序提供的API
- 性能好:iOS上而已,会快2-20倍,在安卓上一样。

****************************************************************************************************************************************************************************
- 16、本地生活案例扩展
- 【1】完成列表页面的开发
- 效果:页面导航传参---上拉触底---下拉刷新
- ***************************************************************************************
- <!-- 九宫格数据 -->
- <view style="display: flex;flex-wrap: wrap;border-left: 1rpx solid #efefef;border-top: 1rpx solid #efefef;">
- <navigator url="/pages/beauty_list/beauty_list?id={{item.id}}&name={{item.name}}" wx:for="{{home.list}}" wx:key="id" style="width: 33.33%;height: 200rpx;display: flex;flex-direction: column;align-items: center;justify-content: center;border-right: 1rpx solid #efefef;border-bottom: 1rpx solid #efefef;box-sizing: border-box;">
- <image src="{{item.preview}}" style="width: 60rpx;height: 60rpx;"></image>
- <text style="font-size: 24rpx;margin-top: 10rpx;">{{item.name}}</text>
- </navigator>
- </view>
- 导航+传参navigator url="/pages/beauty_list/beauty_list?id={{item.id}}&name={{item.name}}"
- ***************************************************************************************
- 动态设置页面的标题
- data: {
- query: {}
- },
- ***************************************************************************************
- onLoad(options) {
- // console.log(options)
- this.data.query = options; // 还是我牛批 三步走!!!!!!说明可以用this.data.query来赋值
- },
- ***************************************************************************************
- onReady() {
- wx.setNavigationBarTitle({
- title: this.data.query.name,
- })
- },
- ***************************************************************************************
- query: {}, // 重新定义包装数据类型 // 神经百战才知道结构化和统一性的重要性!!!!!!!!!!!!
- // 要不统一改写自己的VUE项目吧,感觉肯定是获益匪浅!!!!!!!!!!!!!!
- list: [],
- sendData: {
- currentPage: 1, // 这里都是和服务器对应的
- pageSize: 9
- },
- sendDataForm: {
- total: 0
- },
- returnData: {}
- ***************************************************************************************
- 事实证明: 更靠谱点 卧槽 emmm
- this.setData({
- list: res.data.object.data
- })
- 可以优化,但是不要玩火!!!!!!!!!!!!
- 【2】列表页面的开发
- list: [...this.data.list, ...res.data.object.data], 这个写法需要注意下!!!!!!!!
- ***************************************************************************************
- 排查了一圈,感觉自己的后端逻辑代码真牛皮。
- <!--pages/beauty_list/beauty_list.wxml-->
- <!-- <text>pages/beauty_list/beauty_list.wxml</text> -->
- <view wx:for="{{list}}" wx:key="id" style="display: flex;padding: 15rpx;border: 1rpx solid #efefef;margin:15rpx;border-radius: 8rpx;box-shadow: 1rpx 1rpx 15rpx #ddd;">
- <view>
- <image src="{{item.preview}}" style="width: 250rpx;height:250rpx;display: block;margin-right: 15rpx;"></image>
- </view>
- <view style="display: flex;flex-direction: column;justify-content: space-around;font-size: 24rpx;">
- <text style="font-weight: bold;">名称:{{item.name}}</text>
- <text>大小:{{item.size}}</text>
- <text>类型:{{item.type}}</text>
- <text>MD5:{{item.md5}}</text>
- </view>
- </view>
- ***************************************************************************************55集0分钟
- 实现加载中效果!!!!!!!!!!!!!!!!
- wx.showLoading({
- title: '数据加载中...',
- })
- complete: () => {
- wx.hideLoading()
- },
- ***************************************************************************************
- 上拉触底的分页加载效果:
- onReachBottom() {
- // console.log("执行了")
- this.data.sendData.currentPage = this.data.sendData.currentPage + 1
- console.log(this.data.sendData) // 我搞的好,当超过3也的时候,会不断加载第一页
- this.selectList()
- },
- ***************************************************************************************
- 定义节流阀
- loadingFlag: false
- selectList() {
- // let thisA = this;
- this.data.loadingFlag = true
- wx.showLoading({
- title: '数据加载中...',
- })
- wx.request({
- url: 'https://localhost/document/list_page',
- method: 'post',
- data: this.data.sendData,
- complete: () => {
- wx.hideLoading()
- this.data.loadingFlag = false
- },
- onReachBottom() {
- // console.log("执行了")
- if (!this.data.loadingFlag) {
- this.data.sendData.currentPage = this.data.sendData.currentPage + 1
- console.log(this.data.sendData)
- } else {
- return false
- }
- this.selectList()
- },
- Network下网络改成slow 3G可以模拟出效果
- 【3】分页问题的处理
- 如果只有3页,会发送为第4 5页的请求吗?
- 自己虽然牛批,但是还需要处理重复的数据的.....
- ***************************************************************************************
- 页码值*每页数据>=总页数了,就没有下一页了!!!!牛批!!!哥哥
- if (this.data.sendData.currentPage * this.data.sendData.pageSize >= this.data.returnData.total) {
- // 证明没有下一页了
- return wx.showToast({
- title: '数据加载完毕!',
- icon: "none"
- })
- }
- ***************************************************************************************
- 启动下拉刷新
- {
- "usingComponents": {},
- "enablePullDownRefresh": true // !!!!!!!!!!!!!!!!
- }
- *****************************************
- onPullDownRefresh() {
- // 下拉刷新充值关键数据
- this.data.sendData.currentPage = 1
- this.data.list = []
- this.data.returnData.total = 0
- // 重新发起请求
- console.log(this.data.sendData)
- this.selectList()
- },
- *****************************************
- 解决下拉刷新不会自动关闭的问题
- complete: () => {
- wx.hideLoading()
- this.data.loadingFlag = false
- wx.stopPullDownRefresh() // 自动关闭下拉刷新的效果
- },
- 优化下*********************
- this.selectList(() => {
- wx.stopPullDownRefresh()
- })
- ********************************************
- selectList(cb) {
- // let thisA = this;
- this.data.loadingFlag = true
- wx.showLoading({
- title: '数据加载中...',
- })
- wx.request({
- url: 'https://localhost/document/list_page',
- method: 'post',
- data: this.data.sendData,
- complete: () => {
- wx.hideLoading()
- this.data.loadingFlag = false
- // wx.stopPullDownRefresh()
- cb && cb()
- },
- success: (res) => {
- // console.log(res)
- this.setData({
- list: [...this.data.list, ...res.data.object.data],
- returnData: {
- total: res.data.object.total - 0
- }
- })
- console.log(this.data.list)
- }
- })
- },
- 【4】wxs店铺手机号的处理:过滤器
- /* tools.wxs */
- function toUpperCase(str) {
- return str.toUpperCase()
- }
-
- function shortMd5(str) {
- return str.substring(0, 23)
- }
-
- module.exports = {
- toUpperCase: toUpperCase,
- shortMd5: shortMd5
- }
- *****************************************************************
- <view style="display: flex;flex-direction: column;justify-content: space-around;font-size: 24rpx;">
- <text style="font-weight: bold;">名称:{{item.name}}</text>
- <text>大小:{{item.size}}</text>
- <text>类型:{{item.type}}</text>
- <text>MD5:{{tools.shortMd5(item.md5)}}</text>
- </view>
- </view>
-
- <wxs src="../../utils/tools.wxs" module="tools"></wxs>
- 真能实现我的md5缩减功能,牛批,过滤手机电话号码,应该是一样的
- 【5】总结
- 导航跳转、下拉刷新、上拉加载更多、知道小程序的生命周期函数

****************************************************************************************************************************************************************************
- 17、自定义组件
- 【1】创建组件
- 在componets--->test文件夹--->新建Component
- 组件也是对应4个文件:.js、.json、.wxml和.wxss
- 每个组件建议存在单独的目录中,如test1组件 test2组件,创建Component选项
- 【2】组件的应用
- 局部引用、全局引用!
- {
- "usingComponents": {
- "test1": "/components/test1/test1"
- }
- }
- ********************************************************************************************
- 直接使用即可!!!!!感觉VUE使用还行,小程序有点杀鸡用牛刀的感觉吧
- <!-- home.wxml -->
- <test1></test1>
- 【3】全局引用
- 在app.json里 和pages平级,增加配置,即可
- "usingComponents": {
- "test1": "/components/test1/test1"
- }
- 【4】全局引用与局部引用的使用场景!
- 如果会在多个页面,建议全局引用。
- 如果只在少数页面使用,建议使用局部引用。
- 【5】组件和页面的区别?
- @组件的test1.json中必须有个字段, "component": true,
- @组件的test1.js中,调用的是Component函数
- @组件的函数,需要定义到methods节点中,和VUE一样了!!!!!
- 【6】组件的样式隔离 63集 0分钟(数据记录 三方管理继续修改)

****************************************************************************************************************************************************************************
- 17、自定义组件
- 【1】创建组件
- 在componets--->test文件夹--->新建Component
- 组件也是对应4个文件:.js、.json、.wxml和.wxss
- 每个组件建议存在单独的目录中,如test1组件 test2组件,创建Component选项
- 【2】组件的应用
- 局部引用、全局引用!
- {
- "usingComponents": {
- "test1": "/components/test1/test1"
- }
- }
- ********************************************************************************************
- 直接使用即可!!!!!感觉VUE使用还行,小程序有点杀鸡用牛刀的感觉吧
- <!-- home.wxml -->
- <test1></test1>
- 【3】全局引用
- 在app.json里 和pages平级,增加配置,即可
- "usingComponents": {
- "test1": "/components/test1/test1"
- }
- 【4】全局引用与局部引用的使用场景!
- 如果会在多个页面,建议全局引用。
- 如果只在少数页面使用,建议使用局部引用。
- 【5】组件和页面的区别?
- @组件的test1.json中必须有个字段, "component": true,
- @组件的test1.js中,调用的是Component函数
- @组件的函数,需要定义到methods节点中,和VUE一样了!!!!!
- 【6】组件的样式隔离 63集 0分钟(数据记录 三方管理继续修改)
- 组件样式有隔离的特性:页面不会影响组件,组件不会影响页面
- ***************************************************************************************
- 组件样式隔离的注意点:全局样式声明的样式表对组件是无效的。(仅是类选择器)
- .g_red_text {
- color: red;
- }
- <text class="g_red_text">components/test1/test1.wxml</text>
- ***************************************************************************************
- 只有这样才有效
- <text style="color: green;">components/test1/test1.wxml</text>
- ***************************************************************************************
- 所以使用的使用建议使用类选择器,这样能样式隔离,我更懒,我就用style,嘿嘿嘿...
- ***************************************************************************************
- 修改组件的样式隔离选项:
- Component({
- options: {
- styleIsolation: 'apply-shared' // isolated默认 apply-shared页面影响组件 shared 双向影响
- },
- 这时候页面就影响组件了:
- <text class="allRed">components/test1/test1.wxml</text>
- 就是样式的额变化,没有必要这么玩,都搞迷糊了,卧槽!!!!!!!!!!!!!!!
- 【7】自定义组件-数据方法和属性
- data: {
- name: '组件'
- },
- ***************************************************************************************
- _myShowToast() {
- wx.showToast({
- title: 'name的值:' + this.data.name,
- icon: 'none'
- })
- }
- 只要是自己定义的函数都以_开头。
- methods: {
- addPoint() {
- this.setData({
- name: this.data.name + '.'
- })
- this._myShowToast()
- },
- _myShowToast() {
- wx.showToast({
- title: 'name的值:' + this.data.name,
- icon: 'none'
- })
- }
- }
- ***************************************************************************************
- <!--components/test1/test1.wxml-->
- <text>components/test1/test1.wxml</text>
- <view>
- name的值是:{{name}}
- </view>
- <button bindtap="addPoint">给name加.</button>
- ***************************************************************************************
- 就是VUE的prop卧槽,现在才明白!!!!!!!!!!!!!!!!!!!!
- properties: {
- max: {
- type: Number,
- value: 10 // 默认值
- },
- min: Number // 简化形式
- },
- ***************************************************************************************
- <!--components/test1/test1.wxml-->
- <text>components/test1/test1.wxml</text>
- <view>
- name的值是:{{name}}
- </view>
- <button bindtap="addPoint">给name加.</button>
- 我的prop是:{{max}} {{min}} !!!!!!!!!!!!!!!
- ***************************************************************************************
- <!-- home.wxml -->
- <test1 max="5" min='2'></test1>
- ***************************************************************************************
- 展示的是我的prop是: 5 2 ,懂了吧!!!!!!!!!!!!!!!!!!!
- methods: {
- addPoint() {
- if (this.data.count >= this.properties.max) { //控制自增最大值!!!!!!!!!!!!
- return false
- }
- this.setData({
- count: this.data.count + 1
- })
- this._myShowToast()
- },
- _myShowToast() {
- wx.showToast({
- title: 'count的值:' + this.data.count,
- icon: 'none'
- })
- }
- }
- ***************************************************************************************
- data和properties的区别:小程序里都差不多。
- data存储私有数据,properties是外界传过来的数据,两者都是可读可写的。
- this.data.xxx
- this.properties.xxx 注意下使用的区别!!!!!!!!!!!!!!!!
- ***************************************************************************************
- setData修改properties的值
- this.setData({
- count: this.data.count + 1,
- min: this.properties.min - 1 // !!!!!!!!!!注意是this.properties哦!!!!!
- })
- 【8】自定义组件-数据监听器
- 类似VUE里的watch侦听器
- observers: {
- 'count,min': function name(count, min) {
- console.log("count的值发生变化:" + count + "---" + min)
- }
- }
- 说明不仅能监控data,还能监控properties,卧槽 卧槽 好屌呀
- ***************************************************************************************
- 监听器监听对象属性的变化:
- observers: {
- 'person.name,person.age': function name(name, age) {
- console.log("person属性的值发生变化:" + name + "---" + age)
- }
- }
- ***************************************************************************************
- 数据监听器案例:
- <!--components/test1/test1.wxml-->
- <text>components/test1/test1.wxml</text>
- <view style="background-color: rgb({{fullColor}});line-height: 200rpx;font-size: 24rpx;color: white;text-shadow: 0rpx 0rpx 2rpx black;text-align: center;">
- 颜色值:{{fullColor}}
- </view>
- <button size="mini" bindtap="changeR" type="default"></button>
- <button size="mini" bindtap="changeG" type="primary"></button>
- <button size="mini" bindtap="changeB" type="warn"></button>
- ***************************************************************************************
- // components/test1/test1.js
- Component({
- /**
- * 组件的初始数据
- */
- data: {
- rgb: {
- r: 0,
- g: 0,
- b: 0
- },
- fullColor: '0,0,0'
- },
-
- /**
- * 组件的方法列表
- */
- methods: {
- changeR() {
- this.setData({
- 'rgb.r': this.data.rgb.r + 5 > 255 ? 255 : this.data.rgb.r + 5 // 看看对象的赋值
- })
- },
- changeG() {
- this.setData({
- 'rgb.g': this.data.rgb.g + 5 > 255 ? 255 : this.data.rgb.g + 5 // 看看对象的赋值
- })
- },
- changeB() {
- this.setData({
- 'rgb.b': this.data.rgb.b + 5 > 255 ? 255 : this.data.rgb.b + 5 // 看看对象的赋值
- })
- },
- },
- observers: {
- 'rgb.r,rgb.g,rgb.b': function name(r, g, b) {
- this.setData({
- fullColor: `${r},${g},${b}`
- })
- }
- }
- })
- ***************************************************************************************
- 对象监控的优化:!!!!!!!!!!!!!!!!!对象.**
- observers: {
- 'rgb.**': function name(obj) {
- this.setData({
- fullColor: `${obj.r},${obj.g},${obj.b}`
- })
- }
- }
- 【9】自定义组件-纯数据字段
- 什么是纯数据字段?那些不用于界面渲染的data字段,比如r g b就是纯数据字段。
- ***************************************************************************************
- 纯数据字段能够提升页面更新的性能。
- ***************************************************************************************
- 怎么定义?
- options: {
- pureDataPattern: /^_/ // 凡是以_开头的都是纯数据字段
- },
- data: {
- _a: true, // 纯数据字段
- ***************************************************************************************
- 全局改造!!!!!!!!!!!!!!!!!!提升性能!!!!!!!!!!
- // components/test1/test1.js
- Component({
- /**
- * 组件的初始数据
- */
- options: {
- pureDataPattern: /^_/ // 凡是以_开头的都是纯数据字段
- },
- data: {
- _rgb: {
- r: 0,
- g: 0,
- b: 0
- },
- fullColor: '0,0,0'
- },
-
- /**
- * 组件的方法列表
- */
- methods: {
- changeR() {
- this.setData({
- '_rgb.r': this.data._rgb.r + 5 > 255 ? 255 : this.data._rgb.r + 5
- })
- },
- changeG() {
- this.setData({
- '_rgb.g': this.data._rgb.g + 5 > 255 ? 255 : this.data._rgb.g + 5
- })
- },
- changeB() {
- this.setData({
- '_rgb.b': this.data._rgb.b + 5 > 255 ? 255 : this.data._rgb.b + 5
- })
- },
- },
- observers: {
- '_rgb.**': function name(obj) {
- this.setData({
- fullColor: `${obj.r},${obj.g},${obj.b}`
- })
- }
- }
- })
- 【10】组件的生命周期
- created:常用
- attached:常用
- ready
- moved
- detached:常用
- error
- ***************************************************************************************
- 主要的生命周期函数:
- created 组件示例刚创建好的时候,这时候还不能使用setData
- attached 这时候setData可以执行,可以进行初始化数据
- detached 组件被销毁的时候,适合做一些清理性质的工作
- ***************************************************************************************
- 如何定义组件的生命周期函数:
- lifetimes节点:(新的方式,推荐的)
- // components/test1/test1.js
- Component({
- data: {},
- /**
- * 组件的方法列表
- */
- lifetimes: {
- created() {
- console.log('created 执行')
- },
- attached() {
- console.log('attached 执行')
- }
- },
- methods: {},
- })
- 【11】自定义组件-组件所在!!!“页面”!!!的生命周期函数
- 例如:每当触发页面show生命周期函数时,希望生成一个随机的RGB颜色值
- ***************************************************************************************
- 组件所在页面的声明周期函数有3个:show hide resize
- ***************************************************************************************
- pageLifetimes节点:
- // components/test1/test1.js
- Component({
- data: {},
- /**
- * 组件的方法列表
- */
- pageLifetimes: { // 所在页面的生命周期函数
- show() {
- console.log("show 执行")
- },
- hide() {
- console.log("hide 执行")
- },
- resize() {
- console.log("resize 执行")
- }
- },
- methods: {},
- })
- ***************************************************************************************
- // components/test1/test1.js 这个是我自己实现的呦!!!!!!!!!!!!!!!
- Component({
- data: {
- _rgb: {
- r: 0,
- g: 0,
- b: 0
- },
- fullColor: '0,0,0'
- },
- /**
- * 组件的方法列表
- */
- pageLifetimes: { // 所在页面的生命周期函数
- show() {
- console.log("show 执行")
- this._randomColor()
- },
- hide() {
- console.log("hide 执行")
- },
- resize() {
- console.log("resize 执行")
- }
- },
- methods: {
- _randomColor() {
- this.setData({
- _rgb: {
- r: Math.floor(Math.random() * 256),
- g: Math.floor(Math.random() * 256),
- b: Math.floor(Math.random() * 256),
- },
- })
- this.setData({
- fullColor: this.data._rgb.r + ',' + this.data._rgb.g + ',' + this.data._rgb.b
- })
- // console.log(this.data.fullColor)
- }
- },
- })
- 【12】自定义组件-插槽
- 什么是插槽?用于承载!!!!组件使用者!!!提供的wxml结构。
- <slot></slot>
- 好像VUE也没怎么用过,鸡肋
- ***************************************************************************************
- 单个插槽:
- <!--components/test1/test1.wxml-->
- <view>
- <view>这是组件的内部节点</view>
- <slot></slot>
- </view>
- ***************************************************************************************
- <test1>
- <view style="color: red;">这里是插入到slot中的content</view>
- </test1>
- ***************************************************************************************
- 启用多个插槽
- options: {
- multipleSlots: true // 启用多个插槽
- },
- ***************************************************************************************
- 多个要给slot 加name属性加以区分
- <!--components/test1/test1.wxml-->
- <view>
- <slot name="one"></slot>
- <view>这是组件的内部节点</view>
- <slot name="two"></slot>
- </view>
- ***************************************************************************************
- <test1>
- <view style="color: red;" slot="one">这里是插入到slot one中的content</view>
- <view style="color: red;" slot="two">这里是插入到slot two中的content</view>
- </test1>
- 【13】父子组件之间的通信
- 三种方式:属性绑定(父-子) 事件绑定(子-父) 获取组件实例
- ***************************************************************************************
- 属性绑定!!!!!!!!!!!:home首页是父组件 test1是子组件!!!!!!!!!!!
- <!-- home.wxml -->
- <view>父组件中count的值:{{count}}</view>
- <!-- 组件 -->
- <test1 count="{{count}}">子组件:</test1>
- *****************************************
- data: { // 父组件
- count: 0
- },
- ***************************************************************************************
- 子组件接收:使用
- properties: {
- count: Number
- },
- *****************************************
- <!--components/test1/test1.wxml-->
- <view>
- 我是子组件~~~~~~~~count的值是:{{count}}
- </view>
- *****************************************
- 子组件自增+1
- addCount() {
- this.setData({
- fff_son_count: this.properties.fff_son_count + 1
- })
- }
- *****************************************
- 发现子组件是变化了,但是父组件没变化,所以要实现子组件向父组件传值:事件绑定!!!!!
- ***************************************************************************************
- 事件绑定!!!!!!!!!!!!!!!!!!!!!!!!!!!!!子传父
- 父组件js定义函数
- // 供子组件调用的函数
- son_fff_count() {
- console.log("son_fff_count")
- },
- *****************************************
- <test1 fff_son_count="{{count}}" bind:son_fff_count="son_fff_count">子组件:</test1>
- *****************************************
- this.triggerEvent("son_fff_count")
- *****************************************
- this.triggerEvent("son_fff_count", {
- value: this.properties.fff_son_count // 传递的值
- })
- *****************************************
- // 供子组件调用的函数
- son_fff_count(e) {
- console.log("son_fff_count " + e.detail.value)
- this.setData({
- count: e.detail.value
- })
- },
- ***************************************************************************************
- 至此就实现了父传子、子传父了,牛批!!!!!!!!!!!!!!!
- ***************************************************************************************
- 获取组件实例实现父子组件的通信!!!!!!!!!!
- 建议使用id选择器:
- <test1 fff_son_count="{{count}}" bind:son_fff_count="son_fff_count" id="sonTest1">子组件:</test1>
- <!-- 通过获取实例 -->
- <button bindtap="getSon">获取子组件实例</button>
- ***************************************************************************************
- getSon() {
- const test1 = this.selectComponent("#sonTest1")
- console.log(test1)
- test1.setData({ // 直接操作子组件
- fff_son_count: test1.properties.fff_son_count + 1
- })
- },

****************************************************************************************************************************************************************************
- 18、behaviors作用
- 【1】概念
- 用于实现组件间代码共享的特性,类似vue.js中的mixins,类java的静态变量呀。
- ***********************************************************************************
- 每一个组件可以引用多个behavior,behavior也可以引用其他behavior
- 【2】behavior的创建
- module.exports = Behavior({
- data: {
- name: '陈翔'
- },
- properties: {
-
- },
- methods: {
-
- }
- })
- 【3】导入并使用behavior
- // components/test1/test1.js
- const my_behavior = require('../../behaviors/my_behavior.js')
-
- Component({
- behaviors: [my_behavior],
- ***********************************************************************************
- 使用:
- <view>
- 在behavior中定义的用户名是:{{name}}
- </view>
- 【4】behavior中所有可用的节点
- properties、data、methods、behaviors(引入其他behavior的作用)
- ***********************************************************************************
- 同名字段的覆盖和组合规则。这也太low了
- 【5】组件-总结
- 创建并引用组件 usingComponents
- ***********************************************************************************
- 修改组件的样式隔离选项
- ***********************************************************************************
- 如何定义和使用数据监听器
- ***********************************************************************************
- 能够知道如何定义和使用纯数据字段
- ***********************************************************************************
- 知道实现组件父子通信有哪3中方式
- ***********************************************************************************
- 知道定义和使用behaviors

****************************************************************************************************************************************************************************
- 19、vant-weapp组件库
- 【1】小程序对npm的支持与限制
- 不支持依赖Node.js内置库的包...
- 不支持依赖浏览器内置对象的包...
- 不支持依赖C++插件的包...
- 【2】使用npm安装Vant Weapp的包
- 是有赞前端团队开源的UI组件库,类似于ElementUI。是MIT协议
- ***************************************************************************************
- 安装Vant组件库
- 在目录结构空白处-右击-在外部窗口中打开!!!!!!!!!!!!!!!
- npm i @vant/weapp@1.3.3 -S --production
- 工具---构建npm
- 修改app.json "style": "v2", 去掉
- ***************************************************************************************
- 使用Vant组件
- app.json配置
- "usingComponents": {
- "vant_button": "@vant/weapp/button/index"
- },
- -------------------------------------------------------------------
- <vant_button type="primary">vant按钮</vant_button>
- <vant_button type="info">vant按钮</vant_button>
- <vant_button type="warning">vant按钮</vant_button>
- <vant_button type="danger">vant按钮</vant_button>
- 【3】vant weapp定制全局主题样式
- /**app.wxss**/
- page {
- --button-danger-background-color: #C00000;
- --button-danger-border-color: #D60000;
- }
- 这就可以了!!!!!!!!!!!!!!!!!!

****************************************************************************************************************************************************************************
- 20、MobX实现全局数据共享
- 【1】什么是全局数据共享?
- Vuex Redx Mobx 更强大的组件间的数据传递
- ***************************************************************************************
- mobx-miniprogram来创建save示例对象
- mobx-miniprogram-bindings 把save中的共享数据或方法,绑定到组件或页面中使用
- ***************************************************************************************
- npm i --save mobx-miniprogram@4.13.2 mobx-miniprogram-bindings@1.2.1
- -------------------------------------------------------------------------------------
- 删除miniprogram_npm,然后执行工具---npm构建
- 【2】创建Mbox save实例
- // 在这里js中专门创建save实例对象
- import {
- observable
- } from 'mobx-miniprogram'
-
- export const save = observable({
- saveName: '陈翔',
- saveAge: 26
- })
- ***************************************************************************************
- // 在这里js中专门创建store实例对象
- import {
- action,
- observable
- } from 'mobx-miniprogram'
-
- export const store = observable({
- storeName: '陈翔',
- storeAge: 26,
- // 定义计算属性
- get add() { // add就是计算属性的名字
- return this.storeAge + 1
- },
- // 定义全局方法修改save里的数据
- updateStoreAge: action(function (step) {
- this.storeAge = this.storeAge + step
- })
- })
- 【3】如何将save里的成员绑定到页面中?
- // pages/message/message.js
- import {
- createStoreBindings
- } from 'mobx-miniprogram-bindings'
- import {
- store
- } from '../../store/store'
- -------------------------------------------------------------------------------------
- onLoad(options) {
- this.saveBindings = createStoreBindings(this, {
- save,
- fields: ['saveName', 'saveAge'],
- actions: ['updateSaveAge']
- })
- },
- onUnload() {
- this.saveBindings.destroyStoreBindings()
- },
- 【4】在页面上使用save里的成员
- <view>
- {{storeName}} {{storeAge}}
- </view>
- <vant_button type="primary" bindtap="saveAgeAdd">storeAge+1</vant_button>
- <vant_button type="danger" bindtap="saveAgeReduce" data-step="{{-2}}">storeAge-2</vant_button>
- -------------------------------------------------------------------------------------
- saveAgeAdd() {
- // console.log("saveAgeAdd")
- this.updateStoreAge(1)
- },
- saveAgeReduce(e) {
- // console.log(e)
- this.updateStoreAge(e.target.dataset.step)
- },
- 【5】将store中的成员绑定到组件中
- app.json:
- "usingComponents": {
- "vant_button": "@vant/weapp/button/index",
- "test_component": "components/test_component"
- },
- -------------------------------------------------------------------------------------
- // components/test_component.js
- import {
- storeBindingsBehavior
- } from 'mobx-miniprogram-bindings'
- import {
- store
- } from '../store/store'
- // 使用
- Component({
- behaviors: [storeBindingsBehavior],
- storeBindings: {
- store,
- fields: {
- storeName: () => store.storeName, // 第一种
- storeAge: (store) => store.storeAge, // 第二种
- add: 'add' // 绑定字段的第三种方式
- },
- actions: {
- updateStoreAge: 'updateStoreAge'
- }
- },
- properties: {},
- data: {},
- methods: {
- saveAgeAdd() {
- // console.log("saveAgeAdd")
- this.updateStoreAge(1)
- },
- saveAgeReduce(e) {
- // console.log(e)
- this.updateStoreAge(e.target.dataset.step)
- },
- }
- })
- -------------------------------------------------------------------------------------
- <!--components/test_component.wxml-->
- <text>components/test_component.wxml</text>
- <view>~~~~~~~~~~~~~~~~~~~~~分割</view>
- <view>
- {{storeName}} {{storeAge}}
- </view>
- <vant_button type="primary" bindtap="saveAgeAdd">storeAge+1</vant_button>
- <vant_button type="danger" bindtap="saveAgeReduce" data-step="{{-2}}">storeAge-2</vant_button>

****************************************************************************************************************************************************************************
- 21、API实现Promise化
- 【1】什么是API Promise化?
- 通过额外的配置,升级改造为Promise API,提高代码可读性
- 【2】具体配置与使用
- npm i --save miniprogram-api-promise@1.0.4
- ----------------------------------------------------------------------------------------
- 工具-npm构建 这一步不要忘记了!!!!!!!!!!!!!!
- 可以先删除miniprogram_npm,然后再构建,避免构建出现问题。
- ****************************************************************************************
- 使用:
- // app.js
- import { promisifyAll } from 'miniprogram-api-promise'
- const wxp = wx.p = { }
- promisifyAll(wx, wxp)
- ----------------------------------------------------------------------------------------
- async selectList() {
- const {data:res} = await wx.p.request({
- method: 'post',
- url: 'https://localhost/document/list_page',
- data: this.data.sendData,
- })
- console.log(res)
- },
- ----------------------------------------------------------------------------------------
- 不好意思,用不习惯,emmmm

****************************************************************************************************************************************************************************
- 22、分包
- 【1】概念
- 分包是把一个完整的小程序,划分为不同的子包,在构建时打包成不同的分包,让用户在使用的时候
- 可以按需加载。
- ***********************************************************************************************
- 优点:优化小程序首次启动的下载时间,在多人共同开发的时候更高效、解耦写作
- 【2】分包前项目的构成
- 分包前项目过大:所有页面+公共资源
- ***********************************************************************************************
- 分包后:
- 主包:项目启动页面或TabBar页面,以及分包都需要的一些公共资源
- 分包:只包含当前分包有关的页面和私有资源 N个分包
- 【3】分包的加载规则
- tabBar肯定放在主包...
- -----------------------------------------------------------------------------------------------
- 非tabBar页面可以按照功能的不同,划分为不同的包,进行按需下载
- 【4】分包的体积限制
- 整个小程序主包+分包不能超过16M
- -----------------------------------------------------------------------------------------------
- 单个分包/主包不能超过2M
- 【5】配置使用分包
- 在app.json里的subpackage节点中声明分包的结构
- ***********************************************************************************************
- "subpackages": [{
- "root": "pkgA",
- "pages": [
- "pages/cat/cat",
- "pages/dog/dog"
- ]
- }, {
- "root": "pkgB",
- "pages": [
- "pages/apple/apple",
- "pages/orange/orange"
- ]
- }],
- ***********************************************************************************************
- 起别名:!!!!!!!!!!!!!!!!!!!
- "subpackages": [{
- "root": "pkgA",
- "name": "p1",
- "pages": [
- "pages/cat/cat",
- "pages/dog/dog"
- ]
- }, {
- "root": "pkgB",
- "name": "p2",
- "pages": [
- "pages/apple/apple",
- "pages/orange/orange"
- ]
- }],
- ***********************************************************************************************
- 在详情-基本信息-本地代码-可以看到每个包的大小
- ***********************************************************************************************
- 分包的打包原则:
- @ subpackages分包之外的,都会被打包的主包里面!!!!!!!!!!!!!!
- @ 主包也有自己的pages
- @ tabBar页面必须在主包内
- @ 分包之间不能互相嵌套
- ***********************************************************************************************
- 分包的引用原则:
- @ 主包无法引用分包内的私有资源
- @ 分包之间不能相互引用私有资源
- @ 分包可以引用主包内的公共资源!!!!!!!!!!!!!!!!!!!!!!!!!!!
- 【6】独立分包
- 可以独立于主包和分包独立运行!!!!
- 感觉像是另一个入口,emmmm
- @ 特点就是是否需要依赖主包才能运行
- ***********************************************************************************************
- 独立分包的应用场景:
- @ 独立分包不依赖主包即可运行,提升分包页面的启动速度。
- 注意: 一个小程序可以有多个独立分包
- ***********************************************************************************************
- 独立分包的配置方法:
- , {
- "root": "pkgC",
- "name": "p3",
- "pages": [
- "pages/beauty/beauty",
- "pages/girl/girl"
- ],
- "independent": true // !!!!!!!!!!!!!!!!主要是这里
- }
- ***********************************************************************************************
- 独立分包的引用原则:
- @ 主包无法引用独立分包资源
- @ 独立分包之间无法相互引用资源
- @ 独立分包和普通分包也无法引用资源
- @ 独立分包也不能应用主包的公共资源!!!!!!!!!!!!
- 【7】分包预下载
- 在进入小程序某个页面时,框架自动预下载可能需要的分包,从而提升用户对页面的访问速度。
- ***********************************************************************************************
- 配置分包的预下载
- "preloadRule": { // !!!!!!!!!!!!这里这里这里
- "pages/contact/contact": {
- "packages": ["p1"],
- "network": "all" // 所有网络都会下载
- }
- },
- "subpackages": [{
- "root": "pkgA",
- "name": "p1",
- -----------------------------------------------------------------------------------------------
- 点击联系的时候,控制台会自动打印:
- preloadSubpackages: p1
- preloadSubpackages: success
- ***********************************************************************************************
- 分包预下载的限制:
- 同一个主包页面,享有的所有的预下载大小限额2M(总体预下载分包不能超过2M)

****************************************************************************************************************************************************************************
- 23、自定义tabBar 89集
- 【1】自定义tabBar的实现步骤
- @ 配置信息
- @ 添加tabBar代码文件
- @ 编写tabBar代码
- "tabBar": {
- "custom": true, // !!!!!!!!!!!!!!!!!!!
- "list": [{
- "pagePath": "pages/home/home",
- "text": "首页",
- "iconPath": "/common/主页2.png",
- "selectedIconPath": "/common/主页1.png"
- },
- {
- "pagePath": "pages/message/message",
- "text": "消息",
- "iconPath": "/common/消息2.png",
- "selectedIconPath": "/common/消息1.png"
- },
- {
- "pagePath": "pages/contact/contact",
- "text": "联系",
- "iconPath": "/common/联系2.png",
- "selectedIconPath": "/common/联系1.png"
- }
- ]
- }
- 【2】初步实现自定义tabBar效果
- custom-tab-bar在pages同级,然后新建index组件Component,记录哦 这个很重要!!!!!!!
- ******************************************************************************************
- 紧接着底部就出现了custom-tab-bar/index.wxml
- ******************************************************************************************
- "usingComponents": {
- "vant_button": "@vant/weapp/button/index",
- "test_component": "components/test_component",
- "van-tabbar": "@vant/weapp/tabbar/index",
- "van-tabbar-item": "@vant/weapp/tabbar-item/index"
- },
- ---------------------------------------------------------------------------------------------
- <!--custom-tab-bar/index.wxml-->
- <!-- <text>这是自定义tabBar</text> -->
- <van-tabbar active="{{ active }}" bind:change="onChange">
- <van-tabbar-item icon="home-o">标签</van-tabbar-item>
- <van-tabbar-item icon="search">标签</van-tabbar-item>
- <van-tabbar-item icon="friends-o">标签</van-tabbar-item>
- <van-tabbar-item icon="setting-o">标签</van-tabbar-item>
- </van-tabbar>
- ---------------------------------------------------------------------------------------------
- // custom-tab-bar/index.js
- // 使用
- Component({
- properties: {},
- data: {
- active: 0
- },
- methods: {
- onChange(event) { // event.detail 的值为当前选中项的索引
- this.setData({
- active: event.detail
- });
- },
- }
- })
- ******************************************************************************************
- 自定义徽标:感觉没有组件给的好看,哈哈哈哈
- <!--custom-tab-bar/index.wxml-->
- <!-- <text>这是自定义tabBar</text> -->
- <van-tabbar active="{{ active }}" bind:change="onChange">
- <van-tabbar-item info="3">
- <image slot="icon" src="/common/主页2.png" mode="aspectFit" style="width: 30px; height: 18px;" />
- <image slot="icon-active" src="/common/主页1.png" mode="aspectFit" style="width: 30px; height: 18px;" />
- 首页
- </van-tabbar-item>
- <van-tabbar-item icon="home-o">标签</van-tabbar-item>
- <van-tabbar-item icon="search">标签</van-tabbar-item>
- <van-tabbar-item icon="friends-o">标签</van-tabbar-item>
- <van-tabbar-item icon="setting-o">标签</van-tabbar-item>
- </van-tabbar>
- ---------------------------------------------------------------------------------------------
- data: {
- active: 0,
- "list": [{
- "pagePath": "pages/home/home",
- "text": "首页",
- "iconPath": "/common/主页2.png",
- "selectedIconPath": "/common/主页1.png"
- },
- {
- "pagePath": "pages/message/message",
- "text": "消息",
- "iconPath": "/common/消息2.png",
- "selectedIconPath": "/common/消息1.png"
- },
- {
- "pagePath": "pages/contact/contact",
- "text": "联系",
- "iconPath": "/common/联系2.png",
- "selectedIconPath": "/common/联系1.png"
- }
- ]
- },
- ---------------------------------------------------------------------------------------------
- <!--custom-tab-bar/index.wxml-->
- <!-- <text>这是自定义tabBar</text> -->
- <van-tabbar active="{{ active }}" bind:change="onChange">
- <van-tabbar-item wx:for="{{list}}" wx:key="index">
- <image slot="icon" src="{{item.iconPath}}" mode="aspectFit" style="width: 25px; height: 25px;" />
- <image slot="icon-active" src="{{item.selectedIconPath}}" mode="aspectFit" style="width: 25px; height: 25px;" />
- {{item.text}}
- </van-tabbar-item>
- </van-tabbar>
- 【3】如何渲染出徽标
- info="2"
- ******************************************************************************************
- 处理徽标超出tabBar边界的问题:
- // custom-tab-bar/index.js
- // 使用
- Component({
- options: {
- styleIsolation: "shared" // 不开启不会生效的哈
- },
- ---------------------------------------------------------------------------------------------
- /* custom-tab-bar/index.wxss */
- .van-tabbar-item {
- --tabbar-item-margin-bottom: 0
- }
- ---------------------------------------------------------------------------------------------
- 按需渲染徽标
- {
- "pagePath": "pages/message/message",
- "text": "消息",
- "iconPath": "/common/消息2.png",
- "selectedIconPath": "/common/消息1.png",
- info: 2
- },
- ---------------------------------------------------------------------------------------------
- <!--custom-tab-bar/index.wxml-->
- <!-- <text>这是自定义tabBar</text> -->
- <van-tabbar active="{{ active }}" bind:change="onChange">
- <van-tabbar-item wx:for="{{list}}" wx:key="index" info="{{item.info?item.info:''}}">
- <image slot="icon" src="{{item.iconPath}}" mode="aspectFit" style="width: 25px; height: 25px;" />
- <image slot="icon-active" src="{{item.selectedIconPath}}" mode="aspectFit" style="width: 25px; height: 25px;" />
- {{item.text}}
- </van-tabbar-item>
- </van-tabbar>
- ******************************************************************************************
- 如何把徽标动态化? // 用store.js全局引用和修改,牛批!!!!!!!!!!!
- // custom-tab-bar/index.js
- // 使用
- import {
- storeBindingsBehavior
- } from 'mobx-miniprogram-bindings'
- import {
- store
- } from '../store/store'
- Component({
- behaviors: [storeBindingsBehavior],
- options: {
- styleIsolation: "shared"
- },
- properties: {},
- storeBindings: {
- store,
- fields: {
- changeInfo: 'changeInfo' // 全局存储的字段
- }
- },
- observers: {
- 'changeInfo': function (newVal) {
- // console.log(newVal)
- this.setData({
- 'list[1].info': newVal // 把changeInfo的最新值给到list.info
- })
- }
- },
- data: {
- active: 0,
- "list": [{
- "pagePath": "pages/home/home",
- "text": "首页",
- "iconPath": "/common/主页2.png",
- "selectedIconPath": "/common/主页1.png"
- },
- {
- "pagePath": "pages/message/message",
- "text": "消息",
- "iconPath": "/common/消息2.png",
- "selectedIconPath": "/common/消息1.png",
- info: 2
- },
- {
- "pagePath": "pages/contact/contact",
- "text": "联系",
- "iconPath": "/common/联系2.png",
- "selectedIconPath": "/common/联系1.png"
- }
- ]
- },
- methods: {
- onChange(event) { // event.detail 的值为当前选中项的索引
- this.setData({
- active: event.detail
- });
- },
- }
- })
- 【4】如何实现tabBar页面的切换
- onChange(event) { // event.detail 的值为当前选中项的索引
- this.setData({
- active: event.detail
- });
- wx.switchTab({
- url: '/' + this.data.list[event.detail].pagePath, // 调用切换!!!!!!!!!!!!!
- })
- },
- ******************************************************************************************
- // 在这里js中专门创建save实例对象
- import {
- action,
- observable
- } from 'mobx-miniprogram'
-
- export const store = observable({
- storeName: '陈翔',
- storeAge: 26,
- changeInfo: 2,
- active: 0,
- // 修改active下标的函数
- updateActive: action(function (index) {
- this.active = index
- }),
- // 定义计算属性
- get add() { // add就是计算属性的名字
- return this.storeAge + 1
- },
- // 定义全局方法修改save里的数据
- updateStoreAge: action(function (step) {
- this.storeAge = this.storeAge + step
- this.changeInfo = this.changeInfo + step
- })
- })
- ---------------------------------------------------------------------------------------------
- 处理索引标记的问题
- // custom-tab-bar/index.js
- // 使用
- import {
- storeBindingsBehavior
- } from 'mobx-miniprogram-bindings'
- import {
- store
- } from '../store/store'
- Component({
- behaviors: [storeBindingsBehavior],
- options: {
- styleIsolation: "shared"
- },
- properties: {},
- storeBindings: {
- store,
- fields: {
- changeInfo: 'changeInfo', // 全局存储的字段
- active: 'active'
- },
- actions: {
- updateActive: 'updateActive'
- }
- },
- observers: {
- 'changeInfo': function (newVal) {
- // console.log(newVal)
- this.setData({
- 'list[1].info': newVal // 把changeInfo的最新值给到list.info
- })
- }
- },
- data: {
- "list": [{
- "pagePath": "pages/home/home",
- "text": "首页",
- "iconPath": "/common/主页2.png",
- "selectedIconPath": "/common/主页1.png"
- },
- {
- "pagePath": "pages/message/message",
- "text": "消息",
- "iconPath": "/common/消息2.png",
- "selectedIconPath": "/common/消息1.png",
- info: 2
- },
- {
- "pagePath": "pages/contact/contact",
- "text": "联系",
- "iconPath": "/common/联系2.png",
- "selectedIconPath": "/common/联系1.png"
- }
- ]
- },
- methods: {
- onChange(event) { // event.detail 的值为当前选中项的索引
- /* this.setData({
- active: event.detail
- }); */
- this.updateActive(event.detail)
- wx.switchTab({
- url: '/' + this.data.list[event.detail].pagePath,
- })
- },
- }
- })
- 【5】修改选中项文本的颜色
- <van-tabbar active="{{ active }}" bind:change="onChange" active-color="red">
- active-color="red"!!!!!!!!!!!!默认的也挺好的,噗嗤
- 【6】总结:
- @ vant-weapp组件库配置使用
- @ Mbox 就是store.js的使用
- @ 小程序的API promise化
- @ 实现自定义tabBar效果!!!!!!!!!!!!!!!!!!

****************************************************************************************************************************************************************************
- 24、小程序大项目(uni-app)
- 【1】项目概述:
- 4个tabBar
- ***********************************************************************************
- @ 商品分类
- @ 分类的布局,商品列表页面
- @ 加入购物车
- @ 收货地址
- @ 一键登录
- @ 我的页面 收货客服
- @ 支付
- 【2】uni-app概述与开放环境
- uni-app 是一个使用 Vue.js 开发所有前端应用的框架,开发者编写一套代码,可发布到
- iOS、Android、Web(响应式)、以及各种小程序(微信/支付宝/百度/头条/飞书/QQ
- /快手/钉钉/淘宝)、快应用等多个平台。卧槽 这么屌吗!!!!!!!!!!!!!!!
- ---------------------------------------------------------------------------------------------
- 基于vue.js语法的uni-app模板项目,好牛皮,可以发布小程序项目、H5、Android、iOS、etc等等....
- ***********************************************************************************
- 下载和配置uniapp开发工具:HBuilderX
- https://www.dcloud.io/hbuilderx.html
- ---------------------------------------------------------------------------------------------
- 下载后解压即可
- ---------------------------------------------------------------------------------------------
- 安装scss/sass编译插件
- https://ext.dcloud.net.cn/plugin?id=2046
- ---------------------------------------------------------------------------------------------
- 个性化配置:工具-自定义快捷键
- 【2】新建uniapp项目
- 文件---新建项目---所在位置+文件名---选择uni-ui项目
- ***********************************************************************************
- 组成结构:
- pages:所有小程序页面
- ---------------------------------------------------------------------------------------------
- static:静态资源
- ---------------------------------------------------------------------------------------------
- main.js vue的初始化入口
- ---------------------------------------------------------------------------------------------
- App.vue 配置小程序的全局样式
- ---------------------------------------------------------------------------------------------
- manifest.json
- ---------------------------------------------------------------------------------------------
- pages.json
- ---------------------------------------------------------------------------------------------
- uni.scss
- ***********************************************************************************
- 如何把uniapp项目运行到微信小程序里
- 填写微信小程序APPID---manifest.json---微信小程序配置---粘贴小程序appid
- ---------------------------------------------------------------------------------------------
- 工具-设置-运行配置---小程序运行配置---微信开发者工具路径:C:\Program Files (x86)\Tencent\微信web开发者工具
- ---------------------------------------------------------------------------------------------
- 微信-开发者工具-设置-安全-服务端口打开
- ---------------------------------------------------------------------------------------------
- 通过Hbuilder运行-运行到小程序模拟器---即可打开微信小程序开效果,我日尼玛!!!
- ***********************************************************************************
- 使用Git管理项目
- 根节点新建:.gitignore文件
- /node_modules
- /uppackage/dist
- .gitkeep
- ***********************************************************************************
- 把本地项目托管到码云
- F:\A计算机\IT01项目\4.UNIAPP\uni-shop-2\static
- cmd
- 然后执行如下命令:
- git init
- git status
- git add .
- git commit -m "init project"
- git config --global user.email "wdfgdzx@163.com"
- git config --global user.name "wdfgdzx"
- git config --global user.password "s19911009!"
- 再执行git commit -m "init project"即可!
- ---------------------------------------------------------------------------------------------
- git remote add origin https://gitee.com/wdfgdzx/uniapp.git
- git push -u origin "master"
- 推到码云:::::!!!!!!!!!!毕老师讲的简单过了 我日尼玛!!!
- ***********************************************************************************
- 配置tabBar效果
- git checkout -b tabbar 创建分支
- git branch 查看分支
- 在pages下面右击新建页面
- ***********************************************************************************
- {
- "tabBar": {
- "list": [{
- "pagePath": "pages/home/home",
- "text": "首页",
- "iconPath": "static/tab_icons/home.png",
- "selectedIconPath": "static/tab_icons/home-active.png"
- }, {
- "pagePath": "pages/cate/cate",
- "text": "分类",
- "iconPath": "static/tab_icons/cate.png",
- "selectedIconPath": "static/tab_icons/cate-active.png"
- }, {
- "pagePath": "pages/cart/cart",
- "text": "购物车",
- "iconPath": "static/tab_icons/cart.png",
- "selectedIconPath": "static/tab_icons/cart-active.png"
- }, {
- "pagePath": "pages/my/my",
- "text": "我的",
- "iconPath": "static/tab_icons/my.png",
- "selectedIconPath": "static/tab_icons/my-active.png"
- }]
- },
- "pages": [{
- "path": "pages/home/home",
- "style": {
- "navigationBarTitleText": "",
- "enablePullDownRefresh": false
- }
-
- }, {
- "path": "pages/cate/cate",
- "style": {
- "navigationBarTitleText": "",
- "enablePullDownRefresh": false
- }
-
- }, {
- "path": "pages/cart/cart",
- "style": {
- "navigationBarTitleText": "",
- "enablePullDownRefresh": false
- }
-
- }, {
- "path": "pages/my/my",
- "style": {
- "navigationBarTitleText": "",
- "enablePullDownRefresh": false
- }
-
- }],
- "globalStyle": {
- "navigationBarTextStyle": "black",
- "navigationBarTitleText": "uni-app",
- "navigationBarBackgroundColor": "#F8F8F8",
- "backgroundColor": "#F8F8F8",
- "app-plus": {
- "background": "#efeff4"
- }
- }
- }
- ***********************************************************************************
- "selectedColor": "#C00000",
- ***********************************************************************************
- pages下面是重点,如果看不到记得删除index也就是首页,牛批呀 我的哥哥
- ***********************************************************************************
- 提交与合并
- git add .
- git status
- git commit -m "完成tabBar"
- git push -u origin "tabbar"
- git checkout master
- git merge tabbar
- git push
- git branch
- git branch -d tabbar 删除本地分支
- 【3】实现首页相关的功能!!!!!!!!!!!!!!轮播图
- 不搞分支了,真JB麻烦
- ***********************************************************************************
- npm init -y
- npm i @escook/request-miniprogram
- ---------------------------------------------------------------------------------------------
- // 导入网络请求包
- import {
- $http
- } from '@escook/request-miniprogram'
-
- uni.$http = $http
-
- // 请求拦截器
- $http.beforeRequest = function(options) {
- uni.showLoading({
- title: '数据加载中...'
- })
- }
-
- // 响应拦截器
- $http.afterRequest=function(){
- uni.hideLoading()
- }
- ***********************************************************************************
- 请求轮播图数据
- 原来是我的服务没有设置跨域导致的,我天 卧槽 沃日!!!!!!!!!!!
- ***********************************************************************************
- 我也不知道怎么折腾的,反正更新跨域后就解决了,哈哈哈哈!!!!
- onLoad() {
- // 加载的时候就调用方法
- this.selectList()
- },
- methods: {
- selectList() {
- uni.$http.post("/document/list_page", this.sendData).then(res => {
- console.log(res)
- })
- }
- }
- 至此,就实现了VUE类似的开发,但是可以运行N+个平台,卧槽 牛批!!!!!!!!!!!!!
- ***********************************************************************************
- selectList() {
- uni.$http.post("/document/list_page", this.sendData).then(res => {
- // console.log(res)
- if (res.data.code === "200") {
- this.list = res.data.object.data
- } else {
- return uni.showToast({
- title: '数据请求失败',
- duration: 1500,
- icon: 'none'
- })
- }
- })
- }
- h5 app 小程序 浏览器 皆可以
- ***********************************************************************************
- usw可以快速生成轮播图:
- <template>
- <view>
- <swiper :indicator-dots="true" :autoplay="true" :interval="3000" :duration="1000" :circular="true"
- style="height: 330rpx;">
- <!-- 循环渲染item项目 -->
- <swiper-item v-for="item in list" :key="item.id">
- <view style="width: 100%;height: 100%;">
- <image :src="item.url" style="width: 100%;height: 100%;"></image>
- </view>
- </swiper-item>
- </swiper>
- </view>
- </template>
-
- <script>
- export default {
- data() {
- return {
- // list集合
- list: [],
- sendData: {
- currentPage: 1,
- pageSize: 10,
- total: 10
- }
- };
- },
- onLoad() {
- // 加载的时候就调用方法
- this.selectList()
- },
- methods: {
- selectList() {
- uni.$http.post("/document/list_page", this.sendData).then(res => {
- // console.log(res)
- if (res.data.code === "200") {
- this.list = res.data.object.data
- } else {
- return uni.showToast({
- title: '数据请求失败',
- duration: 1500,
- icon: 'none'
- })
- }
- })
- }
- }
- }
- </script>
-
- <style lang="scss">
-
- </style>
- 【4】配置小程序分包,万众则归一!!!!!!!!!!!!!!!!!!
- 先建立subpkg目录
- 然后再pages.json里配置下
- "subPackages": [{
- "root": "subpkg",
- "pages": [{
- "path": "goods_detail/goods_detail",
- "style": {}
-
- }]
- }],
- ---------------------------------------------------------------------------------------------
- 然后手动到subpkg下新建页面就行了,弹出的页面中注意选择分包名称,完成OVER
- 【5】点击轮播图,跳转商品详情页的功能
- <template>
- <view>
- <swiper :indicator-dots="true" :autoplay="true" :interval="3000" :duration="1000" :circular="true"
- style="height: 330rpx;">
- <!-- 循环渲染item项目 -->
- <swiper-item v-for="item in list" :key="item.id">
- <navigator style="width: 100%;height: 100%;" :url="'/subpkg/goods_detail/goods_detail?id='+item.id">
- <image :src="item.url" style="width: 100%;height: 100%;"></image>
- </navigator>
- </swiper-item>
- </swiper>
- </view>
- </template>
- ---------------------------------------------------------------------------------------------
- 这就完事了,到详情页,有id参数值
- 【6】封装uni.$showMsg(0方法
- 因为当调用失败的时候,每次都要写uni.showToast方法,非常麻烦,所以要封装!!!!
- ---------------------------------------------------------------------------------------------
- // 封装一个报错的方法
- uni.$message = function(title = "数据请求失败!", duration = 1500) {
- uni.showToast({
- title,
- duration,
- icon: 'none'
- })
- }
- ---------------------------------------------------------------------------------------------
- selectList() {
- uni.$http.post("/document/list_page", this.sendData).then(res => {
- // console.log(res)
- if (res.data.code === "200") {
- this.list = res.data.object.data
- return uni.$message("数据请求成功")
- } else {
- return uni.$message()
- }
- })
- }
- 【7】实现分类导航区域
- selectNavList() { // 请求分类图
- uni.$http.post("/kind/list_page", this.sendData).then(res => {
- console.log(res)
- if (res.data.code === "200") {
- this.navList = res.data.object.data // 注意是navList的赋值了
- return uni.$message("数据请求成功!")
- } else {
- return uni.$message()
- }
- })
- }
- ---------------------------------------------------------------------------------------------
- <!-- 分类导航区域 -->
- <view style="display: flex;justify-content: space-around;margin: 15px 0;">
- <view v-for="item in navList" :key="item.id" @click="navClick(item)">
- <image :src="item.urlIcon" style="width: 128rpx;height: 140rpx;"></image>
- <view style="font-size: 24rpx;margin-left: 24rpx;">{{item.type}}</view>
- </view>
- </view>
- ---------------------------------------------------------------------------------------------
- 点击第一项,实现分类页面:
- navClick(item) {
- // console.log(item)
- if (item.type === "点分类") {
- uni.switchTab({ // !!!!!!!!!!!!!这是重点
- url: '/pages/cate/cate'
- })
- }
- },
- 【8】获取楼层数据并渲染楼层的标题
- <view style="">
- <view v-for="(item,index) in floorList" :key="index">
- <!-- 楼层标题 -->
- <view style="height: 60rpx;width: 100%;display: flex;color: crimson;font-size: 36rpx;">
- {{item.floor_title}}
- </view>
- </view>
- </view>
- 【9】渲染楼层里面的图片
- <!-- 左侧大图 mode="widthFix" 如果图片本身合规的话-->
- <view>
- <image :src="item.product_list[0].url" style="width: 232rpx;"></image>
- </view>
- ---------------------------------------------------------------------------------------------
- <!-- 楼层数据 -->
- <view style="">
- <view v-for="(item,index) in floorList" :key="index">
- <!-- 楼层标题 -->
- <view
- style="height: 60rpx;width: 100%;display: flex;color: crimson;font-size: 36rpx;padding-left: 10rpx;">
- {{item.floor_title}}
- </view>
- <!-- 楼层的图片区域 -->
- <view style="display: flex;padding-left: 10rpx;">
- <!-- 左侧大图 mode="widthFix" 如果图片本身合规的话-->
- <view>
- <image :src="item.product_list[0].url" style="width: 232rpx;"></image>
- </view>
- <!-- 右侧4小图 -->
- <view style="display: flex;flex-wrap: wrap;justify-content: space-around;">
- <view v-for="(subItem,subIndex) in item.product_list" :key="subIndex" v-if="subIndex!==0">
- <image :src="subItem.url" style="width: 232rpx;height: 236rpx;"></image>
- </view>
- </view>
- </view>
- </view>
- </view>
- 【10】点击楼层图片跳转到商品列表页
- 在分包里新建goods_list页面,感觉用了uniapp好清晰呀,就一个vue文件,哈哈哈哈!!!!!!
- res.data.object.data.forEach(item => { // 挂载上页面属性
- item.navUrl = "/subpkg/goods_list/goods_list?query=" + item.kind
- })
- ---------------------------------------------------------------------------------------------
- <navigator :url="item.product_list[0].navUrl">
- <image :src="item.product_list[0].url" style="width: 232rpx;"></image>
- </navigator>
- ---------------------------------------------------------------------------------------------
- <view style="display: flex;flex-wrap: wrap;justify-content: space-around;">
- <navigator v-for="(subItem,subIndex) in item.product_list" :key="subIndex" v-if="subIndex!==0"
- :url="subItem.navUrl">
- <image :src="subItem.url" style="width: 232rpx;height: 236rpx;"></image>
- </navigator>
- </view>
- 【11】分支的合并与提交
- 对于我来说就是规整下项目,存下百度网盘!!!!!!!!!!!!!!
- 【12】108集 创建cate分支以及分类页面的编译模式
- 微信小程序里点击小程序模式,新建模式,选择cate页面,这样方便开发!!!!
- 【13】109集初始化分类区域的页面布局
- 滑动区域
- ***************************************************************************************
- 主要是通过scroll-view scroll-y="true" style="height: 300px;width: 120px;"
- 加样式实现:
- ***************************************************************************************
- 占满整个屏幕的高度:
- 自带的方法拿到屏幕高度...
- ---------------------------------------------------------------------------------------
- windowHeight
- ---------------------------------------------------------------------------------------
- onLoad() {
- const sysInfo = uni.getSystemInfoSync();
- // console.log(sysInfo)
- this.windowsHeight = sysInfo.windowHeight
- }
- ---------------------------------------------------------------------------------------
- :style="{height:windowsHeight+'px',width:'120px'}" // 动态属性绑定
- ---------------------------------------------------------------------------------------
- .leftView {
- background-color: #F7F7F7;
- line-height: 60px;
- text-align: center;
- font-size: 12px;
-
- &.active {
- background-color: #FFFFFF;
- position: relative;
-
- &::before {
- content: ' ';
- display: block;
- width: 3px;
- height: 30px;
- background-color: #C00000;
- position: absolute;
- top: 50%;
- left: 0%;
- transform: translateY(-50%)
- }
- }
- }
- ---------------------------------------------------------------------------------------
- 有时候不得不用css,哎
- 【14】获取并渲染一级分类列表数据
- 实操的时候,一级分类需要从mysql group by 下。然后分类肯定有很多吗....
- 【15】渲染二级和三级分类类表:
- <!-- 右侧滑动区域 -->
- <scroll-view scroll-y="true" :style="{height:windowsHeight+'px'}">
- <view style="font-size: 12px;font-weight: bold;text-align: center;padding: 15px 0;">
- <!-- 按道理二级分类应该是动态的 -->
- / 爆款服装-2级 /
- </view>
- <view style="display: flex;flex-wrap: wrap;">
- <view v-for="item in cateListLevel2" :key="item.id"
- style="width: 33.33%;display: flex;flex-direction: column;justify-content: center;align-items: center;margin-bottom: 10px;">
- <!-- 图片 -->
- <image :src="item.url" style="width: 60px;height: 60px;"></image>
- <!-- 文本 -->
- <text style="font-size: 12px;">{{item.name}}</text>
- </view>
- </view>
- </scroll-view>
- 【16】切换的时候滚动条的位置没有从顶部开始
- 解决bug:
- :scroll-top="scrollTop"
- this.scrollTop = this.scrollTop === 0 ? 0.01 : 0 // 因为不能赋值一样的
- ***************************************************************************************
- 点击图片跳转到商品类表页面:
- <view v-for="item in cateListLevel2" :key="item.id"
- style="width: 33.33%;display: flex;flex-direction: column;justify-content: center;align-items: center;margin-bottom: 10px;"
- @click="goGoodsList(item)">
- ---------------------------------------------------------------------------------------
- goGoodsList(item) { // 跳转到商品列表页面
- uni.navigateTo({
- url: '/subpkg/goods_list/goods_list?kind=' + item.kind // 传递分类
- })
- },
- 【17】搜索相关的功能:自定义搜索组件、搜索建议、搜索历史
- 创建自定义搜索组件:
- ***************************************************************************************
- 新建components目录,新建my-search组件
- ---------------------------------------------------------------------------------------
- <template>
- <view>
- 这是自定义搜索组件
- </view>
- </template>
-
- <script>
- export default {
- name: "my-search",
- data() {
- return {
-
- };
- }
- }
- </script>
-
- <style lang="scss">
-
- </style>
- ---------------------------------------------------------------------------------------
- <!-- 使用自定义组件 -->
- <my-search></my-search>
- ---------------------------------------------------------------------------------------
- 优化组件布局
- <template>
- <view style="height: 50px;background-color: #C00000;display: flex;align-items: center;padding: 0 10px;">
- <view
- style="height: 36px;background-color: #FFFFFF;border-radius: 18px;width: 100%;display: flex;justify-content: center;align-items: center;">
- <!-- icon组件 -->
- <uni-icons type="search" size="17"></uni-icons>
- <text style="font-size: 15px;margin-left: 5px;">搜索</text>
- </view>
- </view>
- </template>
-
- <script>
- export default {
- name: "my-search",
- data() {
- return {
-
- };
- }
- }
- </script>
-
- <style lang="scss">
-
- </style>
- ---------------------------------------------------------------------------------------
- 解决添加搜索区域后滚动显示不全的问题:
- this.windowsHeight = sysInfo.windowHeight - 50
- ***************************************************************************************
- 自定义组件的形式,增加通用性:
- 没必要这么人性化,都能自定义,你要知道你的代码谁去用...!!!!!!!!!!!!!
- 用props绑定属性
- 动态绑定style :style="{a:'1',b:'2'}"
- ***************************************************************************************
- 为自定义组件封装click事件:
- <view style="height: 50px;background-color: #C00000;display: flex;align-items: center;padding: 0 10px;"
- @click="searchHandler">
- ---------------------------------------------------------------------------------------
- searchHandler() {
- console.log("-----!!!!!")
- this.$emit('click') // 注意这个名字和引用组件页面的@ click是一样的
- }
- ---------------------------------------------------------------------------------------
- <my-search @click="goSearch"></my-search>
- ---------------------------------------------------------------------------------------
- goSearch() { // 跳转搜索页
- console.log("外界调用")
- },
- 【18】导航跳转与吸顶效果
- goSearch() { // 跳转搜索页 // 这才是真正有用的!!!!!!!!!!!!!!!
- // console.log("外界调用")
- uni.navigateTo({
- url: '/subpkg/search/search'
- })
- },
- ***************************************************************************************
- <!-- 搜索组件 -->
- <view style="position:sticky;top:0;z-index:999">
- <my-search @click="goSearch"></my-search>
- </view>
- 【19】搜索建议
- <template>
- <view>
- <view style="background-color: #C00000;position:sticky;top:0;z-index:999">
- <uni-search-bar @input="input" :radius="100" cancelButton="none" placeholder="请输入搜索内容">
- </uni-search-bar>
- </view>
- </view>
- </template>
-
- <script>
- export default {
- data() {
- return {
-
- };
- },
- methods: {
- input(e) {
- console.log(e)
- }
- }
- }
- </script>
-
- <style lang="scss">
-
- </style>
- ***************************************************************************************
- 搜索框自动获取焦点:
- uni_modules----uni-search-bar---componets---uni-search-bar.vue
- 修改里面的data
- data() {
- return {
- show: true,
- showSync: true, // !!!!!!!!!!!!!!这里
- searchVal: ''
- }
- },
- ***************************************************************************************
- 处理下搜索框的防抖,防止无效的请求
- <script>
- export default {
- data() {
- return {
- timer: null, //延时器
- keyWord: ''
- };
- },
- methods: {
- input(e) {
- // console.log(e)
- clearTimeout(this.timer)
- this.timer = setTimeout(() => {
- // console.log(e)
- this.keyWord = e // 赋值关键词
- }, 500)
- }
- }
- }
- </script>
- 【20】关键词查询建议列表118集合
- selectSearchList() {
- // 搜索关键词是否为空
- if (this.keyWord.length === 0) {
- this.searchResultList = []
- return false
- }
- this.sendData.kind = this.keyWord
- uni.$http.post("/document/list_page", this.sendData).then(res => {
- console.log(res)
- if (res.data.code === "200") {
- this.searchResultList = res.data.object.data
- } else {
- return uni.$message()
- }
- })
- }
- *******************************************************************************************
- 【21】点击跳转详情页
- goDetail(item) { // 跳转详情
- uni.navigateTo({
- url: "/subpkg/goods_detail/goods_detail?id=" + item.id
- })
- },
- *******************************************************************************************
- 【22】渲染搜索历史
- <view style="padding: 0 5px;">
- <!-- 标题区域 -->
- <view
- style="display: flex;justify-content: space-between;height: 40px;align-items: center;font-size: 13px;border-bottom: 1px solid lightgray;">
- <text>搜索历史</text>
- <uni-icons type="trash" size="17"></uni-icons>
- </view>
- <!-- 列表区域 -->
- <view style="display: flex;flex-wrap: wrap;">
- <uni-tag v-for="(item,index) in historyList" :key="index" :text="item"
- style="margin-top: 5px;margin-right: 5px;"></uni-tag>
- </view>
- </view>
- *******************************************************************************************
- 按需展示!!!!!!!!!!!!!!!!!
- <!-- 搜索建议列表 -->
- <view style="padding: 0 5px;" v-if="searchResultList.length!==0">
- <view v-for="item in searchResultList" :key="item.id" @click="goDetail(item)"
- style="display: flex;align-items: center;justify-content: space-between;font-size: 12px;padding: 13px 0;border-bottom: 1px solid lightgray;">
- <view style="white-space: nowrap;overflow: hidden;text-overflow: ellipsis;margin-right: 3px;">
- {{item.kind}}+{{item.name}}
- </view>
- <uni-icons type="arrowright" size="16"></uni-icons>
- </view>
- </view>
- <!-- 搜索历史 -->
- <view style="padding: 0 5px;" v-else>
- <!-- 标题区域 -->
- <view
- style="display: flex;justify-content: space-between;height: 40px;align-items: center;font-size: 13px;border-bottom: 1px solid lightgray;">
- <text>搜索历史</text>
- <uni-icons type="trash" size="17"></uni-icons>
- </view>
- <!-- 列表区域 -->
- <view style="display: flex;flex-wrap: wrap;">
- <uni-tag v-for="(item,index) in historyList" :key="index" :text="item"
- style="margin-top: 5px;margin-right: 5px;"></uni-tag>
- </view>
- </view>
- 【23】处理搜索关键词
- saveHistory() { // 保存搜索历史记录
- this.historyList.push(this.keyWord)
- },
- *******************************************************************************************
- 但是存在排序与重复的问题:解决bug
- computed: {
- betterHistoryList() {
- return [...this.historyList].reverse()
- }
- },
- *******************************************************************************************
- <view style="display: flex;flex-wrap: wrap;">
- <uni-tag v-for="(item,index) in betterHistoryList" :key="index" :text="item"
- style="margin-top: 5px;margin-right: 5px;"></uni-tag>
- </view>
- *******************************************************************************************
- 解决搜索关键词重复问题
- saveHistory() { // 保存搜索历史记录
- const set = new Set(this.historyList)
- set.delete(this.keyWord) // 先移出历史
- set.add(this.keyWord) // 再追加新的
- this.historyList = Array.from(set)
- },
- *******************************************************************************************
- 搜索历史记录持久存储到本地
- onLoad() {
- this.historyList = JSON.parse(uni.getStorageSync('keyWord') || '[]')
- },
- methods: {
- saveHistory() { // 保存搜索历史记录
- const set = new Set(this.historyList)
- set.delete(this.keyWord) // 先移出历史
- set.add(this.keyWord) // 再追加新的
- this.historyList = Array.from(set)
- uni.setStorageSync("keyWord", JSON.stringify(this.historyList))
- },
- 【24】清空历史搜索记录
- cleanHistory() { // 清空历史记录
- this.historyList = []
- uni.setStorageSync("keyWord", '[]')
- },
- 【25】点击搜索历史,跳转商品列表页面
- <!-- 列表区域 -->
- <view style="display: flex;flex-wrap: wrap;">
- <uni-tag v-for="(item,index) in betterHistoryList" :key="index" :text="item" @click="goGoodsList(item)"
- style="margin-top: 5px;margin-right: 5px;"></uni-tag>
- </view>
- *******************************************************************************************
- goGoodsList(keyWord) {
- uni.navigateTo({
- url: "/subpkg/goods_list/goods_list?kind=" + keyWord
- })
- },
- 【25】125集商品列表页面的开发
- <template>
- <view>
- <!-- 外层容器 -->
- <view>
- <!-- item项 -->
- <block v-for="item in list" :key="item.id">
- <view style="display: flex;padding: 10px 5px;border-bottom: 1px solid lightgray;">
- <!-- 左侧盒子 -->
- <view style="margin-right: 5px;">
- <image :src="item.url || defaultImage" style="width: 100px;height: 100px;display: block;">
- </image>
- </view>
- <!-- 右侧盒子 -->
- <view style="display: flex;flex-direction: column;justify-content: space-between;">
- <!-- 商品名称 -->
- <view style="font-size: 13px;">{{item.name}}</view>
- <!-- 商品价格 -->
- <view style="color: #C00000;font-size: 16px;">¥ {{item.price}}</view>
- </view>
- </view>
- </block>
- </view>
- </view>
- </template>
-
- <script>
- export default {
- data() {
- return {
- list: [],
- defaultImage: 'http://wdfgdzx.top:8000/document/a5dd6d1d1c5c45dd98c6017b1821acb8.jpg', // 默认图片地址
- sendData: {
- currentPage: 1,
- pageSize: 10,
- total: 10
- }
- };
- }, // 从上个页面获取参数,获取不到默认是空
- onLoad(options) {
- // console.log(options)
- this.sendData.kind = options.kind || '' // 从上个页面获取参数,获取不到默认是空
- this.selectList()
- },
- methods: {
- selectList() {
- uni.$http.post("/document/list_page", this.sendData).then(res => {
- // console.log(res)
- if (res.data.code = "200") {
- this.list = res.data.object.data
- this.sendData.total = res.data.object.total
- } else {
- return uni.$message()
- }
- })
- }
- }
- }
- </script>
-
- <style lang="scss">
-
- </style>
- 【26】把商品item项分装成自定义组件
- 在components中创建my-goods组件:
- <view>
- <!-- item项 -->
- <block v-for="item in list" :key="item.id">
- <my-goods :item="item"></my-goods> <!-- 注意:item和接受页面名字是一样的 -->
- </block>
- </view>
- *******************************************************************************************
- <template>
- <!-- 外层容器 -->
- <view>
- <view style="display: flex;padding: 10px 5px;border-bottom: 1px solid lightgray;">
- <!-- 左侧盒子 -->
- <view style="margin-right: 5px;">
- <image :src="item.url || defaultImage" style="width: 100px;height: 100px;display: block;">
- </image>
- </view>
- <!-- 右侧盒子 -->
- <view style="display: flex;flex-direction: column;justify-content: space-between;">
- <!-- 商品名称 -->
- <view style="font-size: 13px;">{{item.name}}</view>
- <!-- 商品价格 -->
- <view style="color: #C00000;font-size: 16px;">¥ {{item.price}}</view>
- </view>
- </view>
- </view>
- </template>
-
- <script>
- export default {
- name: "my-goods",
- props: {
- item: { // 这个名字和页面里使用的名字是一致的,注意!!!!!!!!!!!!
- type: Object,
- default: {}
- }
- },
- data() {
- return {
- defaultImage: 'http://wdfgdzx.top:8000/document/a5dd6d1d1c5c45dd98c6017b1821acb8.jpg', // 默认图片地址
- };
- }
- }
- </script>
-
- <style lang="scss">
-
- </style>
- 【27】使用过滤器处理商品价格
- <template>
- <!-- 外层容器 -->
- <view>
- <view style="display: flex;padding: 10px 5px;border-bottom: 1px solid lightgray;">
- <!-- 左侧盒子 -->
- <view style="margin-right: 5px;">
- <image :src="item.url || defaultImage" style="width: 100px;height: 100px;display: block;">
- </image>
- </view>
- <!-- 右侧盒子 -->
- <view style="display: flex;flex-direction: column;justify-content: space-between;">
- <!-- 商品名称 -->
- <view style="font-size: 13px;">{{item.name}}</view>
- <!-- 商品价格 -->
- <view style="color: #C00000;font-size: 16px;">¥ {{item.price | toFixed}}</view>
- </view>
- </view>
- </view>
- </template>
-
- <script>
- export default {
- name: "my-goods",
- props: {
- item: { // 这个名字和页面里使用的名字是一致的,注意!!!!!!!!!!!!
- type: Object,
- default: {}
- }
- },
- data() {
- return {
- defaultImage: 'http://wdfgdzx.top:8000/document/a5dd6d1d1c5c45dd98c6017b1821acb8.jpg', // 默认图片地址
- };
- },
- filters: {
- toFixed(num) {
- return Number(num).toFixed(2)
- }
- }
- }
- </script>
-
- <style lang="scss">
-
- </style>
- 【28】实现下拉加载更多
- {
- "path": "goods_list/goods_list",
- "style": {
- "onReachBottomDistance": 150
- }
- },
- *******************************************************************************************
- onReachBottom() {
- this.sendData.currentPage = this.sendData.currentPage + 1 // 页面+1后 调用selectList方法
- this.selectList()
- },
- methods: {
- selectList() {
- uni.$http.post("/document/list_page", this.sendData).then(res => {
- // console.log(res)
- if (res.data.code = "200") {
- this.list = [...this.list, ...res.data.object.data] // 新旧数据拼接
- this.sendData.total = res.data.object.total
- } else {
- return uni.$message()
- }
- })
- }
- }
- *******************************************************************************************
- 节流阀的实现
- *******************************************************************************************
- 数据是否加载完毕实现
- if (this.sendData.currentPage * this.sendData.pageSize >= this.sendData.total) {
- return uni.$message("数据加载完毕...")
- }
- 【29】实现下拉刷新
- {
- "path": "goods_list/goods_list",
- "style": {
- "onReachBottomDistance": 150,
- "enablePullDownRefresh": true,
- "backgroundColor": "#f8f8f8"
- }
- },
- *******************************************************************************************
- onPullDownRefresh() {
- this.sendData.currentPage = 1
- this.sendData.total = 0
- this.loadingFlag = false
- this.list = []
- this.selectList(() => uni.stopPullDownRefresh())
- },
- *******************************************************************************************
- selectList(cb) {
- this.loadingFlag = true // 打开节流阀
- uni.$http.post("/document/list_page", this.sendData).then(res => {
- // console.log(res)
- this.loadingFlag = false // 关闭节流阀
- cb && cb()
- if (res.data.code = "200") {
- this.list = [...this.list, ...res.data.object.data] // 新旧数据拼接
- this.sendData.total = res.data.object.total
- } else {
- return uni.$message()
- }
- })
- }
- *******************************************************************************************
- UPDATE document SET preview=REPLACE(preview,'localhost','wdfgdzx.top');
- UPDATE document SET url=REPLACE(url,'localhost','wdfgdzx.top');
- *******************************************************************************************
- 【30】点击商品item跳转到商品详情页
- <!-- item项 -->
- <view v-for="item in list" :key="item.id" @click="goDetail(item)">
- <my-goods :item="item"></my-goods> <!-- 注意:item和接受页面名字是一样的 -->
- </view>
- *******************************************************************************************
- goDetail(item) { // 去详情页面
- uni.navigateTo({
- url: "/subpkg/goods_detail/goods_detail?id=" + item.id
- })
- },
- 【31】商品详情页的开发
- <script>
- export default {
- data() {
- return {
- goodsInfo: {}
- };
- },
- onLoad(options) {
- const id = options.id
- this.selectGoods(id)
- },
- methods: {
- selectGoods(id) {
- uni.$http.post("/document/select_id/" + id).then(res => {
- // console.log(res)
- if (res.data.code = "200") {
- this.goodsInfo = res.data.object
- } else {
- return uni.$message()
- }
- })
- }
- }
- }
- </script>
- *******************************************************************************************
- 商品详情页的UI结构
- <view>
- <!-- 商品详情页 -->
- <swiper :indicator-dots="true" :autoplay="true" :interval="3000" :duration="1000" :circular="true"
- style="height: 750rpx;">
- <swiper-item v-for="(item,index) in goodsInfo.imageList" :key="index">
- <image :src="item" style="width: 100%;height: 100%;"></image>
- </swiper-item>
- </swiper>
- </view>
- *******************************************************************************************
- 轮播图预览效果!!!!!!!!!!!!!!!!!!!!!!!!
- <template>
- <view>
- <!-- 商品详情页 -->
- <swiper :indicator-dots="true" :autoplay="true" :interval="3000" :duration="1000" :circular="true"
- style="height: 750rpx;">
- <swiper-item v-for="(item,index) in goodsInfo.imageList" :key="index">
- <image :src="item" style="width: 100%;height: 100%;" @click="preview(index)"></image>
- </swiper-item>
- </swiper>
- </view>
- </template>
-
- <script>
- export default {
- data() {
- return {
- goodsInfo: {
- imageList: []
- }
- };
- },
- onLoad(options) {
- const id = options.id
- this.selectGoods(id)
- },
- methods: {
- preview(index) { // 预览
- uni.previewImage({
- current: index,
- urls: this.goodsInfo.imageList.map(v => v)
- })
- },
- selectGoods(id) {
- uni.$http.post("/document/select_id/" + id).then(res => {
- // console.log(res)
- if (res.data.code = "200") {
- this.goodsInfo = res.data.object
- this.goodsInfo.imageList = res.data.object.imageList.split("&&&")
- // console.log(this.goodsInfo.imageList)
- } else {
- return uni.$message()
- }
- })
- }
- }
- }
- </script>
-
- <style lang="scss">
-
- </style>
- 【32】渲染美化商品信息区域 136集
- <view>
- <!-- 商品价格 -->
- <view>
- {{goodsInfo.price}}
- </view>
- <!-- 信息主题区域 -->
- <view>
- <!-- 商品名称 -->
- <view>
- {{goodsInfo.name}}
- </view>
- <!-- 收藏 -->
- <view>
- <uni-icons type="star" size="18" color="gray"></uni-icons>
- <text>收藏</text>
- </view>
- </view>
- <!-- 运费区域 -->
- <view>
- 快递:免运费
- </view>
- </view>
- *************************************************************************************************
- 美化:
- <!-- 商品信息区域 -->
- <view style="padding: 10px;padding-right: 0;">
- <!-- 商品价格 -->
- <view style="color: #C00000;font-size: 18px;margin: 10px 0;">
- ¥ {{goodsInfo.price}}
- </view>
- <!-- 信息主题区域 -->
- <view style="display: flex;justify-content: space-between;">
- <!-- 商品名称 -->
- <view style="font-size: 13px;margin-right: 10px">
- {{goodsInfo.name}}
- </view>
- <!-- 收藏 -->
- <view style="width: 120px;font-size: 12px;display: flex;flex-direction: column;align-items: center;
- justify-content: center;border-left: 1px solid lightgray;color: gray;">
- <uni-icons type="star" size="18" color="gray"></uni-icons>
- <text>收藏</text>
- </view>
- </view>
- <!-- 运费区域 -->
- <view style="font-size: 12px;color: gray;margin: 10px 0;">
- 快递:免运费
- </view>
- </view>
- 【33】渲染商品详情数据
- <!-- 商品详情图片区域 -->
- <view style="display: flex;justify-content: center;">
- <image src='https://wdfgdzx.top/document/pre_see/00f3be647229489887b4fa6a9f35459b.jpg' style="width: 100%;">
- </image>
- </view>
- *************************************************************************************************
- .webp替换为jpg即可在iOS上显示
- *************************************************************************************************
- 解决商品价格显示闪烁问题:
- <view v-if="goodsInfo.name">
- 【34】渲染商品底部的导航区域
- <!-- 底部导航区域 -->
- <view style="position: fixed;bottom: 0;left:0;width: 100%;">
- <uni-goods-nav :fill="true" :options="options" :buttonGroup="buttonGroup" @click="onClick"></uni-goods-nav>
- </view>
- *************************************************************************************************
- options: [{
- icon: 'headphones',
- text: '客户'
- }, {
- icon: 'shop',
- text: '店铺',
- info: 2,
- backgroundColor: '#007aff',
- color: 'red'
- }, {
- icon: 'cart',
- text: '购物车',
- info: 2
- }],
- buttonGroup: [{
- text: '加入购物车',
- backgroundColor: '#ff0000',
- color: '#fff'
- }, {
- text: '立即购买',
- backgroundColor: '#ffa200',
- color: '#fff'
- }]
- *************************************************************************************************
- 除了说一句:帅!!!!!!!!!!!!!!!!!!!!还能说什么
- *************************************************************************************************
- 点击购物车,跳转到购物车页面
- onClick(e) { //点击
- // console.log(e)
- if (e.content.text === "购物车") {
- uni.switchTab({
- url: "/pages/cart/cart"
- })
- }
- },
- 【35】140集加入购物车store.js,初始化vuex
- import Vue from 'vue'
- import Vuex from 'vuex'
-
- Vue.use(Vuex)
-
- const store = new Vuex.Store({
- modules: {
-
- }
- })
-
- export default store
- *************************************************************************************************
- // #ifndef VUE3
- import Vue from 'vue'
- import App from './App'
- import store from '@/store/store.js'
-
- // 导入网络请求包
- import {
- $http
- } from '@escook/request-miniprogram'
-
- uni.$http = $http
-
- // 请求的根路径
- $http.baseUrl = "https://localhost"
- //$http.baseUrl = "https://wdfgdzx.top"
-
- // 请求开始之前做一些事情
- $http.beforeRequest = function(options) {
- uni.showLoading({
- title: "数据加载中..."
- })
- }
-
- // 请求完成之后做一些事情
- $http.afterRequest = function() {
- uni.hideLoading()
- }
-
- // 封装一个报错的方法
- uni.$message = function(title = "数据请求失败!", duration = 1500) {
- uni.showToast({
- title,
- duration,
- icon: 'none'
- })
- }
-
-
- Vue.config.productionTip = false
-
- App.mpType = 'app'
-
- const app = new Vue({
- ...App,
- store
- })
- app.$mount()
- // #endif
-
- // #ifdef VUE3
- import {
- createSSRApp
- } from 'vue'
- import App from './App.vue'
- export function createApp() {
- const app = createSSRApp(App)
- return {
- app
- }
- }
- // #endif
- *************************************************************************************************
- 购物车数据全局存储
- export default {
- namespaced: true,
- state: () => ({
- // 包含6个属性 id name price count image state
- cart: []
- }),
- mutations: {},
- getters: {}
- }
- ------------------------------------------------------------------------------------------------
- import Vue from 'vue'
- import Vuex from 'vuex'
- import moduleCart from '@/store/cart.js'
-
- Vue.use(Vuex)
-
- const store = new Vuex.Store({
- modules: {
- 'm_cart': moduleCart // 关联购物车示例
- }
- })
-
- export default store
- 【36】实现加入购物车功能
- 辅助函数:
- import {
- mapState
- } from 'vuex'
-
- export default {
- computed: {
- ...mapState('m_cart', [])
- },
- *************************************************************************************************
- ...mapMutations('m_cart', ['addCart']), // 使用全局存储方法
- buttonClick(e) {
- // console.log(e)
- if (e.content.text === "加入购物车") {
- const goods = {
- id: this.goodsInfo.id,
- name: this.goodsInfo.name,
- price: this.goodsInfo.price,
- count: 1,
- image: this.goodsInfo.image,
- state: true // 默认是勾选的
- }
- this.addCart(goods)
- }
- },
- *************************************************************************************************
- <template>
- <view v-if="goodsInfo.name" style="padding-bottom: 50px;">
- <!-- 商品详情页 -->
- <!-- 轮播图区域 -->
- <swiper :indicator-dots="true" :autoplay="true" :interval="3000" :duration="1000" :circular="true"
- style="height: 750rpx;">
- <swiper-item v-for="(item,index) in goodsInfo.imageList" :key="index">
- <image :src="item" style="width: 100%;height: 100%;" @click="preview(index)"></image>
- </swiper-item>
- </swiper>
- <!-- 商品信息区域 -->
- <view style="padding: 10px;padding-right: 0;">
- <!-- 商品价格 -->
- <view style="color: #C00000;font-size: 18px;margin: 10px 0;">
- ¥ {{goodsInfo.price}}
- </view>
- <!-- 信息主题区域 -->
- <view style="display: flex;justify-content: space-between;">
- <!-- 商品名称 -->
- <view style="font-size: 13px;margin-right: 10px">
- {{goodsInfo.name}}
- </view>
- <!-- 收藏 -->
- <view style="width: 120px;font-size: 12px;display: flex;flex-direction: column;align-items: center;
- justify-content: center;border-left: 1px solid lightgray;color: gray;">
- <uni-icons type="star" size="18" color="gray"></uni-icons>
- <text>收藏</text>
- </view>
- </view>
- <!-- 运费区域 -->
- <view style="font-size: 12px;color: gray;margin: 10px 0;">
- 快递:免运费
- </view>
- </view>
-
- <!-- 商品详情图片区域 按道理应该是另一个list集合,不和轮播图的问题-->
- <view>
- <view v-for="(item,index) in goodsInfo.imageList" :key="index"
- style="display: flex;justify-content: center;flex-wrap: wrap;">
- <image :src="item" style="width: 100%;">
- </image>
- </view>
- </view>
-
- <!-- 底部导航区域 -->
- <view style="position: fixed;bottom: 0;left:0;width: 100%;">
- <uni-goods-nav :fill="true" :options="options" :buttonGroup="buttonGroup" @click="onClick"
- @buttonClick="buttonClick"></uni-goods-nav>
- </view>
- </view>
- </template>
-
- <script>
- import {
- mapState,
- mapMutations
- } from 'vuex'
-
- export default {
- computed: {
- ...mapState('m_cart', [])
- },
- data() {
- return {
- goodsInfo: {
- imageList: []
- },
- options: [
- // {
- // icon: 'headphones',
- // text: '客服'
- // },
- {
- icon: 'shop',
- text: '店铺',
- // info: 2,
- backgroundColor: '#007aff',
- color: 'red'
- }, {
- icon: 'cart',
- text: '购物车',
- info: 2
- }
- ],
- buttonGroup: [{
- text: '加入购物车',
- backgroundColor: '#ff0000',
- color: '#fff'
- }, {
- text: '立即购买',
- backgroundColor: '#ffa200',
- color: '#fff'
- }]
- };
-
-
- },
- onLoad(options) {
- const id = options.id
- this.selectGoods(id)
- },
- methods: {
- ...mapMutations('m_cart', ['addCart']), // 使用全局存储方法
- buttonClick(e) {
- // console.log(e)
- if (e.content.text === "加入购物车") {
- const goods = {
- id: this.goodsInfo.id,
- name: this.goodsInfo.name,
- price: this.goodsInfo.price,
- count: 1,
- image: this.goodsInfo.url,
- state: true // 默认是勾选的
- }
- this.addCart(goods) // 调用映射过来的全局存储方法
- }
- },
- onClick(e) { //点击
- // console.log(e)
- if (e.content.text === "购物车") {
- uni.switchTab({
- url: "/pages/cart/cart"
- })
- }
- },
- preview(index) { // 预览
- uni.previewImage({
- current: index,
- urls: this.goodsInfo.imageList.map(v => v)
- })
- },
- selectGoods(id) {
- uni.$http.post("/document/select_id/" + id).then(res => {
- // console.log(res)
- if (res.data.code = "200") {
- this.goodsInfo = res.data.object
- this.goodsInfo.imageList = res.data.object.imageList.split("&&&")
- // console.log(this.goodsInfo.imageList)
- } else {
- return uni.$message()
- }
- })
- }
- }
- }
- </script>
-
- <style lang="scss">
-
- </style>
- *************************************************************************************************
- 此种有真意,欲辨已忘言
- 【37】142集 动态统计购物车中商品的总数量
- totalNum(state) {
- let c = 0
- state.cart.forEach(x => {
- c = c + x.count
- })
- return c // 计算总数
- }
- *****************************************************************************************
- watch: {
- totalNum(newVal) {
- // console.log(newVal)
- const findResult = this.options.find(x => x.text === '购物车')
- if (findResult) {
- findResult.info = newVal
- }
- }
- },
- 【38】持久化存储购物车的数据
- export default {
- namespaced: true,
- state: () => ({
- // 包含6个属性 id name price count image state
- cart: JSON.parse(uni.getStorageSync('cart') || '[]')
- }),
- mutations: { // 方法在这里定义的
- addCart(state, goods) {
- const findResult = state.cart.find(x => x.id === goods.id) // 根据id判断是否存在
- console.log(findResult)
- if (!findResult) {
- state.cart.push(goods)
- } else {
- findResult.count++ // 数量+1
- }
- // console.log(state.cart)
- this.commit('m_cart/saveToStorage')
- },
- // 持久化存储数据
- saveToStorage(state) {
- uni.setStorageSync('cart', JSON.stringify(state.cart)) // 存储到本地
- }
- },
- getters: {
- totalNum(state) {
- let c = 0
- state.cart.forEach(x => {
- c = c + x.count
- })
- return c // 计算总数
- }
- }
- }
- 【39】优化total侦听器
- 因为重新编译后还是0.....日尼玛
- watch: {
- totalNum: {
- handler(newVal) {
- const findResult = this.options.find(x => x.text === '购物车')
- if (findResult) {
- findResult.info = newVal
- }
- },
- immediate: true // 这个就可以在加载完毕后立刻调用
- }
- },
- *****************************************************************************************
- 主要是通过优化侦听器
- 【40】动态设置tabBar的数字徽标
- <script>
- import {
- mapGetters
- } from 'vuex'
-
- export default {
- computed: { // 把全局数据映射到购物车
- ...mapGetters('m_cart', ['totalNum'])
- },
- onShow() {
- this.setBadge()
- },
- data() {
- return {
-
- };
- },
- methods: {
- setBadge() {
- uni.setTabBarBadge({
- index: 2,
- text: this.totalNum + ""
- })
- }
- }
- }
- </script>
- *****************************************************************************************
- 把设置tabBar徽标的代码抽离为mixins
- 因为直接回到首页...等页面,徽标不生效,所以需要抽离!!!!!!!!!!!!!
- import {
- mapGetters
- } from 'vuex'
-
- export default {
- computed: { // 把全局数据映射到购物车
- ...mapGetters('m_cart', ['totalNum'])
- },
- onShow() {
- this.setBadge()
- },
- methods: {
- setBadge() {
- uni.setTabBarBadge({
- index: 2,
- text: this.totalNum + ""
- })
- }
- }
- }
- -------------------------------------------------------------------------------------------------
- import mix from '@/mixins/tabbar-badge.js'
- export default {
- mixins: [mix],
- 徽标永存
- 【41】购物车页面-效果演示和编译模式新增
- 地址、加减购物、结算----牛批了!!!!!!!!!!!!!
- 谢谢黑马的老师!!!!!!!!!!!!!
- 在小程序新增一个直接跳转购物车的模式......简单的一批!!!!!!!!!
- *****************************************************************************************
- <image :src="item.url ||item.image || defaultImage" style="width: 100px;height:
- 100px;display: block;"></image>
- 我是个人才!!!!!!!!!!!!!!!!!!!!!!!
- <!-- 左侧盒子 -->
- <view style="margin-right: 5px;display: flex;justify-content: space-between;align-items: center;">
- <!-- 选择项 -->
- <radio checked="true" color="#C00000"></radio>
- <image :src="item.url ||item.image || defaultImage" style="width: 100px;height: 100px;display: block;">
- </image>
- </view>
- *****************************************************************************************
- 控制显示与隐藏,因为列表也需要隐藏!!!!!!!!!!!!!!!
- props: {
- item: { // 这个名字和页面里使用的名字是一致的,注意!!!!!!!!!!!!
- type: Object,
- default: {}
- },
- showRadio: {
- type: Boolean,
- default: false // 默认不展示选择框 即可,需要的话需要传递true
- }
- },
- -------------------------------------------------------------------------------------------------
- <radio checked="true" color="#C00000" v-if="showRadio"></radio>
- -------------------------------------------------------------------------------------------------
- 验证了一句话:万丈高楼平地起!!!!!!!!!!!!!!又见东风来...
- :checked="item.state"
- 动态绑定选中状态
- 【42】149集 修改购物车商品的勾选状态
- <my-goods :item="item" :showRadio="true" @fff_son_radioChange="fff_son_radioChange"></my-goods>
- -------------------------------------------------------------------------------------------------
- <radio :checked="item.state" color="#C00000" v-if="showRadio" @click="son_fff_radioClick"></radio>
- -------------------------------------------------------------------------------------------------
- son_fff_radioClick() { // 子触发父亲函数
- this.$emit('fff_son_radioChange', {
- item_id: this.item.id,
- item_state: !this.item.state
- })
- }
- -------------------------------------------------------------------------------------------------
- fff_son_radioChange(e) {
- console.log(e)
- }
- *****************************************************************************************
- 更新购物车里面的商品勾选状态:
- // 更新购物车中商品勾选状态
- updateGoodsState(state, goods) {
- const findResult = state.cart.find(x => x.id === goods.id) // 根据id判断是否存在
- if (findResult) {
- findResult.state = goods.state // 更新勾选状态
- this.commit('m_cart/saveToStorage') // 更新存储本地
- }
- }
- -------------------------------------------------------------------------------------------------
- methods: {
- ...mapMutations('m_cart', ['updateGoodsState']),
- fff_son_radioChange(e) {
- // console.log(e)
- this.updateGoodsState(e) // 更新选中状态 e其实是一个对象,传参对象!!!!!!!!!!!!
- }
- }
- 【43】商品列表-封装NumberBox
- <template>
- <!-- 外层容器 -->
- <view>
- <view style="display: flex;padding: 10px 5px;border-bottom: 1px solid lightgray;">
- <!-- 左侧盒子 -->
- <view style="margin-right: 5px;display: flex;justify-content: space-between;align-items: center;">
- <!-- 选择项 -->
- <radio :checked="item.state" color="#C00000" v-if="showRadio" @click="son_fff_radioClick"></radio>
- <image :src="item.url ||item.image || defaultImage" style="width: 100px;height: 100px;display: block;">
- </image>
- </view>
- <!-- 右侧盒子 -->
- <view style="display: flex;flex-direction: column;justify-content: space-between;flex:1;">
- <!-- 商品名称 -->
- <view style="font-size: 13px;">{{item.name}}</view>
- <!-- 包了一层 -->
- <view style="display: flex;justify-content: space-between;align-items: center;">
- <!-- 商品价格 -->
- <view style="color: #C00000;font-size: 16px;">¥ {{item.price | toFixed}}</view>
- <!-- 商品数量 -->
- <uni-number-box :min="1" :value="item.count">
- </uni-number-box>
- </view>
- </view>
- </view>
- </view>
- </template>
-
- <script>
- export default {
- name: "my-goods",
- props: {
- item: { // 这个名字和页面里使用的名字是一致的,注意!!!!!!!!!!!!
- type: Object,
- default: {}
- },
- showRadio: {
- type: Boolean,
- default: false // 默认不展示选择框 即可,需要的话需要传递true
- }
- },
- data() {
- return {
- defaultImage: 'http://wdfgdzx.top:8000/document/a5dd6d1d1c5c45dd98c6017b1821acb8.jpg', // 默认图片地址
- };
- },
- filters: {
- toFixed(num) {
- return Number(num).toFixed(2)
- }
- },
- methods: {
- son_fff_radioClick() { // 子触发父亲函数
- this.$emit('fff_son_radioChange', {
- id: this.item.id,
- state: !this.item.state
- })
- }
- }
- }
- </script>
-
- <style lang="scss">
-
- </style>
- *****************************************************************************************
- 数量框的按需展示:
- 数据库读取最好用线上,不然麻烦不少呀!!!!!!!!!!!!!!!!
- 【44】151集 封装num-change事件,也是父传子,子传父的问题
- <template>
- <!-- 外层容器 -->
- <view>
- <view style="display: flex;padding: 10px 5px;border-bottom: 1px solid lightgray;">
- <!-- 左侧盒子 -->
- <view style="margin-right: 5px;display: flex;justify-content: space-between;align-items: center;">
- <!-- 选择项 -->
- <radio :checked="item.state" color="#C00000" v-if="showRadio" @click="son_fff_radioClick">
- </radio>
- <image :src="item.url ||item.image || defaultImage" style="width: 100px;height: 100px;display: block;">
- </image>
- </view>
- <!-- 右侧盒子 -->
- <view style="display: flex;flex-direction: column;justify-content: space-between;flex:1;">
- <!-- 商品名称 -->
- <view style="font-size: 13px;">{{item.name}}</view>
- <!-- 包了一层 -->
- <view style="display: flex;justify-content: space-between;align-items: center;">
- <!-- 商品价格 -->
- <view style="color: #C00000;font-size: 16px;">¥ {{item.price | toFixed}}</view>
- <!-- 商品数量 -->
- <uni-number-box :min="1" :value="item.count" v-if="showNum" @change="son_fff_numChange">
- </uni-number-box>
- </view>
- </view>
- </view>
- </view>
- </template>
-
- <script>
- export default {
- name: "my-goods",
- props: {
- item: { // 这个名字和页面里使用的名字是一致的,注意!!!!!!!!!!!!
- type: Object,
- default: {}
- },
- showRadio: {
- type: Boolean,
- default: false // 默认不展示选择框 即可,需要的话需要传递true
- },
- showNum: {
- type: Boolean,
- default: false // 默认不展示数量框 即可,需要的话需要传递true
- }
- },
- data() {
- return {
- defaultImage: 'http://wdfgdzx.top:8000/document/a5dd6d1d1c5c45dd98c6017b1821acb8.jpg', // 默认图片地址
- };
- },
- filters: {
- toFixed(num) {
- return Number(num).toFixed(2)
- }
- },
- methods: {
- son_fff_radioClick() { // 子触发父亲函数
- this.$emit('fff_son_radioChange', {
- id: this.item.id,
- state: !this.item.state
- })
- },
- son_fff_numChange(val) { // 子触发父亲函数
- this.$emit('fff_son_numChange', {
- id: this.item.id,
- count: val - 0 // 这就是最新的数量值
- })
- }
- }
- }
- </script>
-
- <style lang="scss">
-
- </style>
- 【45】152 优化NumberBox组件
- uni-number-box.vue已经默认解决了,最大值是100个,可以修改
- *****************************************************************************************
- inputValue 小数的处理也是默认帮处理了,果然技术的发展是牛批的,不断更新的!!!!!
- *****************************************************************************************
- uni-number-box.vue已经自优化了!!!!!!
- 【46】修改购物车数量持久化存储
- 问题:修改数量后,重新编译后还是变回原来的了....
- 搞半天,Hbulider没有运行到小程序,搞笑呀!!!!!!!!!!!!!!!!!!!!
- // 更新商品的数量并保存到本地
- updateCount(state, goods) { // 更新商品数量
- const findResult = state.cart.find(x => x.id === goods.id) // 根据id判断是否存在
- if (findResult) {
- findResult.count = goods.count // 更新数量
- // console.log(findResult)
- this.commit('m_cart/saveToStorage') // 更新存储本地
- }
- }
- *****************************************************************************************
- fff_son_numChange(e) {
- // console.log(e)
- this.updateCount(e) // 更新选中状态 e其实是一个对象,传参对象!!!!!!!!!!!!
- }
- 【47】滑动删除的UI效果
- 之后查看官网示例时发现options是旧版的写法,我使用的是新版,要用right-options代替。
- *****************************************************************************************
- 坑呀!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
- *****************************************************************************************
- <!-- 渲染购物车中的商品信息 -->
- <uni-swipe-action>
- <block v-for="(item,index) in cart" :key="index">
- <uni-swipe-action-item :right-options="options" @click="">
- <my-goods :item="item" :showRadio="true" :showNum="true" @fff_son_radioChange="fff_son_radioChange"
- @fff_son_numChange="fff_son_numChange"></my-goods>
- </uni-swipe-action-item>
- </block>
- </uni-swipe-action>
- *****************************************************************************************
- data() {
- return {
- options: [{
- text: '删除',
- style: {
- backgroundColor: '#C00000'
- }
- }]
- };
- },
- *****************************************************************************************
- 实现滑动删除的功能
- 代码写错,导致state.cart出错,耗费了我不少时间排查
- 还得实现保存空,重新保存,没少费劲
- removeGoodsById(state, goods) { // 根据id删除商品
- state.cart = state.cart.filter(x => x.id !== goods.id)
- this.commit('m_cart/saveToStorage') // 更新存储本地
- }
- *****************************************************************************************
- @click="swipeItemClick(item)">
- swipeItemClick(item) {
- // console.log(item)
- this.removeGoodsById(item)
- }
- 【48】收货地址的实现!!!!!!!!!!!!!!!!!!155集
- <template>
- <view>
- 收货地址组件
- </view>
- </template>
-
- <script>
- export default {
- name: "my-address",
- data() {
- return {
-
- };
- }
- }
- </script>
-
- <style lang="scss">
-
- </style>
- *****************************************************************************************
- <template>
- <view>
- <!-- 选择收货地址的盒子 -->
- <view style="height: 90px;display: flex;justify-content: center;align-items: center;">
- <button type="primary" size="mini" style="">请选择收货地址+</button>
- </view>
- <!-- 底部边框 -->
- <image src="/static/cart_border@2x.png" style="display: flex;width: 100%;height: 5px;"></image>
- </view>
- </template>
-
- <script>
- export default {
- name: "my-address",
- data() {
- return {
-
- };
- }
- }
- </script>
-
- <style lang="scss">
-
- </style>
- *****************************************************************************************
- <template>
- <view>
- <!-- 选择收货地址的盒子 -->
- <view style="height: 90px;display: flex;justify-content: center;align-items: center;">
- <button type="primary" size="mini" style="">请选择收货地址+</button>
- </view>
-
- <!-- 渲染收货信息的盒子 -->
- <view
- style="font-size: 12px;height: 90px;display: flex;flex-direction: column;justify-content: center;padding: 0 5px;">
- <!-- 第一行 -->
- <view style="display: flex;justify-content: space-between;">
- <!-- 左右布局 -->
- <view>收货人:ask</view>
- <view style="display: flex;">
- <view>电话:183XXXX0000</view>
- <uni-icons type="arrowright" size="16"></uni-icons>
- </view>
- </view>
- <!-- 第二行 -->
- <view style="display: flex;justify-content: space-between;align-items: center;margin-top: 10px;">
- <!-- 左右布局 -->
- <view style="white-space: nowrap;">收货地址:</view>
- <view>安徽省合肥市蜀山区创新大道2889号苏宁小店安徽省合肥市蜀山区创新大道2889号苏宁小店安徽省合肥市蜀山区创新大道2889号苏宁小店</view>
- </view>
- </view>
-
- <!-- 底部边框 -->
- <image src="/static/cart_border@2x.png" style="display: flex;width: 100%;height: 5px;"></image>
- </view>
- </template>
-
- <script>
- export default {
- name: "my-address",
- data() {
- return {
-
- };
- }
- }
- </script>
-
- <style lang="scss">
-
- </style>
- *****************************************************************************************
- 按需展示
- <view style="height: 90px;display: flex;justify-content: center;align-items: center;"
- v-if="JSON.stringify(address)==='{}'">
- <button type="primary" size="mini" style="">请选择收货地址+</button>
- </view>
-
- <!-- 渲染收货信息的盒子 -->
- <view v-else
- style="font-size: 12px;height: 90px;display: flex;flex-direction: column;justify-content:
- center;padding: 0 5px;">
- 【49】实现选择收货地址功能
- "requiredPrivateInfos": [
- "getLocation",
- "chooseAddress"
- ]
- 要使用,先开启
- *****************************************************************************************
- 然后再配置方法
- methods: {
- async pickAddress() {
- const [err, success] = await uni.chooseAddress().catch(err => err)
- // console.log(res)
- if (err === null && success.errMsg === 'chooseAddress:ok') {
- // console.log(success)
- this.address = success
- }
- }
- }
- 【50】渲染收货人信息
- computed: {
- addressStr() {
- if (!this.address.provinceName) {
- return ''
- } else {
- return this.address.provinceName + this.address.cityName + this.address.countyName + this.address
- .detailInfo
- }
- }
- },
- 【51】将客户选择的地址,存储到VUEX全局存储中
- export default {
- namespaced: true, // 开启命名空间
-
- // 数据节点
- state: () => ({
- address: {}
- }),
-
- // 方法
- mutations: {
- updateAddress(state, address) {
- state.address = address // 更新收货地址
- }
- },
-
- // 访问方法
- getters: {
-
- }
- }
- *****************************************************************************************
- ...mapState('m_user', ['address']),
- *****************************************************************************************
- methods: {
- ...mapMutations('m_user', ['updateAddress']),
- async pickAddress() {
- const [err, success] = await uni.chooseAddress().catch(err => err)
- // console.log(res)
- if (err === null && success.errMsg === 'chooseAddress:ok') {
- // console.log(success)
- // this.address = success
- this.updateAddress(success) // 更新地址
- }
- }
- }
- 【52】持久化存储到store.js中
- updateAddress(state, address) {
- state.address = address // 更新收货地址
- this.commit('m_user/saveAddressToStorage'); // 调用存储
- },
- saveAddressToStorage(state) {
- uni.setStorageSync('address', JSON.stringify(state.address)) // 存储到本地
- }
- 【53】将addressStr抽离为getters,目的是提高代码的复用性
- export default {
- namespaced: true, // 开启命名空间
-
- // 数据节点
- state: () => ({
- address: JSON.parse(uni.getStorageSync('address') || '{}')
- }),
-
- // 方法
- mutations: {
- updateAddress(state, address) {
- state.address = address // 更新收货地址
- this.commit('m_user/saveAddressToStorage'); // 调用存储
- },
- saveAddressToStorage(state) {
- uni.setStorageSync('address', JSON.stringify(state.address)) // 存储到本地
- }
- },
-
- // 访问方法
- getters: {
- addressStr(state) {
- if (!state.address.provinceName) {
- return ''
- } else {
- return state.address.provinceName + state.address.cityName + state.address.countyName + state.address
- .detailInfo
- }
- }
- }
- }
- *****************************************************************************************
- import {
- mapState,
- mapMutations,
- mapGetters
- } from 'vuex'
-
- export default {
- name: "my-address",
- data() {
- return {
- // address: {}
- };
- },
- computed: {
- ...mapState('m_user', ['address']),
- ...mapGetters('m_user', ['addressStr'])
- },
- methods: {
- ...mapMutations('m_user', ['updateAddress']),
- 【54】重新选择收货地址
- <view v-else @click="pickAddress"
- style="font-size: 12px;height: 90px;display: flex;flex-direction: column;justify-content:
- center;padding: 0 5px;">
- *****************************************************************************************
- 解决收货地址授权失败的问题!!!!!!!!!!
- 我的项目好像没这个问题,牛批 162说解决了这个问题,但是我的不需要解决,哈哈哈
- 【55】封装结算区域的组件
- <template>
- <view style="position: fixed; bottom: 0;left: 0;width: 100%;height: 50px;background-color: yellow;">
- 结算组件
- </view>
- </template>
-
- <script>
- export default {
- name: "my-settle",
- data() {
- return {
-
- };
- }
- }
- </script>
-
- <style lang="scss">
-
- </style>
- *****************************************************************************************
- <template>
-
- <view style="position: fixed; bottom: 0;left: 0;width: 100%;height: 50px;background-color: white;display: flex;justify-content: space-between;
- align-items: center;font-size: 14px;padding-left: 5px;">
- <!-- 全选 -->
- <label style="display: flex;align-items: center;">
- <radio color="#C00000" :checked="true" />
- <text>全选</text>
- </label>
-
- <!-- 合计 -->
- <view>
- 合计:<text style="color: #C00000;font-weight: bold;">¥ 123.06</text>
- </view>
-
- <!-- 结算按钮 -->
- <view
- style="background-color: #C00000;height: 50px;color: white;line-height: 50px;padding: 0 10px;min-width: 100px;text-align: center;">
- 结算(0)
- </view>
- </view>
- </template>
-
- <script>
- export default {
- name: "my-settle",
- data() {
- return {
-
- };
- }
- }
- </script>
-
- <style lang="scss">
-
- </style>
- 【56】动态渲染已勾选商品的总数量!!!!!!!!!!!!!!!!!!!!!!!
- checkedCount(state) {
- // console.log(tempList)
- let total = 0
- state.cart.filter(x => x.state).forEach(item => {
- // console.log(item.count)
- total = total + item.count
- })
- return total
- }
- *****************************************************************************************
- 动态渲染全选的状态:
- computed: {
- ...mapGetters('m_cart', ['checkedCount', 'totalNum']),
- fullCheckFlag() {
- return this.totalNum === this.checkedCount
- }
- }
- 【57】商品的全选和反选功能
- updateAllGoodsState(state, newState) { // 更新所有商品的勾选状态
- state.cart.forEach(x => x.state = newState)
- this.commit('m_cart/saveToStorage') // 更新存储本地
- }
- *****************************************************************************************
- ...mapMutations('m_cart', ['updateAllGoodsState']),
- changeAllState() { // 改变所有商品的勾选状态
- // console.log("执行了")
- this.updateAllGoodsState(!this.fullCheckFlag)
- }
- *****************************************************************************************
- getGoodsCheckedPrice(state) {
- let total = 0
- state.cart.filter(x => x.state).forEach(item => {
- // console.log(item.count)
- total = total + item.price * item.count
- })
- return total.toFixed(2)
- }
- *****************************************************************************************
- ...mapGetters('m_cart', ['checkedCount', 'totalNum', 'getGoodsCheckedPrice']),
- *****************************************************************************************
- <view>
- 合计:<text style="color: #C00000;font-weight: bold;">¥ {{getGoodsCheckedPrice}}</text>
- </view>
- *****************************************************************************************
- 动态计算购物车徽标的数值,就是自己一直关注的tabBar数字不更新问题的处理!!!!
- import {
- mapGetters
- } from 'vuex'
-
- export default {
- computed: { // 把全局数据映射到购物车
- ...mapGetters('m_cart', ['totalNum'])
- },
- watch: { // !!!!!!!!!!!!!!!!!!!!!this one
- totalNum() {
- this.setBadge()
- }
- },
- onShow() {
- this.setBadge()
- },
- methods: {
- setBadge() {
- uni.setTabBarBadge({
- index: 2,
- text: this.totalNum + ""
- })
- }
- }
- }
- 【58】购物车细节渲染
- <view v-if="cart.length!==0">
- <!-- 空购物车 -->
- <view v-else style="display: flex;flex-direction: column;align-items: center;padding-top: 150px;">
- <image src="/static/cart_empty@2x.png" style="width: 90px;height: 90px;"></image>
- <text style="font-size: 12px;color: gray;margin-top: 15px;">购物车空空如也~</text>
- </view>
- 【59】170集 登录与支付
- settleClick() { // 用户点击了结算按钮
- if (!this.checkedCount) {
- return uni.$message("请选择要结算的商品")
- }
- if (!this.addressStr) {
- return uni.$message("请选择收货地址")
- }
- if (!this.token) {
- return uni.$message("请您先登录账户")
- }
- }
- 【60】登录页面UI的初步渲染
- 创建下我的页面的编译模式
- ********************************************************************************************
- 登录和登录后判断条件展示
- <!-- 登录组件 -->
- <my-login v-if="!token"></my-login>
-
- <!-- 登录后组件 -->
- <my-user-info v-else></my-user-info>
- ********************************************************************************************
- <template>
- <view>
- <uni-icons type="contact-filled" size="100" color="#AFAFAF"></uni-icons>
- <button type="primary" style="">一键登录</button>
- <text style="">登录后进行更多权益</text>
- </view>
- </template>
-
- <script>
- export default {
- name: "my-login",
- data() {
- return {
-
- };
- }
- }
- </script>
-
- <style lang="scss">
-
- </style>
- ********************************************************************************************
- <template>
- <view
- style="height: 750rpx;background-color: #F8F8F8;display: flex;flex-direction: column;justify-content: center;align-items: center;">
- <uni-icons type="contact-filled" size="100" color="#AFAFAF"></uni-icons>
- <button type="primary"
- style="width: 90%;border-radius: 100px;margin: 15px 0;background-color: #C00000;">一键登录</button>
- <text style="font-size: 12px;color: gray">登录后进行更多权益</text>
- </view>
- </template>
-
- <script>
- export default {
- name: "my-login",
- data() {
- return {
-
- };
- }
- }
- </script>
-
- <style lang="scss">
-
- </style>
- ********************************************************************************************
- <template>
- <view class="login-container" style="height: 750rpx;background-color: lightgray;display: flex;
- flex-direction: column;justify-content: center;align-items: center;position: relative;overflow: hidden;">
- <uni-icons type="contact-filled" size="100" color="#AFAFAF"></uni-icons>
- <button type="primary"
- style="width: 90%;border-radius: 100px;margin: 15px 0;background-color: #C00000;">一键登录</button>
- <text style="font-size: 12px;color: gray">登录后进行更多权益</text>
- </view>
- </template>
-
- <script>
- export default {
- name: "my-login",
- data() {
- return {
-
- };
- }
- }
- </script>
-
- <style lang="scss">
- .login-container {
- &::after {
- content: '';
- display: block;
- width: 100%;
- height: 40px;
- background-color: #F5F5F5;
- position: absolute;
- bottom: 0;
- left: 0;
- border-radius: 100%;
- transform: translateY(50%);
- }
- }
- </style>
- 【61】点击按钮实现登录 172集
- open-type="getUserInfo" @getuserinfo="getUserInfo"
- 前面的那个更重要!!!!!!!!!!!!!!!!!!
- 【62】将用户的基本信息存储到本地
- updateUserInfo(state, userInfo) {
- state.userInfo = userInfo
- this.commit('m_user/saveUserInfoToStorage'); // 调用存储
-
- },
- saveUserInfoToStorage(state) {
- uni.setStorageSync('userInfo', JSON.stringify(state.userInfo))
- }
- ********************************************************************************************
- ...mapMutations('m_user', ['updateUserInfo']),
- getUserInfo(e) {
- if (e.detail.errMsg === 'getUserInfo:fail auth deny') {
- return uni.$message("您取消了登录授权")
- }
- this.updateUserInfo(e.detail.userInfo)
- // console.log(e)
- }
- 【63】调动uni.login获取用户登录凭证
- async getToken(info) { // 获取code的值
- // 获取code对应的值
- const [err, res] = await uni.login().catch(err => err)
-
- // console.log(res)
- if (err || res.errMsg !== 'login:ok') {
- return uni.$message('登录失败')
- }
- console.log(res.code)
- console.log(info)
- }
- 【64】获取token并存储到vuex
- 先继续写,后面可能需要改造login API
- uni.$http.post('/api/public/v1/users/wxlogin', sendData).then(res => {
- console.log(res)
- if (res.statusCode !== 200) {
- return uni.$message("登录失败!")
- }
- uni.$message("登录成功!")
- this.updateToken(
- "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1aWQiOjIzLCJpYXQiOjE1NjQ3MzAwNzksImV4cCI6MTAwMTU2NDczMDA3OH0"
- )
- })
- ********************************************************************************************
- 我设置的是假的Token,后台接口需要根据信息生成
- 【65】登录后信息布局展示
- <template>
- <view style="height: 100%;background-color: #F4F4F4;">
- <!-- 头像和昵称区域 -->
- <view
- style="height: 400rpx;background-color:#C00000;display: flex;justify-content: center;align-items: center;flex-direction: column;">
- <image :src="userInfo.url"
- style="width: 90px;height: 90px;border-radius: 45px;border: 2px solid #FFF;box-shadow: 0 1px 5px black;">
- </image>
- <view style="font-size: 16px;color: #FFF;font-weight: bold;margin-top: 10px;">
- {{userInfo.nickName}}
- </view>
- </view>
- </view>
- </template>
-
- <script>
- import {
- mapState
- } from 'vuex'
- export default {
- name: "my-user-info",
- computed: {
- ...mapState('m_user', ['userInfo'])
- },
- data() {
- return {
-
- };
- }
- }
- </script>
-
- <style lang="scss">
-
- </style>
- 【66】渲染第一个面板区域
- <!-- 1个面板 panel1-->
- <view>
- <view> <!-- panel-body -->
- <view> <!-- panel-item -->
- <text>8</text>
- <text>收藏的店铺</text>
- </view>
- <view> <!-- panel-item -->
- <text>14</text>
- <text>收藏的商品</text>
- </view>
- <view> <!-- panel-item -->
- <text>18</text>
- <text>关注的商品</text>
- </view>
- <view> <!-- panel-item -->
- <text>84</text>
- <text>足迹</text>
- </view>
- </view>
- </view>
- ********************************************************************************************
- <!-- 1个面板 panel1-->
- <view style="padding: 0 10px;position: relative;top:-10px;">
- <!-- panel-body -->
- <view
- style="background-color: white;border-radius: 3px;margin-bottom: 8px;display: flex;justify-content: space-around;">
- <!-- panel-item -->
- <view style="display: flex;flex-direction: column;align-items: center;justify-content: space-around;padding: 10px 0;
- font-size: 13px;">
- <text>8</text>
- <text>收藏的店铺</text>
- </view>
- <!-- panel-item -->
- <view style="display: flex;flex-direction: column;align-items: center;justify-content: space-around;padding: 10px 0;
- font-size: 13px;">
- <text>14</text>
- <text>收藏的商品</text>
- </view>
- <!-- panel-item -->
- <view style="display: flex;flex-direction: column;align-items: center;justify-content: space-around;padding: 10px 0;
- font-size: 13px;">
- <text>18</text>
- <text>关注的商品</text>
- </view>
- <!-- panel-item -->
- <view style="display: flex;flex-direction: column;align-items: center;justify-content: space-around;padding: 10px 0;
- font-size: 13px;">
- <text>84</text>
- <text>足迹</text>
- </view>
- </view>
- </view>
- 【67】渲染第二个面板区域
- <view style="padding: 0 10px;position: relative;top:-10px;">
- <!-- title -->
- <view
- style="line-height: 45px;padding-left: 10px;font-size: 15px;border-bottom: 1px solid #F4F4F4;background-color: white;">
- 我的订单
- </view>
- <!-- body -->
- <view
- style="background-color: white;border-radius: 3px;margin-bottom: 8px;display: flex;justify-content: space-around;">
- <!-- panel-item -->
- <view style="display: flex;flex-direction: column;align-items: center;justify-content: space-around;padding: 10px 0;
- font-size: 13px;">
- <image src="/static/my-icons/icon1.png" style="width:35px;height: 35px;"></image>
- <text>待付款</text>
- </view>
- <!-- panel-item -->
- <view style="display: flex;flex-direction: column;align-items: center;justify-content: space-around;padding: 10px 0;
- font-size: 13px;">
- <image src="/static/my-icons/icon2.png" style="width:35px;height: 35px;"></image>
- <text>待收货</text>
- </view>
- <!-- panel-item -->
- <view style="display: flex;flex-direction: column;align-items: center;justify-content: space-around;padding: 10px 0;
- font-size: 13px;">
- <image src="/static/my-icons/icon3.png" style="width:35px;height: 35px;"></image>
- <text>退款/退货</text>
- </view>
- <!-- panel-item -->
- <view style="display: flex;flex-direction: column;align-items: center;justify-content: space-around;padding: 10px 0;
- font-size: 13px;">
- <image src="/static/my-icons/icon4.png" style="width:35px;height: 35px;"></image>
- <text>全部订单</text>
- </view>
- </view>
- </view>
- 【68】第三个面板
- <!-- 3个面板 -->
- <!-- panel -->
- <view style="padding: 0 10px;position: relative;top:-10px;">
- <!-- panel list -->
- <view style="background-color: white;">
- <view
- style="display: flex;justify-content: space-between;align-items: center;font-size: 15px;padding: 0 10px;line-height: 45px;">
- <text>收货地址</text>
- <uni-icons type="arrowright" @size="15"></uni-icons>
- </view>
- <!-- panel list -->
- <view
- style="display: flex;justify-content: space-between;align-items: center;font-size: 15px;padding: 0 10px;line-height: 45px;">
- <text>联系客服</text>
- <uni-icons type="arrowright" @size="15"></uni-icons>
- </view>
- <!-- panel list -->
- <view
- style="display: flex;justify-content: space-between;align-items: center;font-size: 15px;padding: 0 10px;line-height: 45px;">
- <text>退出登录</text>
- <uni-icons type="arrowright" @size="15"></uni-icons>
- </view>
- </view>
- </view>
- 【69】退出登录功能的实现
- methods: {
- ...mapMutations('m_user', ['updateAddress', 'updateUserInfo', 'updateToken']),
- async logout() {
- const [err, success] = await uni.showModal({
- title: '提示',
- content: '确认需要退出登录吗?'
- }).catch(err => err)
-
- if (success && success.confirm) {
- this.updateAddress({})
- this.updateUserInfo({})
- this.updateToken({})
- }
- }
- }
- 【70】182集 3秒后跳转登录页面
- if (this.token.length === undefined) {
- // return uni.$message("请您先登录账户")
- return this.delayNav();
- }
- },
- showTips(n) { // 展示倒计时提示
- uni.showToast({
- icon: 'none',
- title: '请登录后再结算!' + n + '秒后自动跳转到登录页',
- mask: true,
- duration: 1500
- })
- },
- delayNav() { // 延迟导航到my登录页面
- this.showTips(this.endTime)
- setInterval(() => {
- this.endTime--
- this.showTips(this.endTime)
- }, 1000)
- }
- ********************************************************************************************
- delayNav() { // 延迟导航到my登录页面
- this.showTips(this.endTime)
- this.timer = setInterval(() => {
- this.endTime--
- if (this.endTime <= 0) {
- clearInterval(this.timer) // 清除定时器
- uni.switchTab({
- url: '/pages/my/my'
- })
- return
- }
- this.showTips(this.endTime)
- }, 1000)
- }
- 主要是判断+clearInterval的应用!!!!!!!!!!!!!!!!
- 和uni.switchTab的使用......................................
- ********************************************************************************************
- 解决endTime倒计时不会重置的问题,我自己解决的,好屌呀!!!!!!!!!!!!!!
- if (this.endTime <= 0) {
- this.endTime = 3
- }
- 【71】如果在登录成功之后,返回之前的页面 183集
- delayNav() { // 延迟导航到my登录页面
- if (this.endTime <= 0) {
- this.endTime = 3
- }
- this.showTips(this.endTime)
- this.timer = setInterval(() => {
- this.endTime--
- if (this.endTime <= 0) {
- clearInterval(this.timer) // 清除定时器
- uni.switchTab({
- url: '/pages/my/my',
- success: () => {
- this.updateRedirectInfo({
- openType: 'switchTab',
- from: '/pages/cart/cart'
- })
- }
- })
- return
- }
- this.showTips(this.endTime)
- }, 1000)
- }
- ********************************************************************************************
- navigateBack() {
- if (this.redirectInfo && this.redirectInfo.openType === 'switchTab') {
- uni.switchTab({
- url: this.redirectInfo.from,
- complete: () => {
- this.updateRedirectInfo(null) // 重定向后置为null
- }
- })
- }
- }
- 【72】在请求头重添加Token身份认证字段
- 搞半天其实是为了安全保证...
- // 请求开始之前做一些事情
- $http.beforeRequest = function(options) {
- uni.showLoading({
- title: "数据加载中..."
- })
- // console.log("我0604:" + JSON.stringify(options))
- if (options.url.indexOf('wx') !== -1) { // 这是包含的情况
- options.header = {
- Authorization: store.state.m_user.token
- }
- }
- // console.log("我0604:" + JSON.stringify(options))
- }
- 【73】了解微信支付的概念
- 创建订单,返回订单编号
- ********************************************************************************************
- 订单预支付
- ********************************************************************************************
- 发起微信支付
- 【74】创建订单API接口
- // 2创建订单 - 发起请求
- uni.$http.post('/wx_buy', sendData).then(res => {
- // console.log("0604打印" + JSON.stringify(res))
- if (res.data.code !== '200') {
- return uni.$message("订单创建失败")
- }
- const orderNumber = res.data.object.no; // 订单编号
- // console.log("0604打印" + orderNumber)
- })
- ********************************************************************************************
- 创建并返回订单编号,这个重点在后端
- 【75】实现订单的预支付 187集-----------!!!!!!!!!!!!!!!!!!!!!!
- ********************************************************************************************
- 中间遇到了支付的问题。提交工商户审核
- 【76】发起微信支付
- uni.requestPayment(payInfo)
- 【77】微信小程序发布的流程
- 提升用户体验,缩小体积
- 【78】uniapp发布为小程序
- 点击Hbulid的发行
- ---------------------------------------------------------------------------------------------------------
- 小程序-微信(第5个)
- ---------------------------------------------------------------------------------------------------------
- 小程序名称+APPID
- ---------------------------------------------------------------------------------------------------------
- 这样发型的体积更小 更好用!!!!!!!!!!!!!!!!!这个还挺重要的!!!!!
- ---------------------------------------------------------------------------------------------------------
- 提交小程序审核即可
- 【79】发布为Android APP
- APP 图标配置
- ---------------------------------------------------------------------------------------------------------
- 发行—>原生APP—>云打包
- ---------------------------------------------------------------------------------------------------------
- 注意:选择收货地址、微信登录、微信支付是无法正常使用的!!!!!!!!

****************************************************************************************************************************************************************************
- 25、扩展功能:客服+虚拟充值
- 【1】UNIAPP滑动问题处理:paddingBottom: -100 + 'px', // this.safeAreaInsets
- 【2】校对与量控制,打通除回调支付外的隐藏支付...哈哈哈!!!!!!!!!!!!
****************************************************************************************************************************************************************************
- 26、总要有所突破
- 【1】Ws长链接!!!!!!!!!!!!
- 【2】Socket
- 客户端要有Socket、服务端也要有Socket
- *************************************************************************************
- 客户端的要和服务器的建立连接,必须要知道服务器的IP地址。
- 通过Socket传到服务端,服务端同样也可以通过Socket传到客户端。
- *************************************************************************************
- 只要链接不断开,服务端和客户端都可以主动推送消息
- 【3】应用场景:
- 在20230615终于实现了稳定的聊天小程序
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。