创建小程序初始页面

weui 库
我们这边直接github中找到weui的样式例子库可复制相应的组件源码
weui的样式源码 下载后往app.wxss中引入@import 'static/css/weui.wxss'; 直接可以用了
端口配置异步请求
-
params 需要添加字符串参数 qs,执行安装命令
npm init -y,npm i qs -S取qs导入util中。在这当中由于小程序开启了ES6转码导致页面使用
async函数无法使用,故需要导入npm install regenerator-runtime --save dev取runtime.js到相应调用的页面中,具体参考微信小程序regeneratorRuntime is not defined解决方案 -
util.js中
const qs = require('../static/js/qs.js'); let baseURL = "http://192.168.2.120:5000/api/" let request = function(url,options) { let myUrl = `${baseURL}${url}`; //处理method,data,params => 查询字符串 //请求头 //合并对象data if(options.data) { tempOptions.data = data; } //如果params,添加查询字符串参数 if (options.params) { let urlQueryString = qs.stringify(options.params,{ addQueryPrefix: true, allowDots:true, }) myUrl += addQueryString; } return new Promise((resolve,reject) => { wx.showLoading({ title: '玩命加载中...', }) wx.request({ method: 'get', url: myUrl, success:resolve, fail: reject, complete: wx.hideLoading, ...options }) }) } module.exports = { formatTime: formatTime, request: request }app.js中导入工具对象
const { formaTime, request } = require('utils/util.js'); globalData: { //向外提供属性 userInfo: null, request, formaTime }编写好域名,直接页面调用,index.js
// 获取app的值 getApp() const {request} = getApp().globalData; const regeneratorRuntime = require('../../static/js/runtime.js'); onLoad: async function () { let result = await request('Profile/test',{ method: 'get', // params: {} }); console.log(result); },常见的功能开发
链接跳转
<navigator url="{{'/pages/list/list?id='+item.id}}" wx:for="{{swipe}}" wx:key="{{item.id}}">{{item.name}}</navigator> //链接跳转后获取 onLoad: function (options) { let {id} = options; console.log(id); },获取整个view的数据
bindtap="doSearchByQuery"for循环多层嵌套
<!-- 内外层都是item 会优先内层 --> <view class="item" wx:for="{{list}}" wx:key="{{index}}" wx:for-item="Q"> {{Q.title}} <view wx:for="{{Q.item_list}}" wx:key="{{index}}" data-index="{{index}}" data-item="{{item}}"> {{item.classfiy}} </view> </view>需要取值的话可以设置data-*系列去取到相应点击的值
页面滚动监听
onPageScroll(obj) {}tab实现切换展示不一样的数据分页

需求: 切换不同的栏目,加载出不同的数据,而且还能分页
解决: 定义出tab三个栏目不同的数据,一方面由于每个栏目都能分页,故定义出三组,每一组再拼接进请求到的数据。
const types = ['pop', 'new', 'sell'] //data goods: { pop: {page: 0, list: []}, new: {page: 0, list: []}, sell: {page: 0, list: []} }, //数据请求(传入相应的数据) // 2.3.将数据设置到data中的goods中 const page = this.data.goods[type].page + 1; const typeKey = `goods.${type}.list`; const pageKey = `goods.${type}.page`; this.setData({ [typeKey]: oldList, [pageKey]: page })其二我们定义的tab切换为子组件,需要每次切换传值到给页面中,页面可以根据标识显示相应的数据(w-goods也是将图片文字封装成子组件)
<w-goods goods="{{goods[currentType].list}}"/>需求: 固定住tab栏目(滑到相应的位置固定住)
解决: 如果普通的滑到某个位置让tab栏目固定住,就会出现闪跳得情况,所以我们可以复制出两份,让他到一定位置的显示出已经固定住的一份,隐藏另一个
<w-tab-control titles="{{titles}}" bind:tabclick="handleTabClick" id="tab-control" class="{{isTabFixed ? 'fixed': ''}}"/> <w-tab-control titles="{{titles}}" wx:if="{{isTabFixed}}"/>其二,我们需要获取到相应滚动到的高度,我们一开始加载完页面获取到高度会出现页面图片没加载完的情况,导致获取到的高度是少了图片的高度情况,那么我们可以监听图片的,等图片加载完再回调执行我们获取到高度
//子组件 <image src="{{item.image}}" bind:load="handleImageLoad"/> handleImageLoad() { if (!this.data.isLoad) { this.triggerEvent('imageload') this.data.isLoad = true } } //页面: 监听图片加载完回调有bindload handleImageLoad() { wx.createSelectorQuery().select('#tab-control').boundingClientRect(rect => { this.data.tabScrollTop = rect.top }).exec() },页面按钮跳转
通过某些按钮或者函数调用而导致底部的按钮切换需要配置
switchTab来实现的<navigator url="/pages/add/add" open-type="switchTab" class="item">添加</navigator>多项目管理方式

//上传
git add .
git commit -m '案例1'
git tag 案例1
//回滚初始
git log //查看分支
git reset --hard 复制其中一段tag的哈希值
git status //初始
//查看目前几个tag
git tag
//上传
git push --tabs
//代码查看
git checkout 案例1
数据处理
循环 wx:for
<view wx:for="{{list}}">{{item.name}}</view>
点击 bindtap=''
vue动态每次改变数据都能更改界面数据,是通过object.defineProperty监听变化
小程序需要this.setData({ counter: 100 })
vue 跟小程序的对比
- M:Model ,V:View , VM:ViewMode
- 视图层和数据层通过ViewMode在 DataBing和DomListener上实现交互

MINI框架了解,MVVM架构将我们从
命令式编程转移到声明式编程,具体两种声明式编程和命令式编程的理解
命令式编程:操作DOM

声明式编程: vue/React

相关文件说明
project.config.json 是相对于本地设置而生成的文件,目的是在不同的编辑器开发中起到配置的一致性,不用多次配置

小程序的双线程模型

Dom树

渲染出页面
WXML -> Js对象 -> 真正DOM树 -> WebView界面(渲染线程渲染) -> 数据发生变化 -> 逻辑层提供变化数据 -> JS对象进行diff算法对比 -> 反映到真正DOM树 -> 更新UI
此处中都是虚拟DOM操作,最后只有真正的DOM才起渲染页面的作用,拓展:减少DOM请求

界面渲染过程(diff算法)

这边是如何进行比较前后两个修改的JS对象的呢,又如何应用到原来的DOM上-->Diff算法在此处的重要性
小程序启动


获取用户信息 :
第一种: wx.getUserInfo
<button open-type="getUserInfo" bindgetuserinfo="onGetUserInfo">第二种</button>
<open-data type="userNickName">第三种</open-data>
<open-data type="userGender">第三种</open-data>
样式权重


条件
wx:if -- wx:elif -- wx:eles
WXS

<wxs module="info">
var name = '小米'
var age = '18'
function sum(num1,num2) {
return num1+num2;
}
module.exports = {
name: name,
age: age,
sum: sum
}
</wxs>
<view>{{info.name}}</view>
<view>{{info.age}}</view>
<view>{{info.sum(8,4)}}</view>
//一般情况下都是独立文件夹引入的(相对路径,记得module.exports抛出)
<wxs src="../../wxs/info.wxs" module="info" />
冒泡和捕获
bind: 一层层传递
catch: 阻止事件的进一步传递
<view catchtap="hand" capture-catch:tap="handview">
<view bindtap="hand1" capture-bind:tap="handview1"></view>
</view>
创建自定义组件
目录设置一般可以这样,层次感清晰

//json--此处可以使用绝对路径或是相对
"usingComponents": {
"my-cpn":"/components/my-cpn/my-cpn"
}
//wxml
<my-cpn></my-cpn>
- 如果自定义子组件相互引用也是支持的,写法雷同(用绝对路径实现更为方便点)
- 如果多个页面都是需要用到子组件那么我们可以在app.json中直接引用就可以了,就不再需要再各个页面引用
//app.json
"usingComponents": {
"my-cpn": "/components/my-cpn/my-cpn"
},
- 组件内的样式和外部样式是互不影响的,组件内不能使用id选择器,属性选择器,标签选择器
- 如果想组件内的样式会被外部样式影响,那么我们可以在子组件JS中设置
//my-cpn不设置为隔离
Component({
options: {
styleIsolation:'apply-shared'
},
})
// isolated/apply-shared/shared =>三种状态 隔离/子接受父影响 /互相伤害
命名规范
- WXML --- 小写字母,中划线,下划线
- 自定义组件和页面所在项目根目录名 不能以 'wx-'为前缀,否则报错
组件和页面通信

properties
子组件
<!--wxml-->
<view >{{title}}</view>
<!--js-->
properties: {
title: {
type: String,
value: '我是默认值',
observer:function(newVal,oldVal) { //对新旧值的监听
console.log(newVal,oldVal)
}
}
},
页面
<!-- 自定义组件 -->
<my-cpn title='我是父子'></my-cpn>
<my-cpn />
<my-cpn title='我也还能是这样'></my-cpn>
监听properties/data 的数据变化=> observers: {}
externalClasses(有点绕,其实你只要理清楚样式隔离就行了,哪里的样式注定在哪里才生效)
子组件
<!--wxml-->
<view class="titleclass">{{title}}</view>
<!--js-->
externalClasses: ['titleclass'],
页面
<!-- wxml -->
<my-cpn title='我是父子' titleclass="red"></my-cpn>
<my-cpn titleclass="green"/>
<my-cpn title='我也还能是这样'></my-cpn>
<!--wxss-->
.green {color: green}
.red { color: red}
自定义事件传递数据
子传给父-triggerEvent
子组件
<!--wxml-->
<button bind:tap="handclick">+1</button>
<!--js-->
methods: {
handclick() {
this.triggerEvent('icrement', { name: '小米' }, {}) //传值需要triggerEvent
}
}
页面
<!-- wxml -->
<view>点击了 {{count}}</view>
<my-btn bind:icrement="icrement"/> //写法方式切记如果你写成bindtap="icrement"是获取不到第二个的值
<!--js-->
icrement(event) {
console.log(event)
this.setData({
count: this.data.count + 1
})
},
父改变子,页面直接调用组件修改数据/方法,selectComponent获取到子组件的标签
子组件
<!--wxml-->
<view>页面来改变我点击次数{{countnum}}</view>
<!--js-->
data: {
countnum: 0,
},
methods: {
incrementCounter(num) {
this.setData({
countnum: this.data.countnum + num
})
}
}
页面
<!-- wxml -->
<my-slot id="self_id" class="self_class" />
<button bind:tap="click_btn">我要改变子页面</button>
<!--js-->
click_btn() {
const my_self = this.selectComponent('.self_class')
console.log(my_self)
my_self.incrementCounter(20)
},
slot 插槽
单插槽
子组件
<!--wxml-->
<view>我是头部</view>
<slot />
<view>我是底部</view>
页面
<!-- wxml -->
<z-slot>
<text>我是改变内容</text>
</z-slot>
多插槽 (multipleSlots: true)
子组件
<!--wxml-->
<view>我是头部</view>
<slot name="slot1"/>
<view class="xx"><slot name="slot2"/></view>
<slot name="slot3"/>
<view>我是底部</view>
<!--js-->
Component({
options: {
multipleSlots: true
},
})
页面
<!-- wxml -->
<z-slot>
<button slot="slot2" size="mini">我是插入第二个插槽</button>
<view slot="slot1">我是插入第一个插槽</view>
</z-slot>
子组件有两套生命周期

网络请求封装
wx.request()直接请求数据会出现 降低网络请求和wx.request的耦合度,使用pomise的方法获取回调。为什么要用Promise?

小程序登录
生成的code 只有五分钟有效期
