微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

小程序

小程序基础

小程序构成

项目结构

pages # 用来存放页面
utils  # 用来存放工具类
app.js # 小程序的入口
app.json # 小程序配置文件
app.wxss # 小程序的全局样式
project.config.json # 小程序的项目配置
sitemap.json # 是否允许被微信索引

页面组成

# 每个页面由四个文件组成
.js # 页面的数据 处理函数
.json # 页面的配置
.wxml # 页面结构
.wxss # 页面样式

WXML和HTML

标签不同

HTML(div, sapn, img,a)
WXML(view,text,image,navigator)

属性节点不同

<a href="#"></a>
<navigator url="/pages/home/home"></navigator>

提供类似vue的模板

  • 数据绑定
  • 列表渲染
  • 条件渲染

WXSS 和 CSS

新增rpx尺寸单位

提供全局的样式和局部样式

支持部分选择器

  • .class 和 #id
  • element
  • 并集选择器 后代选择器
  • :: after 和 :: before

通讯模式

渲染层和逻辑层之间的通信

  • 由微信客户端进行转发

逻辑层和第三方服务器之间的通讯

  • 由微信客户端进行转发

小程序组件

view

<!--类似div-->
<view></view>

scroll-view滑动

横向滑动

<scroll-view class="main" scroll-x>
    <view>1</view>
    <view>2</view>
    <view>3</view>
</scroll-view>
.main{
  height: 100rpx;
  width: 100rpx;
  white-space: Nowrap;
}
.main view{
  display: inline-block; 
  height: 100rpx;
  width: 100rpx;
  background: rgb(35, 190, 21);
}

竖向滑动

<scroll-view class="main" scroll-y>
    <view>1</view>
    <view>2</view>
    <view>3</view>
</scroll-view>
.main{
  height: 100rpx;
  width: 100rpx;
  /* white-space: Nowrap; */
}
.main view{
  /* display: inline-block; */
  height: 100rpx;
  width: 100rpx;
  background: rgb(35, 190, 21);
}

swiper和swiper-item 轮播图

<swiper>
  <swiper-item>A</swiper-item>
  <swiper-item>B</swiper-item>
  <swiper-item>C</swiper-item>
</swiper>
# 属性
indicator-dots # 是否显示认false
indicator-color # 指示点的颜色
indicator-active-color # 选中点的指示颜色
autopay # 是否自动切换
interval #  时间间隔
circular # 是否衔接滑动

text 文本

<!--selectable 长摁选中-->
<text selectable>1393939393</text>

rich-text 将渲染html字符串

<rich-text nodes="<h1>qwe</h1>"></rich-text>

小程序API

监听事件API

以on开头,来监听某些事件的触发

wx 类似window

wx.onWindowResize(function) 监听窗口是否变化

同步API

以sync结尾的API

执行的结果可以通过函数返回直接获取

异步API

需要通过success ,fail , complete接收调用的结果

WXML

数据绑定

.js里定义数据

Page({
  /**
   * 页面的初始数据
   */
  data: {
    name: 'giao',
    age: 18
  },
})

.wxml 直接用

<view>{{name}}</view>
<view>{{age}}</view>

事件绑定

渲染层到逻辑层的通讯方式

可以将用户在渲染层的行为通过微信客户端反馈到逻辑层

常用

tap # 触摸(类似点击)
input # 输入框事件
change  # 状态改变

事件对象的属性列表

触发回调函数的时候, 会收到事件对象event

type # 事件类型
target # 触发事件的组件
currentTarget # 当前事件所绑定的组件
detail # 额外的信息

bindtap 触摸事件

Page({
  /**
   * 页面的初始数据
   */
  data: {
    count: 0
  },
  /**
   * 触摸函数
   */
  countAdd(e){
    // 通过e.target.dataset 获取参数
    console.log(e.target.dataset);
    // 修改data的值
    this.setData({
      count: this.data.count + 1
    })
  },
  /**
   * 输入框改变
   */
  onInputFn(e){
    console.log(e.detail.value);
    this.setData({
      msg: e.detail.value
    })
  },
})
<!-- bindtap不能传值 需要通过 data-名字 -->
<button bindtap="countAdd" data-num="{{1}}">+1</button>
<input value="{{msg}}" bindinput="onInputFn" type="text" />

条件渲染

<view wx:if="{{sex === 1}}">男</view>
<view wx:elif="{{sex === 2}}">女</view>
<view wx:else>妖</view>

包裹性质的组件 ,不会在页面渲染, 可以控制多个组件显示隐藏

<block wx:if="{{false}}">
  <view>block包裹</view>
  <view>block包裹</view>
</block>

hidden

隐藏元素

<view hidden="{{true}}">block包裹</view>

wx:if和hidden

  • wx:if 是动态销毁
  • hidden 是隐藏

列表渲染

<!-- wx:key 不用{{}} -->
<view wx:for="{{arr}}" wx:key="item">
  {{item}}
</view>

小程序配置

全局配置

app.json

pages # 所有小程序页面的存路径
window # 全局设置小程序窗口的外观
tabBar # 设置小程序底部的tabBar
style # 是否启用组件样式

windiw

"window":{
  	// 下拉刷新时 loading样式
    "backgroundTextStyle":"dark",
  	// 导航栏背景
    "navigationBarBackgroundColor": "#345333",
  	// 导航栏内容
    "navigationBarTitleText": "健康宝",
  	// 导航栏字体颜色
    "navigationBarTextStyle":"white",
  	// 开启下拉刷新
    "enablePullDownRefresh" : true,
  	// 下拉刷新时 背景
    "backgroundColor": "#efefef",
  	// 上拉触底 滚动条距离底部50px 加载数据
  	"onReachBottomdistance": 50
  },

tabBar

用于实现多页面切换, 渲染顶部的时候不显示icon

最少渲染两个, 做多渲染5个

"tabBar": {
  	// 背景颜色
    "backgroundColor": "#fff234",
  	// 字体颜色
    "color": "#fff",
  	// 边框颜色 black white
    "borderStyle": "black",
  	// 配置内容图标
    "list":[
      {
        // 路径
        "pagePath": "pages/nav/nav",
        // 内容
        "text": "nav",
        // 图标
        "iconPath": "/img/tabs/home.png",
        // 选中图标
        "selectedIconPath": "/img/tabs/home-active.png"
      },
      {},
      {}
    ]
  },

页面配置

会覆盖全局配置, 跟 window一致

小程序数据请求

出于安全考虑, 小程序官方对数据接口的请求做出来两个限制

  • 只能请求https类型的接口
  • 必须将接口的域名添加到信任列表
wx.request({
  url:'url',
  method: 'get',
  success: (res)=> {
    console.log(res);
  }
})
wx.request({
  url:'url',
  method: 'post',
  data:{},
  success: (res)=> {
    console.log(res);
  }
})

视图与逻辑

声明式导航

页面上声明一个导航组件, 点击跳转

<!-- 
  声明式跳转 
  url="/..."
  open-type="switchTab" 跳转配置tabBar
-->
<navigator url="/pages/msg/msg" open-type="switchTab">配置tabBar</navigator>

<!-- 
  声明式跳转 
  url="/..."
  open-type="navigate" (可选) 跳转配置没tabBar
-->
<navigator url="/pages/info/info" open-type="navigate">配置没tabBar</navigator>

<!-- 
  返回
  open-type="navigateBack"
  delta="1" (为一时可以不写)  返回页面数
 -->
<navigator open-type="navigateBack" delta="1">返回</navigator>

传参

<!--
  传参
  参数与路径之间使用?分隔
  参数键与参数值 用等号
  不同参数&
 -->
<navigator url="/pages/info/info?name=zs&age=18" open-type="navigate">配置没tabBar</navigator>

编程式导航

调用小程序的导航API, 实现跳转

wx.switchTab({
  // 路径
  url:'',
  // 成功
  success: () =>{},
  // 失败
  fail: ()=>{},
  // 成功失败都会执行
  complete: ()=>{}
})
  /**
   * 编程式导航
   * 跳转tabBar
   */
  onNavigator(){
    wx.switchTab({
      url:"/pages/msg/msg"
    })
  },
  /**
   * 编程式导航
   * 跳转非tabBar
   */
  onNavigatorTo(){
    wx.navigateto({
      url: '/pages/info/info'
    })
  },
    
    
  /**
   * 返回
   */
  onBack(){
    wx.navigateBack({
      // 可选不写就是1
      delta: 1, 
    })
  },
<!-- 编程式跳转 -->
<button type="primary" bindtap="onNavigator">编程式跳转tabBar</button>
<button type="primary" bindtap="onNavigatorTo">编程式跳转非tabBar</button>

<!--返回-->
<button type="primary" bindtap="onBack">返回</button>

传参

/**
 * 编程式导航
 * 跳转非tabBar
 */
onNavigatorTo(){
  wx.navigateto({
    url: '/pages/info/info?name=zs&age=18'
  })
},

接收参数

/**
 * 生命周期函数--监听页面加载
 */
onLoad(options) {
  // 传递的参数
  console.log(options);
  this.setData({
    query: options
  })
},

下拉刷新

全局 app.json window节点 enablePullDownRefresh: ture

局部 .json enablePullDownRefresh: true

  /**
   * 页面相关事件处理函数--监听用户下拉动作
   */
  onPullDownRefresh() {
    this.setData({
      count: 0
    })
    // 关闭下拉刷新
    wx.stopPullDownRefresh({
      success: (res) => {
        console.log(res);
      },
    })
  },

上拉触底

"onReachBottomdistance": 50 距离底部50

  /**
   * 页面上拉触底事件的处理函数
   */
  onReachBottom() {
    this.getColor()
  },

loading显示隐藏

wx.showLoading({
  title: '加载',
})
wx.hideLoading()

生命周期

应用生命周期

特指小程序从启动 运行 销毁的过程

页面生命周期

特指小程序, 每个页面的加载 渲染 销毁

  /**
   * 生命周期函数--监听页面加载
   * 只调用一次
   * options 当前页面获取的传参
   */
  onl oad(options) {

  },

  /**
   * 生命周期函数--监听页面初次渲染完成
   * 可以进行交互
   */
  onReady() {

  },

  /**
   * 生命周期函数--监听页面显示
   * 进入前台
   */
  onShow() {

  },

  /**
   * 生命周期函数--监听页面隐藏
   * 切入后台
   */
  onHide() {

  },

  /**
   * 生命周期函数--监听页面卸载
   * navigateBack 
   */
  onUnload() {

  },

  /**
   * 页面相关事件处理函数--监听用户下拉动作
   */
  onPullDownRefresh() {

  },

  /**
   * 页面上拉触底事件的处理函数
   */
  onReachBottom() {

  },

  /**
   * 用户点击右上角分享
   */
  onShareAppMessage() {

  }

wxs

数据类型

number  数值类型
string  字符串
Boolean 布尔
object  对象
function 函数
array   数组
date    日期
regexp  正则

语法

支持普通函数 var定义 类似Es5 , 遵循commonjs

<view>{{n1.giao('giao')}}</view>

<wxs module="n1">
  module.exports.giao = function(str){
    return  str + 123
  }
</wxs>

可以写成wxs文件

<wxs src="" module=""></wxs>

自定义组件

创建组件

创建components文件夹
创建text文件夹 右键 点击新建Component

引用组件

局部引用

只能在当前页面被引用

.json下添加

{
  "usingComponents": {
    "text-01" : "/components/text/text"
  }
}

// 调用 <text-01></text-01>

全局引用

可以再每个页面使用

app.json下添加

{
  "usingComponents": {
    "text-01" : "/components/text/text"
  }
}

// 调用 <text-01></text-01>

组件和页面的区别

  • json 需要声明 "component": true,
  • js 中调用 Component()
  • 事件处理函数定义到methods

组件样式隔离

组件与页面之间互不影响

只有class会有样式隔离 , 不要使用Id , 属性, 标签选择器

修改样式隔离选项

"styleIsolation": "isolated"
// isolated 启用样式隔离
// apply-shared 页面能影响组件 , 组件影响不了页面
// shared  互相影响

数据方法属性

Component({
  /**
   * 组件的属性列表
   * 用来接收外界传的属性
   */
  properties: {
    max: {
      type: Number, //类型
      value: 10 // 认值
    }
  },

  /**
   * 组件的初始数据
   */
  data: {

  },

  /**
   * 组件的方法列表
   */
  methods: {

  }
})
this.setData({
  // 可以用setData修改 properties属性
  max: this.properties.max + 1
})

数据监听器

Component({
  observers: {
    //如果监听的数据太多 可以 obj.**
    '字段1,字段2.name':function(字段1,字段2){}
  }
})

纯数据字段

options:{
    // 正则 匹配上之后就是纯数据字段
    pureDataPattern: /^_/
},
  
_data: true  // 只能用于纯数据处理,不能用来渲染

组件声明周期

created # 组件刚创建 (不能调用setData)
attached # 组件进入页面节点树(可以发请求, 初始化数据)
ready # 在视图层布局完后执行
moved # 实例被移动到另一个节点树
detached # 组件被移出
Component({
  // 调用生命周期函数
  lifetimes: {
    attached(){},
    detached(){}
  }
})

组件在页面的声明周期

show  # 组件在页面被展示时
hide  # 组件在页面被隐藏时
resize # 组件页面尺寸发生变化
Component({
  // 调用页面生命周期函数
  pageLifetimes: {
   show: function(){},
   hide: function(){},
   resize: function(size){},
  }
})

插槽

<!--组件添加-->
<slot></slot>

<!--页面调用-->
<text-01>
  	// 插槽内容
	123
</text-01>

开启多个插槽

 options:{
   // 开启多个插槽
    multipleSlots: true
  },
<slot name="before"></slot>
<slot name="after"></slot>

<text-01>
  <text slot="before">before</text>
  <text slot="after">after</text>
</text-01>

通讯

属性绑定(父传子)

父向子传值, 只能传递普通类型的数据

<text-01 count="{{count}}"></text-01>
properties: {
    count: Number
},
<view>{{count}}</view>

事件绑定(子传父)

// 父页面
// <text-01 bind:giao="countAdd"></text-01>

// 在子js , 调用函数
this.triggerEvent('giao',{value:this.properties.count})

获取组件实例

可以获取组件的属性方法

<button bindtap="getText">获取text</button>
const child = this.selectComponent('.text')
child.setData({
  count: child.properties.count + 1
})

behaviors

实现组件间代码共享, 可以包含属性, 数据, 生命周期函数方法

Behaviors/index.js

module.exports = Behavior({
  //节点属性
  properties:{},
  // 私有属性
  data: {
    age:18
  },
  // 方法
  methods:{}
})
import Behavior from '../../Behaviors/index'
Component({
 behaviors: [Behavior],
})

npm包

Vant Weapp

小程序项目 直接安装 npm i @vant/weapp@1.3.3 -S --production

然后 点工具 构建npm

修改 project.config.json

{
  ...
  "setting": {
    ...
    "packNpmManually": true,
    "packNpmRelationList": [
      {
        "packageJsonPath": "./package.json",
        "miniprogramNpmdistDir": "./"
      }
    ]
  }
}

app.json 引入组件

"usingComponents": {
  "van-button": "@vant/weapp/button/index"
}
<van-button type="primary">测试按钮</van-button>

API Promise化

官方提供的API都是基于回调函数实现的, 容易造成回调地狱

miniprogram-api-promise

npm i --save miniprogram-api-promise@1.0.4

注意: 每一次安装完包都要构建npm

import {promisifyAll} from 'miniprogram-api-promise'
const wxp = wx.p = {}
// 把wx放到wxp上 , 在任何页面都可以 wx.p.request()
promisifyAll(wx,wxp)
async getPromise(){
  const res = await wx.p.request({
    url: 'url',
    method: 'get',
  })
  console.log(res);
},

Mobx

mobx-miniprogram # 创建store
mobx-miniprogram-bindings # 把store 绑定到组件
npm i mobx-miniprogram@4.13.2 mobx-miniprogram-bindings@1.2.1

store/index.js

import {action, observable} from 'mobx-miniprogram'

// observable 返回值就是store实例
export const store = observable({
  count1: 1,
  count2: 2,
  // get 计算属性
  get sum(){
    return this.count1 + this.count2
  },
  // action 修改store值 不能用箭头函数
  updateCount: action(function (num) {
    this.count1 = this.count1 + num
  })
})

页面使用

import {createStoreBindings} from 'mobx-miniprogram-bindings'
import {store} from '../../store/index'
Page({
  countAdd(e){
    this.updateCount(e.target.dataset.num)
  },

  /**
   * 生命周期函数--监听页面加载
   */
  onl oad: function (options) {
    // createStoreBindings 可以将store数据绑定到页面
    this.storeBingings = createStoreBindings(this,{
      store,
      // 字段和计算属性
      fields: ['count1','count2','sum'],
      // 方法
      actions: ['updateCount']
    })
  },
  
  /**
   * 生命周期函数--监听页面卸载
   */
  onUnload: function () {
    this.storeBingings.detroyStoreBindings()
  },
})
<text>{{count1}}+{{count2}}={{sum}}</text>
<button type="primary" bindtap="countAdd" data-num="{{1}}">+1</button>
<button  bindtap="countAdd" data-num="{{-1}}">-1</button>

组件使用

import {storeBindingsBehavior}  from 'mobx-miniprogram-bindings'
import {store} from '../../store/index'
Component({
  behaviors: [storeBindingsBehavior],
  storeBindings:{
    store,
    fields:{
      count1: 'count1',
      count2: 'count2',
      sum: 'sum'
    },
    actions:{
      updateCount: 'updateCount'
    }
  },
  methods:{
  	countAdd(e){
      this.updateCount(e.target.dataset.num)
    }
  }
})
<text>{{count1}}+{{count2}}={{sum}}</text>
<button type="primary" bindtap="countAdd" data-num="{{1}}">+1</button>
<button  bindtap="countAdd" data-num="{{-1}}">-1</button>

分包

什么是分包

把完整的小程序项目 , 按照需求划分成不同的子包 用户使用时按需加载

  • 可以优化小程序首次启动的下载时间
  • 多团队共同开发, 解耦协作

分包后项目构成

  • 主包: 启动页面 + tabBer页面 , 一些公共资源
  • 分包: 只包含和当前分包有关的页面资源

小程序启动时, 认会下载主包并启动主包页面, 当用户进入分包的某个页面, 客户端会把对应分包下载下来, 进行展示

**注意: ** 整个小程序不能超过16M, 单包不能超过2M

使用分包

小程序会按 subpackages 的配置进行分包, subpackages 之外的目录将被打包到主包中

// 进行分包声明
"subpackages":[
  {
    "root": "text1", //第一个分包目录
    "pages": [  // 分包下的页面
      "pages/info/info"
    ]
  },
  {
    "root": "text2",
    "pages": [
      "pages/info/info"
    ]
  }
],
  1. 主包无法引用分包的私有资源
  2. 分包之间不能引用私有资源
  3. 分包可以引用公共资源

独立分包

普通分包依赖主包

独立分包独立运行 , 不能引用公共资源

// 进行分包声明
"subpackages":[
  {
    "root": "text1", //第一个分包目录
    "pages": [  // 分包下的页面
      "pages/info/info"
    ],
    "independent": true // 声明独立分包
  }
],

分包预下载

进入指定页面, 下载需要用的分包

预下载大小限额2M

"preloadRule": {
  "pages/message/message":{
    // 在指定网络模式进行预下载
    "network": "all",
    // root名 下载哪些包
    "packages": ["text1"]
  }
},

自定义TabBar

配置信息 custom: true 是否开启自定义tabbar

app.json

{
  "tabBar": {
    "custom": true,
    // list 要保留 低版本兼容
    "list": [{
      "pagePath": "page/component/index",
      "text": "组件"
    }, {
      "pagePath": "page/API/index",
      "text": "接口"
    }]
  },
  "usingComponents": {}
}

跟根目录添加custom-tab-bar 文件 新建Component

编写代码即可

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐