小程序介绍

206 阅读8分钟

小程序

优势

  • 用户粘性高
  • 开发成本低
  • 适配成本低
  • 容易小规模试错,快速迭代(不需要用户特意升级)

结构层

  • wxml
  • wxss
  • js
  • json

项目初始化

  • 删除logs文件夹
  • 保留Pages文件夹中的index.jspage({})
  • 保留Pages文件夹中的index.json{}
  • 保留app.jsonpage字段
  • wxss样式删除
  • wxml结构全删除

插件

  • prettier

全局app.json

{
	// 入口页面
  "entryPagePath": "pages/index/index",
  // 设置页面
  "pages": ["pages/test/index", "pages/index/index"],
  // 导航栏配置
  "window": {
    "navigationBarBackgroundColor": "#ff0",
    "navigationBarTitleText": "Not friendly",
    "navigationBarTextStyle": "black",
    "enablePullDownRefresh": true
  }
}

page.json

  • 可以对单独页面进行独立配置

    {
      "navigationBarBackgroundColor": "#f40",
      "backgroundColor": "#ff0",
      "enablePullDownRefresh": true
    }
    
    

绑定属性

  • 小程序开发不需要写:绑定
// index.js
Page({
  data: {
    msg: "这是文字",
    isLoading: true,
    id:9
  },
});

<!-- index.wxml -->
<!-- 正确写法 -->
<view id="{{id}}">{{msg}}</view>
<!-- 拼接写法 -->
<view id="item-{{id}}">{{msg}}</view>
<!-- 错误写法 -->
<view :id="item-{{id}}">{{msg}}</view>

显示隐藏

  • wx:if

  • hidden

  • 与vue语法有所不同

  • hidden与v-show稍有区别,条件为真是不会显示的

    <!-- 标签隐藏与显示 -->
    <view wx:if="{{isShow}}">wx:if显示隐藏</view>
    <view hidden="{{hidden}}">hidden显示隐藏</view>
    
    Page({
      data: {
        isShow: true,
        hidden: false,
      },
    });
    

判断语句

  • wx:if
  • wx:elif
  • wx:else
Page({
  data: {
    day: 5,
  },
});
<!-- 判断语句 -->
<view wx:if="{{day===1}}">星期一</view>
<view wx:elif="{{day===2}}">星期二</view>
<view wx:elif="{{day===3}}">星期三</view>
<view wx:else>星期四</view>

遍历

  • wx:for一定要配合插值使用(形参默认是itemindex

  • wx:for-item, wx:for-index这两个语法可以更改形参名字,便于在嵌套for时区分内容

  • 插值表达式前后要注意检查,不要加上空格或者其他字符,否则会被拼接成遍历字符串

    <!-- for循环 -->
    <view wx:for="{{list}}">{{item}}--{{index}}</view>
    <!-- 更改形参名字 -->
    <view wx:for="{{objList}}" wx:for-item="value" wx:for-index="i">{{value.name}}--{{value.id}}</view>
    <!-- 嵌套场景 -->
    <view wx:for="{{objList}}" wx:for-item="value" wx:for-index="i">
      <view wx:for="{{list}}">{{item}}--{{value.name}}</view>
    </view>
    
    
    Page({
      data: {
        list: ["深圳", "广州", "潮汕"],
        objList: [
          { id: 1, name: "小明" },
          { id: 2, name: "莎拉" },
          { id: 3, name: "小夫" },
        ],
      },
    });
    
    
    
  • index默认是键值对中的键,item是值

    <!-- item--值,index--键 -->
    <view wx:for="{{person}}">{{item}}--{{index}}</view>
    
    
    Page({
      data: {
        person: {
          age: 12,
          name: "孙悟空",
          skill: "fly",
        },
      },
    });
    
    
    

添加key,优化就地更新策略

  • wx:key="值唯一的键名"
    • 作用:与vue一样,提高更新效率
<!-- 加key, 解决就地更新策略 -->
<!-- 纯数组 -->
<view wx:for="{{list}}" wx:key="*this">{{item}}</view>
<!-- 对象数组 -->
<view wx:for="{{objList}}" wx:key="id">{{item.name}}</view>
<!-- 纯对象 -->
<view wx:for="{{person}}" wx:key="*this">{{item}}</view>


事件

  • 小程序没有@绑定事件语法

  • 取而代之的是bind+时间名

    • 例如bindTap, 点击事件
  • 小程序也没有alert, document方法

  • 方法定义在page里,不是methods里

    <view bindtap="tapFn">点我</view>
    
    Page({
      tapFn() {
        console.log("点击了我");
      },
    });
    
    

事件传递参数

  • 利用自定义属性data-xxx="xx"

  • 获取的时候,写e.target.dataset.xxx

    <view bindtap="handleFn" data-name="100">test02</view>
    
    Page({
      handleFn(e) {
        console.log(e.target.dataset.name);
      },
    });
    
    
  • data-xxx="{{xx}}"

  • 输出的值是number

    <view bindtap="handleFn" data-name="{{100}}">点我</view>
    

获取数据

  • 语法:this.data.xxx

    <view>{{msg}}</view>
    <view bindtap="changeFn">点我改变上面</view>
    
    data: {
    	msg: "hello world",
    },
    changeFn() {
    	console.log(this.data.msg);
    },
    

更改数据

  • 语法:this.setData({xxx:xx})

    data: {
    	msg: "hello world",
    },
    changeFn() {
    	console.log(this.data.msg);
    },
    
  • 更改数组的方法(工作常用解构)

    • 可以随意更改新数据在数组中的位置
    pushFn() {
        // this.data.list.push("新水果");
        const {list} = this.data.
        const newList = ["老板娘", ...this.data.list];
        this.setData({ list: newList });
      },
    
    

双向绑定model:value

  • model:value写在行内
    • 使用时需要加上空的bindinput事件才不会报错

样式

  • 大部分样式可以使用
  • 不支持通配符*, 可通过并集选择器
  • 单位(vw, rpx)
    • 一般不适用rem
    • 100能除尽尽量用vw
    • 除不尽100的大小,可以用rpx
  • rpx
    • 微信小程序把屏幕分成750份

组件

view

  • view是一个块级元素
    • 可以代替div来使用

text

  • text标签只能套文本内容
    • 行内可以加上user-select, 表示用户可以拖动文本

图片

  • image
    • 是一个固定尺寸的容器
    • 默认图片铺满整个容器
    • 需要设置模式mode使图片不拉伸
    • 有四个属性
      • 默认scaleToFill
        • 宽高拉满
        • 场景:缩略图
      • aspectFit
        • 等比例缩放,可能会留白
        • 查看详细图片
      • widthFix
        • 宽度固定,高度自适应
      • heightFix
        • 高度固定,宽度自适应

轮播图

  • swiper轮播图
    • 嵌套swiper-item
    • autoplay——自动播放
    • interval——轮播时长
    • indicator-dots——滚动小点
    • circular——无缝衔接

navigator

  • navigator跳转组件
    • url属性——可以写需要跳转的页面
    • open-type属性
      • switchTab
        • 作用:可以允许跳转到tab页面
        • 特点:清除掉历史记录,没有回退按钮
      • redirect
        • 作用: 不产生一条跳转的历史记录
        • 注意:如不需要产生历史记录, 该页面中navigator使用redirect
      • navigatorBack
        • 作用:回退一步
        • 特点:不需要写url,无效
        • 场景:通常配置自定义导航栏、自定返回按钮
      • reLaunch
        • 作用:会清除掉所有的历史记录,重新打开某个页面
        • 注意:不常用, 小程序希望尽量缓存页面

按钮

  • button
    • open-type属性
      • share 分享
      • feedback 反馈
      • contact 联系客服
获取用户地理位置
  • 创建按钮

    <button open-type="openSetting">打开设置</button>
    
  • 全局js

     /**
       * 当小程序初始化完成时,会触发 onLaunch(全局只触发一次)
       */
      onLaunch: function () {
        wx.getLocation({
          success: (result) => {
            console.log(result);
          },
          fail: (res) => {
            console.log(res);
          },
          complete: (res) => {},
        });
      },
    
  • 全局json

    "permission": {
        "scope.userLocation": {
          "desc": "请求您的地理位置"
        }
      }
    
获取用户手机号码
  • 注意:需要企业认证才可获取到用户手机号码,否则undefined

  • 结构

    <button open-type="getPhoneNumber" bindgetphonenumber="getPhone">获取用户手机号</button>
    
  • js文件自定义函数

    // 自定义函数
      getPhone(e) {
        console.log("获取手机号---->", e.detail.code);
      },
    

富文本rich-text

  • 标签rich-text

  • 作用:后台返回html字符串时,可以用富文本

  • 结构

    <rich-text nodes="{{strHtml}}"></rich-text>
    
  • data对象声明变量

    data: {
        strHtml: "<h1 style='background-color: lime;'>hello</h1>",
      },
    

自定义组件

  • 注意

    • 相关文件应该放在独立组件文件夹中,否则样式会失效
    • 大小写敏感(注册时,组件名大写开头)
    • 不使用则不注册,否则报错
  • 步骤

    1. 创建组件

      1. 根目录创建components/xxx文件夹
      2. 右键xxx文件夹,点击新建Component
      3. 输入文件名,完成创建
    2. 在需要使用组件的页面json文件注册组件

      "usingComponents": {
          "MyButton": "/components/myButton/myButton"
        }
      
    3. 使用组件

      <MyButton></MyButton>
      

    组件通信

    父传子
    • 传数据——父组件中,通过组件的标签属性传值

    • 接收数据——子组件,通过properties接收

    • 步骤

      1. 父组件通过属性传值

        <MyButton title="父传子"></MyButton>
        
        
      2. 子组件通过properties接收父组件传过来的数据

          properties: {
            title: {
              type: String,
              value: "默认值",
            },
          },
        
        
    子传父
    • 步骤

      1. 子组件绑定事件

        <button bindtap="btnToFa">{{title}}</button>
        
        
      2. 触发子组件事件

         methods: {
            btnToFa(){
              // 传值
              this.triggerEvent('btnToFa','hello')
            }
          },
        
        
      3. 父组件定义接收数据的方法

        <MyButton title="父传子" bindbtnToFa="btnToFa"></MyButton>
        
        
      4. 父组件通过绑定自定义事件

        <MyButton title="父传子" bindbtnToFa="btnToFa"></MyButton>
        
        

生命周期

  • 一堆会在特定时期触发的函数
  • 触发时机
  • 场景作用

应用生命周期

onlaunch
  • 触发时机:初始化小程序时,全局只触发一次

  • 使用场景:初始化数据,获取用户位置信息,获取用户信息

    /**
       * 当小程序初始化完成时,会触发 onLaunch(全局只触发一次)
       */
      onLaunch: function () {
        
      },
    
    
onShow
  • 触发时机:从后台切换到前台时或者第一次启动时

  • 使用场景:常用来获取统计数据,例如时长,时段

  • 注意:进入后台进程后,大概5分钟,会自动关掉

      /**
       * 当小程序启动,或从后台进入前台显示,会触发 onShow
       */
      onShow: function (options) {
        console.log("我切换回前台了");
      },
    
    
onHide
  • 触发时机:从前台切换到后台时或者第一次启动时

  • 使用场景:常用来获取一些统计数据

      /**
       * 当小程序从前台进入后台,会触发 onHide
       */
      onHide: function () {
        console.log("我切换回后台了");
      },
    
    
onError
  • 触发时机:出现错误时

  • 使用场景:配合后台接口,上报错误(埋点)

      /**
       * 当小程序发生脚本错误,或者 api 调用失败时,会触发 onError 并带上错误信息
       */
      onError: function (msg) {
        console.log(msg);
      },
    
    
onThemeChange
  • 触发时机:小程序切换日间 || 夜间模式

  • 使用场景:自动换色(跟随系统)

      /**
       * 当小程序发生脚本错误,或者 api 调用失败时,会触发 onError 并带上错误信息
       */
      onError: function (msg) {
        console.log(msg);
      },
    
    

页面生命周期

onLoad
  • 触发时机:创建后自动执行

  • 使用场景:获取数据、存数据到变量

      /**
       * 生命周期函数--监听页面加载
       */
      onLoad(options) {
        wx.request({
          url: "https://api-hmugo-web.itheima.net/api/public/v1/home/swiperdata",
          success: (res) => {
            this.setData({ list: res.data.message });
          },
        });
      },
    
    
onShow, onHide
  • 触发时机:后台-前台,前台-后台 || 进入页面-离开页面

  • 使用场景:获取数据、存数据到变量

      /**
       * 生命周期函数--监听页面显示
       */
      onShow() {},
    
      /**
       * 生命周期函数--监听页面隐藏
       */
      onHide() {},
    
    
onReady
  • 对应vue的mounted

  • 触发时机:渲染完成

  • 使用场景:

    • 最先获取元素
    • 开启定时器
      /**
       * 生命周期函数--监听页面初次渲染完成
       * mounted
       */
      onReady() {
        console.log("页面初次渲染完成");
      },
    
    
onUnload
  • 对应vue的destroyed

  • 触发时机:渲染完成

  • 使用场景:

    • 清除定时器
    • 清除缓存
    • navigator除了默认的跳转方式,不会写在页面。尽量缓存组件页面
    • 非默认跳转,都会卸载页面
      /**
       * 生命周期函数--监听页面卸载
       */
      onUnload() {
        console.log("页面卸载啦");
      },
    
    
onPullDownRefresh
  • 触发时机:下拉

  • 使用场景:下拉刷新

      /**
       * 页面相关事件处理函数--监听用户下拉动作
       */
      onPullDownRefresh() {},
    
    
onReachBottom
  • 触发时机:滚动到底部的时候

  • 使用场景:上拉请求下一页数据

      /**
       * 页面上拉触底事件的处理函数
       */
      onReachBottom() {},
    
    
onShareAppMessage
  • 触发时机:用户点击右上角分享

  • 使用场景:分享赠送福利

    onShareAppMessage() {},
    
    
onShareTimeline
  • 触发时机:用户点击右上角转发朋友圈

  • 使用场景:转发朋友圈送福利

    onShareTimeline() {},
    
    
onAddToFavorites
  • 触发时机:右上角收藏

  • 使用场景:收藏送福利

    onPageScroll() {},
    
    
onPageScroll
  • 触发时机:页面滚动触发事件的处理函数

  • 使用场景:吸顶效果

    onPageScroll() {},
    
    
onResize
  • 触发时机:页面尺寸改变时触发

  • 使用场景:用户设备横屏时

    onResize() {},
    
    

组件生命周期

attached
  • 对应created

  • 触发时机:挂载后

  • 使用场景:发请求,开定时器

    lifetimes: {
        /**
         * 对应created
         * 触发时机:挂载后
         * 场景:发请求,开定时器
         */
        attached() {},
      },
    
    
detached
  • 对应destroyed

  • 触发时机:卸载时

  • 使用场景:清除动作

    lifetimes: {
        /**
         * 对应destroyed
         * 触发时机:卸载时
         * 场景:清除动作
         */
        detached() {},
      },