day1 :
1, 申请账号 ,找到appid
2, 下载工具
3, 创建git ,使用git仓库来使用tag来管理项目
// 关联项目到自己的仓库
git remote add origin https://github.com/a654688383/learnMiNiProgramer.git
// 上传项目
git push -u origin master
// 修改项目 打tag提交
git add .
git status
git commit -m "testTag1"
git tag testtag1
// 查看日志 切换tag
git tag
git checkout testtag1
// 提交 tag到远程
git push --tags
// 切换到某个tag ,注意这个时候 处于 tag所在的快照分支 ,非master ,提交代码 需要切换到mastergit checkout testtag1
// 回滚到某个版本 回退到某个版本 取hash的某一段
git log
git reset --hard hashvalue
4,删掉项目 ,搞清app和pages 都是干嘛的, 搞清 json,js,wxss,wxml都是干嘛的, 然后根据报错从头创建一遍,有快捷键。
*******************************************
day2
1, project.config.json / sitemap.json / app.json / app.js / app.wxss / page.json 都是干嘛的
1,project.config.json // 项目的 配置文件
2, sitemap.json // 小程序搜索相关的可配置
3, app.json // 全局的配置
4, app.js // 全局的生命周期相关
5,app.wxss // 全局的样式配置
5. page.json // 局部页面设置
2, mvvm
// mvvm m:model v: view vm :viewModel
viewModel 干了两件事:
a: domListeners 监听dom
b: data bindings 绑定数据,根据数据改变dom
*********************************
1, react 和 vue的 mvvm
view // DOM
model // js obj
mvvm // react vue
2, 小程序的 mvvm
view // DOM
model // APP service 逻辑层
mvvm // Mina框架 小程序框架
3,小程序的双线程模型
宿主环境为了执行小程序的各种文件 ,提供了双线程模型:
1. 渲染层 WXML WXSS 运行于渲染层,以页面为单位分为多个线程
2. 逻辑层 js脚本使用jsCore运行于逻辑层
这两种线程 经由 微信客户端进行中转交互
*******************************************
day3
1,了解小程序的生命周期
// 小程序的生命周期
1,下载小程序包
2,启动小程序
3,加载app.json
4, 注册app(),执行生命周期函数
5,加载自定义组件,注册自定义组件
6. 加载解析 page.json
7, 渲染层加载page.WXML, 逻辑层注册page();
8,执行page的生命周期;
*****************
App({
/**
* 当小程序初始化完成时,会触发 onLaunch(全局只触发一次)
* 一般获取用户信息
*
*/
onLaunch: function () {
wx.getUserInfo({
success:(e)=>{
console.log(e.userInfo)
}
})
// setTimeout(()=>{throw new Error()},1000)
},
/**
* 当小程序启动,或从后台进入前台显示,会触发 onShow
* 小程序在后台的存活时间,一般为两个小时
* * 判断小程序进入场景
* 通过用户信息来发请求给服务器
*/
onShow: function (options) {
console.log(options.scene)
},
/**
* 当小程序从前台进入后台,会触发 onHide
*/
onHide: function () {
},
/**
* 当小程序发生脚本错误,或者 api 调用失败时,会触发 onError 并带上错误信息
*/
onError: function (msg) {
console.log('error',msg)
},
/**
*
* 当小程序页面找不到的时候
*/
onPageNotFound:function(){
}
})
2, 了解获取用户信息的三种方式
1, wx.getUserInfo 即将废弃
wx.getUserInfo({
success:(e)=>{
console.log(e.userInfo)
}
})
2. button 官方推荐 需要用户点击
<button
open-type="getUserInfo"
bindgetuserinfo="getUserInfoHandle"
>按钮</button>
getUserInfoHandle:function(e){
console.log(e.detail.userInfo)
},
3. open-data标签 只做展示
<open-data type='userNickName'></open-data>
3 ,了解getApp() 获取全局实例
1, 在app中定义
globalData:{
name:'xiaoming',
age:'111'
}
2. 在page.js中操作
const app = getApp();
let {name,age} = app.globalData;
console.log(name, age)
// pages/home/home.js
Page({
/**
* 页面的初始数据
*/
data: {
name: name,
age:age
},
)}
3, 在html中使用变量
<view>{{name}}</view>
<view>{{age}}</view>
4 ,了解request请求
1, 使用wx.request({})
一般入参对象有几个属性参数, url, success ,error ....,
2, 如果没有配置域名,那么会发不出去请求,调试的时候可以设置不校验域名
3, 尽量所以的回调函数 使用箭头函数
5,常用属性
1,id
2,class
3,style
4,hidden
5,data-*
6,bind/catch
day4
1, 了解rpx
1, 这个单位是以750px(iphone6 375 *2) 屏幕为标准模版。其他屏幕自适应。
2, 放手机上,一般就是 1px = 2rpx; 比如 iphone6 下满屏 375px 就写 750rpx;
3, 所以调试样式的时候就在iphone6上去调试就好了
2,了解样式引入复用, 还有官方的ui库还有使用;
3, 了解wxs
wxs的特性
1, 写起来差不多跟js一样,只能使用es5以下的语法
2,不能够作为事件的回调函数, 不能够能拿到其他模块的变量方法,只能作为局部存在
3,在ios中wxs比js块 2到20倍,在安卓无差异
个人觉得可以作为工具函数来使用
写法有两种 :
1, 自建wxs
// utils.wxs
function process(a,b){
return a + b;
}
var price = '20';
module.exports ={
process:process,
price: price
}
//在wxml中使用
<wxs src='../../utils/utils.wxs' module='info'/>
<view>{{info.process(10,20)}}</view>
<view>{{info.price}}</view>
2.局部块wxs
<wxs module='info'>
function process(a,b){
return a + b;
}
var price = '20';
module.exports ={
process:process,
price: price
}
</wxs>
<view>{{info.process(10,20)}}</view>
<view>{{info.price}}</view>
4,了解template 语法
template
1, 模版语法在以前没有组建的情况下,主要是提供了 html的复用
2, 可以配合 import使用,但是无法递归引用模版
3, 可以使用变量,data属性传入
4, 必须有name属性, 也是其唯一标识,使用的话是is属性
使用起来有两种方式
1, 自建template 文件夹
// template.wxml
<template name='info'>
<view>{{name}}</view>
<view>{{age}}</view>
</template>
// 在wxml中使用
<import src='../../template/template.wxml' />
<template is='info' data="{{name:'xiaoming',age:18}}" />
2, 使用局部模块 template
<template name='info'>
<view>{{name}}</view>
<view>{{age}}</view>
</template>
<template is='info' data="{{name:'xiaoming',age:18}}" />
**********************
import
import可以引用 template
include
可以引入 除了template,wxs的文件, 算是复制, 可以递归导入wxml
day5:
1,组件都都有自己的特殊事件类型
input 有bindinput/bindblur/bindfocus
scroll-view 有 bindscrolltowpper/bindscrolltolower
2, 所以组件共有的事件
1,touchstart // 手指触摸开始
2, touchmove // 手指触摸并且移动
3,touchcancel // 来电弹窗打断触摸操作,不常用
4,touchend // 手指触摸结束
5,tap // 手指点击
6,longpress // 手指点击超过了350ms以上,和tap只会生效其中一个
7,longtap // 手指点击超过了350ms以上,推荐使用longpress替代
3,绑定事件的形式 以及写法
形式有两种:
1, bind 冒泡 事件从目标向外冒泡
2, catch 捕获 事件从外往内捕获传递
bind 的写法:
1 , bindtap='xxx'
2, bind:tap='xxx'
4, 事件对象 event
1, type 事件类型
2, timeStamp 页面打开到触发事件经过的毫秒数
3, target 触发事件的组件的一些集合属性
4, currentTarget 当前触发事件的组件的一些集合属性
5, detail 额外的信息, 一般的data-xx 会传递进来
6, touches 触摸事件的触摸点的信息数组
7, changedTouches 触摸事件,当前变化的触摸点的信息数组
5,传递数据 data-*
小程序向组件传递数据是data-*,然后在事件的event.currentTarget.dataset中就可以拿到*了,
<view
bindtap="handleClick"
data-index="11"
>111</view>
handleClick:(event)=>{
console.log(event.currentTarget.dataset)
}
day 6:
1,小程序组件基本
小程序组件由四部分组成
json js wxml wxss
需要放到component文件夹下
****************
使用
1, 建立组件
2 , 在 需要引用的页面引入组件
{
"usingComponents": {
"test":"../../../component/test/test"
}
}
3, 在页面使用组件
<test>
</test>
<test/>
4 hidden show 对自定义组件无效,需要用v-if
2,组建的注意事项
1, wxml的节点标签名字,只能是字母,中划线和下划线组成的组合,数字偶尔也可以
2,自定义组件可以引用其他的自定义组件
3,不要以 wx 作为前缀 微信
4,如果是全局组件,那么在 app.json里注册 就可以全局复用了
3, 自定义组件的样式 细节
1, 为了不造成 样式之间的混淆, 官方推荐使用class 不推荐使用id,属性,标签选择器。
4,组件页面 通信
页面对组件之间传递 :
1,数据 properties
在组件属性定义好外部传入的值得相关项
properties: {
// name: String, // 此写法没有默认值
name:{
type:String,
value:'defaultName',
observer:function(newValuye, oldValue){ // 新值替换老值
console.log(newValuye, oldValue);
}
}
},
在页面内使用
<test name='1'/>
<test name='2'/>
<test name='3'/>
在组件内部使用值
<!--component/test/test.wxml-->
<view >{{name}}</view>
2,样式
在组件中定义能传过来的样式
externalClasses:['props-class'], // 从父组件传递到组件样式值的变量,注意 驼峰不认识, 主流中划线
在组件中使用该样式
<!--component/test/test.wxml-->
<view class="props-class">{{name}}</view>
在页面中使用
<test name='1' props-class="red"/>
<test name='2' props-class="blue"/>
<test name='3' props-class="green"/>
在样式中定义
.red{
color:red;
}
.blue{
color:blue;
}
.green{
color:green;
}
3,标签插槽, slot
分为两类插槽,一类是 单个插槽, 另外一类是 多个插槽
#单个插槽
第一步预留插槽
<!--component/test/test.wxml-->
<view >header</view>
<slot/>
<view >footer</view>
第二步 使用组件和插槽
<test >
<view>woshichacao</view>
</test>
#多个插槽
第一步 ,在组件中先开启新属性
options:{
multipleSlots:true
},
第二步, 给slot们起个name属性
<view >header</view>
<slot name='slot1'/>
<slot name='slot2'/>
<slot name='slot3'/>
<view >footer</view>
第三部 在页面使用slots ,主要是 slot属性, 顺序 无所谓
<test >
<view slot='slot1'>111</view>
<view slot='slot2'>111</view>
<view slot='slot3'>111</view>
</test>
**************
组件对页面之间传递 :
自定义事件
组件的事件要写到method属性中
第一步,声明组件要发射的方法
click(){
this.triggerEvent('click',{params:1},{}); //核心方法: 第一个参数是事件名字,第二个参数是数据,第三个参数是其他选项,
}
第二步 组件中使用这个方法
<button size="mini" bindtap="click">+1</button>
第三步 在页面绑定这个方法
<view>{{count}}</view>
<test bind:click='add'/>
第四部 在页面中注册这个对应绑定的方法
data: {
count:0
},
add(obj){
console.log(obj.detail) // 传递过来的参数
this.setData({
count: ++this.data.count
})
}
、、、、、、、、、、、、、、、
通过页面来改变组件内部的数据 (不传值直接操作实例)
第一步,组件内定义变量并且在组件内使用
/**
* 组件的初始数据
*/
data: {
name:'李刚'
},
<view >{{name}}</view>
第二步, 在页面使用组件
<view bindtap="changeName">clickme</view>
<test id='name' />
第三步, 直接改变组件内部的值
changeName(){
const ele = this.selectComponent('#name');
ele.setData({name:'王健林'});
}
最后 应该是规范一下吧这个改变接口的方法在内部暴露出去 然后外部统一调用修改;
一,在组件内自定义函数
/**
* 组件的方法列表
*/
methods: {
changeName(params){
this.setData({name:params});
}
}
二, 在页面调用组件实例的方法
const ele = this.selectComponent('#name');
ele.changeName('王健林');
5,组件的构造器component 对象
1. properties
2. data
3. methods
4. externalClasses
5. options
6. observers:{ // 监听properties ,data属性的变化;
name(newvalue){ // 只有新值 ,没有老值
console.log(newvalue)
}
}
7. 组件中的生命周期函数 ,一类是本组件的生命周期 ,另外一类是可以监听所在页面的生命周期
lifetimes: { // 本组件的生命周期
created(){}, // 创建
attached(){}, // 组件被添加到页面中
ready(){}, // 被渲染出来
movied(){}, // 位置移动
detached(){} // 移除掉
},
pageLifeTimes: { // 可以监听所在页面的生命周期
show(){},
hide(){},
resize(){},
}
day7:
1,网络请求 wx.request
注意: 没有指定域名,又希望调试 ,就到详情---本地设置---勾选不校验域名即可
wx.request方法使用对象需要包含很多个参数:
1,url
2,data
3, header 头部信息
4, method
5, dataType 告诉服务器,我要想什么格式的数据 一般是json ,或者string
6, responseTyoe 你告诉服务器,让服务器返回什么样的数据类型给你 ,一般是文本 可以是流 图片
7, success
8, fail
9, complete 结束的函数,相当于finaly
2,封装该请求
export default function request(options){
return new Promise( (resolve,reject)=>{
wx.request({
...options,
url: options.url || '',
data: options.data || {},
method: options.method || 'get',
success: resolve, // resolve,reject 也是一个带参函数
fail: reject,
})
})
}
在页面使用
/**
* 当小程序初始化完成时,会触发 onLaunch(全局只触发一次)
* 一般获取用户信息
*
*/
onLaunch: function () {
request({
url:'http://123.207.32.32:8000/recommend'
}).then((res)=>{
console.log(res)
})
},
day8
1, 展示系统弹窗
一共分为四类
1, toast
wx.showToast({ // 其他的看参数就好
title: 'iii', // 标题
icon:'' , // 可以使用 自定义本项目内的如片 默认是对勾
})
2, modal 展示一个弹窗 取消确定
wx.showModal({ // 其他的看参数就好
title: 'iii', // 标题
content:'ppppp',
})
3, loading
wx.showLoading({ // 其他的看参数就好
title: '111', // 标题
mask:true, // 蒙版
})
setTimeout(()=>{wx.hideLoading()},2000)
4, actionsheet //下拉 选项
wx.showActionSheet({
itemList: ['111','222'],
})
2,使用分享
小程序只能分享给好友,不能分享到朋友圈,最多分享二维码到朋友圈
在页面内实现这个函数就可以实现分享功能
onShareAppMessage:function(options){ // 实现这个函数就可以定制分享了
return {
title:'爆款',
path:'', // 以/为开头的完整路径 默认是首页
imageUrl:'https://s10.mogucdn.com/mlcdn/c45406/180917_18l981g6clk33fbl3833ja357aaa0_750x390.jpg', // 没有就是当前网页的快照
}
}
如果说希望点击某个地方也出现分享,并不只是右上角的分享 ,那么需要这么干
<button sizi='mini' open-type="share">分享</button>
day 9 登录
1, 登录流程
前端 :
1, wx.login 得到code ,有效期五分钟
2,发送code 和标识 到后台 ,服务器返回一个 登录状态 ,比如token
3,讲token存储在小程序
4,请求需要登录态标识的token时, 携带token
后端 :
1, 凭借 appid + code + appsecret 换回 seesion_key + openid ,
2, 自定义登录状态与 session_key,openid关联,返回前端token
3, checkcode 这步就通过token 检查 session_,openid
2, 实现登录
1,登录函数 登录 拿到 token ,前端存储在storage, app内存存储各一份
2, 优化请求,检查存储token当前结果 ,
(1),没有直接去发请求
(2),有的话检查状态 一 过期直接去发请求, 二,没有过期给 当前 app内存存储一份
day10
1, 页面跳转 - navigator 组件
navigator 组件的四个属性
1, target 在哪个目标发生跳转 ,默认当前小程序
2, url 当前小程序内部跳转链接
3, open-type 跳转方式
3, detal 当 open-type 是 navigateBack的时候 ,返回的层数
open-type 的 6种类型:
1, navgate 普通跳转
2, redirect 替换当前页面跳转
3, switchTab 跳转到对应的tabbar页面,并且关闭所有的非tab页面
4, relaunch 关闭所有页面 ,打开这一个页面
5, navigateback 返回 页面
6, exit 退出小程序 target = 'minProgram'时生效
使用
<navigator url='/pages/about/about'>about</navigator>
2 , 页面跳转 - wx.api 跳转
点击按钮 然后跳转
<button size="mini" bindtap="gotoabout">gotoabout</button>
gotoabout(){
wx.navigateTo({
url: '/pages/about/about?name="111"',
})
}
所有 的 navifator的 opentype 都有对应的api
3, 跳转过程中 数据的传递
1, 父级页面向子级页面传递
父级页面
<navigator url='/pages/about/about?name="111"'>about</navigator>
子级页面
onLoad: function (options) {
console.log(options)
},
2, 子级页面向父级页面传递
/**
* 生命周期函数--监听页面卸载
*/
onUnload: function () {
//getCurrentPages 返回一个浏览历史栈
// 这个位置就可以拿到
const pages = getCurrentPages();
const home = pages[pages.length-2]; // 我觉得可遍历去拿个更稳定的值;
console.log(pages)
// 拿到页面实例操作页面数据, 其实可以优化到 页面内部方法去做这个事情
home.setData({name:'王健林'});
},
4,上拉加载更多
// 数据模型
titles:["流行","新款","精选"],
currentItem:'new',
goods:{
pop: { page: 0, list: [] },
new :{page:0,list:[]},
sell: { page: 0, list: [] },
}
// 请求方法
getGoods(type){
let page = this.data.goods[type].page+1;
fetchGoods({type,page}).then((res)=>{
console.log(res)
// case 1
// let listString = `goods.${type}.list`;
// let pageString = `goods.${type}.page`;
// this.setData({
// good:{
// ...this.data.goods,
// [type]:{
// list: [...this.data.goods[type].list, { aaa: 1 }],
// page:page
// }
// }
// })
// case 2
this.data.goods[type].list = [...this.data.goods[type].list,res.data];
this.data.goods[type].page= page;
this.setData({
goods: { ...this.data.goods}
});
})
},
// 触发上拉加载更多
onReachBottom(){
this.getGoods(this.data.currentItem)
}