学习小程序之《从入门到入土篇一》

268 阅读14分钟

前言

这篇文章是我之前学习小程序时做的笔记,最近拿出来整理了一下,适合刚学习小程序的小白,如果有不正确的地方请评论区留言,以便于及时改正错误

注册微信小程序账号

  1. 打开官网地址:mp.weixin.qq.com/
  2. 点击立即注册 注册账号
  3. 点击小程序
  4. 填写基本资料
  5. 获取AppID(点击开发管理,切换到开发设置就能看见AppID)

下载微信开发者工具

  1. 打开下载链接:developers.weixin.qq.com/miniprogram…
  2. 根据自己的系统下载相对应的

微信开发者工具基本设置

  1. 扫码登录
  2. 点击设置

image-20210830220837301.png 3. 用于更换主题

image-20210830220920076.png 4.代理方式选择不适用使用任何代理

image-20210830221118255.png 然后就可以创建自己的微信小程序项目了

1.点击加号创建

image-20210830221324026.png 2.appID是在微信公众号平台获取(也可以使用测试账号)

image-20210830221801290.png

初步认识下小程序的基本页面结构

全局

  • app.js:设置一些项目的全局变量
  • app.json:每一个新页面都必须在这个地方注册,项目的导航栏和窗口界面设置
  • app.wxss:项目全局样式
  • project.config.json:项目配置文件

页面局部

  • xxx.wxml:页面的结构
  • xxx.wxss:页面的样式
  • xxx.json:页面的配置文件
  • xxx.js:页面的脚本文件

认识配置文件 小程序项目中有四种配置文件

  • 项目根目录中的app.json 配置文件
  • 项目根目录中的project.config.json 配置文件
  • 项目根目录中的 sitemap.json 配置文件
  • 每个页面文件夹中的json 配置文件 下面咱就细说说每个配置文件的作用

app.json

是用来对微信小程序进行全局配置,决定页面文件的路径、窗口表现、设置网络超时时间、设置多 tab 等。先来了解app.json下几个基本配置项

  • pages:用于配置当前小程序所有页面的路径,如下图所示,pages是个数组,如果我们需要添加页面,就可以在pages数组下配置相对应的路径,开发工具会自动帮我们生成对应的文件夹,而写在 pages 字段的第一个页面就是这个小程序的首页(打开小程序看到的第一个页面)

image.png

  • window:用于全局定义小程序所有页面的背景颜色、文字颜色等,下图只是简单的几个配置,详细配置可点击官方文档参考来进行配置 image.png

  • style:用于全局定义小程序使用的样式版本,新版就是v2,如果不配置就会用老的样式,下图进行比较,左图v2版本,右图默认老版本

image.png

  • tabBar:用于配置底部标签栏(最少两个,最多五个),基本配置如下,详细配置可点击官方文档参考来进行配置
{
  "pages": [
    "pages/index/index",
    "pages/logs/logs"
  ],
  "window": {
    "navigationBarBackgroundColor": "#07c160", 
    "navigationBarTitleText": "导航栏标题文字内容",
    "navigationBarTextStyle": "black"
  },
  "sitemapLocation": "sitemap.json",
  "lazyCodeLoading": "requiredComponents",
  "tabBar": {
    "list": [
      {
        "pagePath": "pages/index/index",
        "text": "首页"
      },
      {
        "pagePath": "pages/logs/logs",
        "text": "日志"
      }
    ]
  }
  
}

属性类型必填说明
pagePathstring页面路径,必须在 pages 中先定义
textstringtab 上按钮文字
iconPathstring图片路径
selectedIconPathstring选中时的图片路径
  • sitemapLocation:用于指明sitemap.json的路径

project.config.json

project.config.json项目配置文件,用来记录对小程序开发工具所做的个性化配置

  • setting编辑相关的配置
  • appid 小程序ID
  • projectname 项目名称 setting对应的设置还可以在本地设置里面配置,会在setting配置里面进行同步
"setting": { 
    "urlCheck": true, //是否检查安全域名和TLS版本
    "es6": true, //是否启用es5转es6
    "postcss": true, //上传代码时样式是否自动补全
    "minified": true, //上传代码时是否自动压缩
    "checkSiteMap": true // 是否能被微信索引
  },

image.png

sitemap.json

sitemap.json是用来配置小程序页面是否能被微信索引,类似于pc网页的SEO,详细配置可点击官方文档配置

{
  "desc": "关于本文件的更多信息,请参考文档       https://developers.weixin.qq.com/miniprogram/dev/framework/sitemap.html",
  "rules": [{
  "action": "allow", // allow(允许所有页面被索引),disallow(不允许被索引),
  "page": "*"
  }]
}
属性类型必填默认值取值取值说明
actionstring"allow""allow"、"disallow"命中该规则的页面是否能被索引
pagestring"*"、页面的路径“*” 表示所有页面,不能作为通配符使用
paramsstring[]当 page 字段指定的页面在被本规则匹配时可能使用的页面参数名称的列表(不含参数值)
matchingstring"inclusive""exact","inclusive","exclusive","partial"当 page 字段指定的页面在被本规则匹配时,此参数说明 params 匹配方式
priorityNumber优先级,值越大则规则越早被匹配,否则默认从上到下匹配

json

json用来配置当前页面的外观,会覆盖全局app.json里面相同的配置项,配置与上述配置差不多,详细可点击官方文档进行查看

样式相关

rpx

rpx(responsive pixel): 可以根据屏幕宽度进行自适应。规定屏幕宽为750rpx。如在 iPhone6 上,屏幕宽度为375px,共有750个物理像素,则750rpx = 375px = 750物理像素,1rpx = 0.5px = 1物理像素。

样式导入

使用@import语句可以导入外联样式表,@import后跟需要导入的外联样式表的相对路径,用;表示语句结束。

// 样式一
/* common.wxss */
view {
  width:100rpx
}
// 导入样式一 
@import "common.wxss"
view {
  width:100rpx
}

语法相关

模板语法

小程序的模板语法适合vue里的Mustache语法是一样使用的,先在js里声明变量,用{{}}包裹变量在wxml使用就可以了

// wxml 
<view class="container">
// 模板语法
  <view>{{msg}}</view> 
// 三元表达式  true
  <view>{{num > 9}}</view> 
// 算数运算 19
  <view>{{num + 9}}</view>
</view>
// js
data: {
  msg:'小程序',
  num:10
},

条件渲染

  • wx:if
<view wx:if="{{length > 5}}"> 1 </view>
<view wx:elif="{{length > 2}}"> 2 </view>
<view wx:else> 3 </view>
  • hidden
<view class="container">
  <view hidden="{{true}}">表达式为true的时候隐藏</view>
  <view hidden="{{fasle}}">表达式为false的时候显示</view>
</view>

wx:if和hidden的区别

  • wx:if是以动态的创建和销毁元素的方式来控制对元素的显示与隐藏的,当初始条件为false的时候不会做任何操作,有为true的时候才会创建元素,控制条件复杂和不频繁的切换的时候使用wx:if
  • hidden是基于display:block/none来控制元素的显示与隐藏的,不管初始条件为true或者是false,都会创建该元素,当切换非常频繁的时候使用hidden

列表渲染

  • wx:for用于循环列表,需要绑定key值,建议是谓唯一值,可以提高渲染效率,如果没有唯一值可以绑定index,当我们不手动指定索引和当前项的变量的时候,默认是indexitem
  // 默认
  <view wx:for="{{list}}" wx:key="id">
    id:{{item.id}} ---  姓名:{{item.name}} --- 索引:{{index}}
  </view>
  // 手动指定
  <view wx:for="{{list}}" wx:key="id" wx:for-item="cur" wx:for-index="i">
    id:{{cur.id}} ---  姓名:{{cur.name}} --- 索引:{{i}}
  </view>

事件绑定

事件类型

事件类型触发条件
bindtap/bind:tap手指触摸后马上离开,类似HTML点击事件
bindinputinput/bind:input文本框输入触发
bindchange/bind:change状态改变的时候触发
touchstart手指触摸动作开始
touchmove手指触摸后移动
touchcancel手指触摸动作被打断,如来电提醒,弹窗
touchend手指触摸动作结束
<!--logs.wxml-->
<view class="container">
 <view bindtap="say">打招呼</view>
</view>
// logs.js  自定义函数与data平级
say() {
    console.log('你好');
}

事件对象的属性

属性备注
type触发的时间类型
target触发事件的组件里的属性集合
currentTarget当前组件里的属性集合
detail获取信息
timeStamp页面从打开到触发事件经过的时间(毫秒)
touches触摸事件,获取停留在触摸点的信息
changedTouches触摸事件,获取当前变化触摸点的信息

更改data里面的数据

this.setData({
   num: this.data.num + 1
})

事件传参

通过data-来进行传参,后面跟着自定义参数的名字,使用e.target.dataset来进行接收

 <view data-info="{{'你好'}}" bindtap="changeQuery">获取参数</view>
 changeQuery(e) {
    console.log(e.target.dataset.info);
  }

请求资源

使用wx.request()发送请求,具体配置点击官方文档进行查看

 wx.request({
    //请求接口地址
    url: 'url',
    // 请求方式
    method: 'GET',
    // 请求数据
    data: {
      name: '旺仔',
      age: 18
    },
    // 成功后的回调函数
    success: (res) => {
      console.log(res);
    }
 })

wxs

wxs是小程序的一套脚本语言,结合 WXML,可以构建出页面的结构,其作用场景一般用于过滤器, wxs遵循的是commonJs规范

  • 过滤一个时间戳
// 声明处理事件戳的函数
function formatTime(times) {
  if (times) {
    var time = getDate(times);
    var year = time.getFullYear();
    var month = time.getMonth() + 1;
    var date = time.getDate();
    var hour = time.getHours();
    var minute = time.getMinutes();
    var second = time.getSeconds();
    return year + "-" + add0(month) + "-" + add0(date) + " " + add0(hour) + ":" + 
    add0(minute) + ":" + add0(second);
  } else {
    return times
  }
}

// 补零
function add0(m) {
  return m < 10 ? '0' + m : m;
}

// 暴露formatTime函数
module.exports = {
  formatTime: formatTime
}
// index.js
Page({
  /**
   * 页面的初始数据
   */
  data: {
    date: Date.now()
  },
})
index.wxml
// 使用wxs
<view>{{ m1.formatTime(date) }}</view>
// src="wxs的路径" module="自定义名称"
<wxs src="../../utils/formatTime.wxs" module="m1"></wxs>

导航相关

  • url: 跳转页面的地址
  • target: 跳转目标
  • open-type: 跳转方式
  • delta: 当 open-typenavigateBack 时有效,表示回退的层数 导航部分详细配置请点击官方文档查看

声明式导航

导航跳转

使用<navigator />进行页面,跳转方式默认是navigate,如果是跳转到tabBar页面,跳转方式必须先为switchTab

  • 跳转到非tabBar页面
  <navigator url="/pages/list/list" open-type="navigate">导航到非tabBar页面</navigator>
  • 跳转到tabBar页面
  <navigator url="/pages/index/index" open-type="switchTab">导航到tabBar页面</navigator>

后退导航 返回到上个页面,可指定open-typenavigateBack即可,如果需要返回多级页面则可以加上delta,值为要后退的步数,默认是1

  <navigator open-type="navigateBack">后退一步</navigator>
  <navigator open-type="navigateBack" delta="1">后退一步</navigator>
  <navigator open-type="navigateBack" delta="3">后退三步</navigator>

导航传参

在url路径后面拼接即可

<navigator url="/pages/index/index?name=zs&age=13" />

编程式导航

导航跳转

  • 跳转到非tabBar页面,使用wx.navigateTo()
  wx.navigateTo({
    url: '跳转的url路径',
    // 成功后的回调函数
    success: (res) => {
      console.log(res);
    },
    // 失败后的回调函数
    fail: (err) => {
      console.log(err);
    },
    // 成功和失败都会触发的回调函数
    complete: (e) => {
      console.log(e);
    },
 })
  • 跳转到tabBar页面,使用wx.switchTab()
  wx.switchTab({
    url: '跳转的url路径',
    // 成功后的回调函数
    success: (res) => {
      console.log(res);
    },
    // 失败后的回调函数
    fail: (err) => {
      console.log(err);
    },
    // 成功和失败都会触发的回调函数
    complete: (e) => {
      console.log(e);
    },
 })

后退导航

wx.navigateBack({
   delta: 1 // 后退的的步数,默认为1
})

导航传参

wx.navigateTo({
  url:'/pages/index/index?name=zs&age=13'
})

生命周期

应用生命周期

  • onLaunch:小程序初始化完成时触发,全局只触发一次。参数也可以使用 wx.getLaunchOptionsSync 获取
  • onShow:小程序启动,或从后台进入前台显示时触发。也可以使用 wx.onAppShow 绑定监听。
  • onHide:小程序从前台进入后台时触发。也可以使用 wx.onAppHide 绑定监听。
  • onError:小程序发生脚本错误或 API 调用报错时触发。也可以使用 wx.onError 绑定监听。
  • onPageNotFound:小程序要打开的页面不存在时触发。也可以使用 wx.onPageNotFound 绑定监听。注意事项请参考 wx.onPageNotFound
App({
  onLaunch (options) {
    // 做一些初始化的事情
  },
  onShow (options) {
    // 在展示的时候触发
  },
  onHide () {
    // 在隐藏的时候触发
  },
  onError (msg) {
    // 报错的时候触发
  },
  onPageNotFound(res) {
    // 在跳转的时候找不到页面的时候触发
    wx.redirectTo({
      url: 'pages/...'
    }) // 如果是 tabbar 页面,请使用 wx.switchTab
  }
})

页面生命周期

  • onLoad:页面加载时触发。一个页面只会调用一次,可以在 onLoad 的参数中获取打开当前页面路径中的参数。
  • onShow:页面显示/切入前台时触发。
  • onHide:页面隐藏/切入后台时触发。 如wx.navigateTo或底部 tab 切换到其他页面,小程序切入后台等。
  • onUnload:页面卸载时触发。如wx.redirectTowx.navigateBack到其他页面时触发。 页面事件处理函数
  • onPullDownRefresh:监听用户下拉刷新事件。
  • onReachBottom:监听用户上拉触底事件。
  • onPageScroll:监听用户滑动页面事件。
  • onAddToFavorites:监听用户点击右上角菜单“收藏”按钮的行为,并自定义收藏内容。
  • onResize:页面尺寸发生变化或者屏幕翻转的时候触发。
  • onTabItemTap:点击tab时触发
  • onShareTimeline:监听右上角菜单“分享到朋友圈”按钮的行为,并自定义分享内容(注:只有定义了此事件处理函数,右上角菜单才会显示“分享到朋友圈”按钮)
//index.js
Page({
  data: {
    text: "学习小程序之《从入门到入土篇》"
  },
  onLoad: function(options) {
    // 当页面加载时做一些初始化。
  },
  onShow: function() {
    // 在展示的时候触发
  },
  onReady: function() {
    // 当页面渲染好后触发
  },
  onHide: function() {
    // 在隐藏的时候触发
  },
  onUnload: function() {
    // 页面卸载时触发
  },
  onPullDownRefresh: function() {
    // 下拉刷新的时候触发
  },
  onReachBottom: function() {
    // 上拉触底的时候触发
  },
  onShareAppMessage: function () {
    // 点击分享的时候触发
  },
  onPageScroll: function() {
    // 页面滚动的时候触发
  },
  onResize: function() {
    // 页面尺寸发生变化的时候触发
  },
  onTabItemTap(item) {
    //点击tab的时候触发
  },
 
})

自定义组件相关

组件是项目中必不可少的,可以有利于复用和代码的结构简化,在小程序中使用组件需要注意,先要在当前组件的json文件中声明自己是个组件,如果全局引用的话就在app.json里面引入,局部引用的话需要用到该组件的json文件中引用

  • 声明组件
{
  "component": true
}
  • 引用组件
"usingComponents": {
  //"组件名":"组件路径"
  "my-component":"../component/index/index"
}

组件属性

// component/test1/test1.js
Component({
  /**
   * 组件的属性列表
   */
  properties: {

  },
  /**
   * 数据监听器
   */
  observers: {

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

  },

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

  }
})

  • properties 用于接收外界传递过来的数据,用于组件传值,学过vue的同学应该知道这个属性相当于props用于接收传递过来的数据,
// test1 用于引用组件
<test2 money="100"></test2 >
// component/test1/test1.js
Component({
  /**
   * 组件的属性列表
   */
  properties: {
    money:{
      type:number  // 定义属性值的类型
      value:1  // 属性的默认值
    }
  },
})
  • observers:数据监听器,用于监听属性和数据的变化来执行操作,类似于vue的watch侦听器,可以监听多个
Component({
  /**
   * 组件的初始数据
   */
  data: {
    obj:{
      name:'小明',
      age:18
    }
  },

  /**
   * 数据监听器
   */
  observers: {
  // 监听obj.name属性
    'obj.name':function(newValue){
       // 执行操作
    }
  },
})

组件的隔离特性

在自定义组件中具有样式隔离的特性,每个组件都有自己的样式,引用组件的页面样式不会影响组件的样式,组件的样式也是不会影响页面的样式,全局样式也是对组件不能生效,注:只有class类名选择器才有隔离特性,其他的选择器没有隔离特性,当然也可以通过组件内的stylelsolation属性解除样式隔离

  • isolated:启用样式隔离,使用class类名选择器的样式不会互相影响
  • apply-shared:页面中的样式会影响到自定义组件,自定义组件的样式不能影响页面
  • shared:页面和自定义组件的样式可以互相影响
Component({
 options:{
    styleIsolation:'apply-shared' // 解除样式隔离
  },
})

组件传值

  • 属性绑定:用属性绑定实现父向子传值,只能传递普通类型数据,无法进行方法传递,在父组件中使用事件绑定传递参数,子组件使用properties进行接收 父组件:father
// component/father/father.js
Component({
  // 父组件内定义数据
  data: {
    name:'海绵宝宝'
  }
})
{
  "component": true,
  "usingComponents": {
    // 引入子组件
    "son":"/component/son/son"
  }
}
<!--component/father/father.wxml-->
<view>
  <view>父组件:{{name}}</view>
  ------------------------------
   <!-- 在父组件中使用子组件 name(子组件中用于接收的变量)="name"(父组件中定义的数据) -->
  <son name="{{name}}" ></son>
</view>

son

// component/son/son.js
Component({
  /**
   * 组件的属性列表
   */
  // 接收父组件中传递的值
  properties: {
    // 接收的变量名
    name: {
      // 类型
      type: String,
      // 默认值
      value: "辛迪"
    }
  }
})
<!--component/son/son.wxml-->
<view>
  <view>子组件:{{name}}</view>
</view>
  • 事件绑定:用事件绑定绑定实现子向父传值,可以传递任何类型的数据,在父组件中定义一个函数,传递给子组件,子组件使用this.triggerEvent('自定义事件名称',{参数对象}),将数据传送到父组件,父组件使用e.detail获取子组件传递来的数据 father
// component/father/father.js
Component({
  // 父组件内定义数据
  data: {
    name: '海绵宝宝'
  },

  /**
   * 组件的方法列表
   */
  methods: {
    updateName(e) {
      console.log(e.detail);
      this.setData({
        name: e.detail
      })
    }
  }
})
<!--component/father/father.wxml-->
<view>
  <view>父组件:{{name}}</view>
  ------------------------------
   <!-- 在父组件中使用子组件 name(子组件中用于接收的变量)="name"(父组件中定义的数据) -->
  <son name="{{name}}" bind:fatherUpdateName="updateName"></son>
  <!-- bind:fatherUpdateName(传递给子组件用于触发的方法名)="updateName"父组件中定义的方法 -->
</view>

son

// component/son/son.js
Component({
  /**
   * 组件的属性列表
   */
  // 接收父组件中传递的值
  properties: {
    // 接收的变量名
    name: {
      // 类型
      type: String,
      // 默认值
      value: "辛迪"
    }
  },

  /**
   * 组件的方法列表
   */
  methods: {
    // 更改姓名
    updateName() {
      this.setData({
        name: '派大星'
      })
      // 此时只能更改子组件的数据,不能更改该父组件的数据,需要使用this.triggerEvent调用父组件的方法来进行头部更新
      this.triggerEvent('fatherUpdateName','派大星')
    }
  }
})
<!--component/son/son.wxml-->
<view>
  <view>子组件:{{name}}</view>
  <button bindtap="updateName">点击更换名字</button>
</view>
  • 组件实例:通过this.selectComponent("id/class"),获取组件实例的方法直接访问子组件的方法和数据,只能使用idclass选择器 father
// component/father/father.js
Component({
  // 父组件内定义数据
  data: {
    name: '海绵宝宝'
  },

  /**
   * 组件的方法列表
   */
  methods: {
    updateName(e) {
      console.log(e.detail);
      this.setData({
        name: e.detail
      })
    },
    // 获取子组件实例
    getComponent(){
     const son =  this.selectComponent('#son')
     console.log(son);
    }
  }
})
<!--component/father/father.wxml-->
<view>
  <view>父组件:{{name}}</view>
  <button bindtap="getComponent">this.selectComponent获取子组件实例</button>
  ------------------------------
   <!-- 在父组件中使用子组件 name(子组件中用于接收的变量)="name"(父组件中定义的数据) -->
  <son name="{{name}}" bind:fatherUpdateName="updateName" id="son"></son>
  <!-- bind:fatherUpdateName(传递给子组件用于触发的方法名)="updateName"父组件中定义的方法 -->
</view>