WX小程序的常用知识点总结

一、WX小程序的优势和劣势

1.优势

(1)微信助理,容易推广。在微信中,小程序拥有众多入口,例如附近的小程序、小程序码、分享、发现-小程序等五十多个的入口。这些入口有助于企业更好的获取流量,从而进行转化、变现。
(2)使用便捷。用户在使用小程序时,只需要轻轻点一下就可以使用,更加符合用户对使用方便、快捷的需求,所以小程序的用户数量不断增加。
(3)体验良好,有接近原生app的体验。在微信生态里,小程序在功能和体验上是可以秒杀掉 H5 页面的,H5 页面经常出现卡顿、延时、加载慢、权限不足等原因,而这些问题在小程序里都不会出现。
(4)成本更低,从开发成本到运营推广成本,小程序的花费仅为APP的十分之一,无论是对创业者还是传统商家来说都是一大优势。

2.不足

(1)单个包大小限制为2M,这导致无法开发大型的应用,采用分包最大是20M(这个值一直在变化,以官网为准)。
(2)需要像app一样审核上架,这点相对于H5的发布要麻烦一些。
(3)处处受微信限制。例如不能直接分享到朋友圈,涉及到积分,或者虚拟交易的时候,小程序也是不允许的。

二、WX小程序的项目结构

1.pages:
        (1)wxml: 编写小程序界面结构的地方
        (2)wxss: 编写小程序样式的地方
        (3)json:编写界面配置的地方
        (4)js:编写界面逻辑的地方
2.utils: 编写工具类的地方
3.app.js:创建程序实例的位置
4.app.json: 编写全局配置地方
5.app.wxss: 编写全局样式的地方
6.project.config.json: 项目的配置文件

三、小程序中的js和浏览器以及node中的区别

1.浏览器中的js

        (1)ES

        (2)DOM

        (3)BOM

2.node中的js

        (1)ES

        (2)NPM

        (3)Native

3.wx小程序中的js

        (1)ES

        (2)小程序框架

        (3)小程序API

小程序的执行的入口文件是 app.js 。并且会根据其中 require 的模块顺序决定文件的运行顺序。

四、小程序中的数据渲染与浏览器中有什么不同

        1.浏览器中渲染时单线程的

        2.小程序中的运行环境分为渲染层和逻辑层,WXML和WXSS工作在渲染层,js工作在逻辑层

        在页面中展示时通过插值表达式{ { }}

五、简述一下小程序的通讯模型

        小程序的渲染层和逻辑层分别由2个线程管理:

        渲染层的界面使用了WebView 进行渲染;

        逻辑层采用JsCore线程运行JS脚本。

        一个小程序存在多个界面,所以渲染层存在多个WebView线程,这两个线程的通信会经由微信客户端(下文中也会采用Native来代指微信客户端)做中转,逻辑层发送网络请求也经由Native转发。

六、如何优化小程序的首次加载速度(分包加载)

1.什么是分包加载

        某些情况下,开发者需要将小程序划分成不同的子包,在构建时打包成不同的分包,用户在使用时按需进行加载。首次访问小程序的时候会加载主包的内容,只有在访问到分包界面的时候,才会去加载分包的内容

2.为什么要使用分包

        (1)小程序单包大小限制为2M,使用分包最大可以扩展到20M(构建大型APP的时候)

        (2)优化首次加载小程序的速度,可以把不需要首次加载的内容放在分包里,可以提升小程序的使用性能(对性能要求比较高的时候)

3.如何使用分包

(1)目录结构

 (2)配置(只需要在app.json中配置即可)

{ 
"pages":[ "pages/index", "pages/logs" ],
 "subpackages": [ 
    { 
        "root": "packageA", 
        "pages": [ "pages/cat", "pages/dog" ] 
    }, 
    {   
        "root": "packageB", 
        "name": "pack2", 
        "pages": [ "pages/apple", "pages/banana"] 
    } 
] 
}

(3)分包的限制

        a.分包之间不能相互引用js

        b.主包不能引用分包的js

(4)独立分包

        不依赖主包的分包

        配置分包的时候加上independent的配置即可声明为独立分包

(5)分包预加载

        在路由到某个界面的时候,可以需要加载某个分包的内容,以提升访问这个分包的速度。

        在app.json中配置即可       

{    
    "pages": ["pages/index"],   
    "subpackages": [      
        {
            "root": "important",
            "pages": ["index"]
        },{
            "root": "sub1",
            "pages": ["index"],
        },{
            "name": "hello",
            "root": "path/to",
            "pages": ["index"]
        }, {
            "root": "sub3",
            "pages": ["index"]
        },{
            "root": "indep",
            "pages": ["index"],
            "independent": true
        }
    ],   
    "preloadRule": {      
        "pages/index": {
            "network": "all",
            "packages": ["important"]
        },      
        "sub1/index": {        
            "packages": ["hello", "sub3"]
        },      
        "sub3/index": {        
            "packages": ["path/to"]          
        },      
    "indep/index": {        
        "packages": ["__APP__"]      
     }    
  }
}

七、配置tabbar的方式及注意事项

        1.配置tabbar(需要注意的是,tabbar的图标不能是线上的地址,需要提前准备好放到项目里,一般情况下,这些静态资源只能放在assets文件夹下

        2.写在根目录的app.json文件中,需要注意list中最少要有两个,最多只能有五个

        3.list中的每个对象有四个属性

                (1)pagePath:对应页面的路径

                (2)text:显示的文字

                (3)iconPath:未选中时图标的位置路径

                (4)selectedIconPath:选中时图标的位置路径

"tabBar": {
    "color":"",
    "selectedColor": "#f00",
    "list": [
      {
      "pagePath": "pages/index/index",
      "text": "首页",
      "iconPath": "./assets/shouye.png",
      "selectedIconPath": "./assets/shouye1.png"
    },
    {
      "pagePath": "pages/logs/logs",
      "text": "log",
      "iconPath": "./assets/bianji.png",
      "selectedIconPath": "./assets/bianji1.png"
    },
    {
      "pagePath": "pages/home/home",
      "text": "我的",
      "iconPath": "./assets/grzl.png",
      "selectedIconPath": "./assets/grzl1.png"
    }
  ]
  }

八、wxml中常用的组件(标签)

        view标签是我们开发过程中最常用的标签了,这个就相当于Html中的div。

        text标签也是我们开发中常用的,这个相当于Html中的span

        image标签相当于我们Html中的img。

九、wxss相比较css的区别

与 CSS 相比,WXSS 扩展的特性有:    

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

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

例如:要导入的对象

/** common.wxss **/
.small-p {
  padding:5px;
}

 导入的位置

/** app.wxss **/
@import "common.wxss";
.middle-p {
  padding:15px;
}
内联样式

十、微信小程序中的事件绑定及传参

        1.事件定义:在小程序中绑定事件可以以bind开头然后跟上事件的类型,如bindtap绑定一个点击事件,对应的值是一个字符串,需要在page构造器中定义同名函数,每次触发事件之后就会执行对应函数的内容

<view bindtap="handleTap">点击事件</view>
<view bind:tap="handleTap">另一种写法</view>


// pages/my/index.js
Page({
  handleTap(){
    console.log("执行了点击事件");
  }
})

        2.阻止事件冒泡:在小程序中除了通过bind之外,还可以通过catch进行事件绑定,通过catch绑定的事件不会触发事件冒泡。

        3.事件捕获:事件的触发分为两个阶段,首先是捕获阶段,其次是冒泡阶段。默认情况下事件都是在冒泡阶段触发。如果希望事件可以在捕获阶段触发,可以通过capture-bind进行事件绑定

        4.事件传参:在小程序中进行事件传参不能像传统的Web项目中一样,在括号里写参数。在小程序中需要在标签上通过data-方式定义事件所需的参数。

<!-- data-参数名=’参数值’ -->
<view bindtap="handleTap" data-msg="我是事件的参数">点击事件</view>

        每个事件回调触发时,都会收到一个事件对象,通过这个对象可以获取路由传递的参数

handleTap(e){
console.log("执行了点击事件");
	// 通过currentTarget中的dataset属性可以获取时间参数
    console.log(e.currentTarget.dataset.msg);
}

十一、逻辑渲染与列表渲染的方式

        1.逻辑渲染

        WXML 中,使用 wx:if="{ {condition}}" 来判断是否需要渲染该代码块

<view wx:if="{
   
   {condition}}"> True </view>

        使用 wx:elifwx:else 来添加一个 else 块:     

<view wx:if="{
   
   {length > 5}}"> 1 </view>
<view wx:elif="{
   
   {length > 2}}"> 2 </view>
<view wx:else> 3 </view>

         因为 wx:if 是一个控制属性,需要将它添加到一个标签上。如果要一次性判断多个组件标签,可以使用一个 <block/> 标签将多个组件包装起来,并在上边使用 wx:if 控制属性。

<block wx:if="{
   
   {true}}">
  <view> view1 </view>
  <view> view2 </view>
</block>

        除此之外微信小程序还可以通过hidden属性进行条件渲染。wx:if在不满足条件的时候会删除掉对应的DOM,hidden属性则是通过display属性设置为none来进行条件渲染。

<view hidden="{
   
   {condition}}">
隐藏
</view>

        2.列表渲染

        在组件上使用 wx:for 控制属性绑定一个数组,即可使用数组中各项的数据重复渲染该组件。默认数组的当前项的下标变量名默认为 index,数组当前项的变量名默认为 item

<!-- array 是一个数组 -->
<view wx:for="{
   
   {array}}">
  {
   
   {index}}: {
   
   {item.name}}
</view>

        使用 wx:for-item 指定数组当前元素的变量名,使用 wx:for-index 指定数组当前下标的变量名。(在嵌套循环时需要自定义)

<view wx:for="{
   
   {array}}" wx:for-index="idx" wx:for-item="itemName">
  {
   
   {idx}}: {
   
   {itemName.name}}
</view>

        注意:使用 wx:key 来指定列表中项目的唯一的标识符

        wx:key 的值以两种形式提供:

        (1)字符串,代表在 for 循环的 array 中 item 的某个 property,该 property 的值需要是列表中唯一的字符串或数字,且不能动态改变

        (2)保留关键字 this 代表在 for 循环中的 item 本身,这种表示需要 item 本身是一个唯一的字符串或者数字

        设置key值的好处:当数据改变触发渲染层重新渲染的时候,会校正带有 key 的组件,框架会确保他们被重新排序,而不是重新创建,以确保使组件保持自身的状态,并且提高列表渲染时的效率

十二、App.js的生命周期以及page中的生命周期、组件的生命周期

        1.app.js的生命周期

                onLaunch: 当小程序初始化完成时,会触发 onLaunch(全局只触发一次)

                onShow:当小程序启动,或从后台进入前台显示,会触发 onShow

                onHide:当小程序从前台进入后台,会触发 onHide

                onError:当小程序发生脚本错误,或者 API 调用失败时,会触发 onError 并带上错误信息。

        2.page中的生命周期

                onLoad:生命周期函数--监听页面加载,触发时机早于onShow和onReady

                onReady:生命周期函数--监听页面初次渲染完成

                onShow:生命周期函数--监听页面显示,触发事件早于onReady

                onHide:生命周期函数--监听页面隐藏

                onUnload:生命周期函数--监听页面卸载

        3.组件的生命周期

生命周期 参数 描述 最低版本
created 在组件实例刚刚被创建时执行 1.6.3
attached 在组件实例进入页面节点树时执行 1.6.3
ready 在组件在视图层布局完成后执行 1.6.3
moved 在组件实例被移动到节点树另一个位置时执行 1.6.3
detached 在组件实例被从页面节点树移除时执行 1.6.3
error Object Error 每当组件方法抛出错误时执行 2.4.1

十三、用户交互反馈的方式(loading、wx.showToast、wx.showModal)

        1.使用button组件的loading属性,在按钮的文字前边出现一个Loading

        2.wx.showToast显示提示(一般搭配wx.hideToast使用)

wx.showToast({
        title: '已发送',
        icon: 'success',
        duration: 1500
})

//例如点击显示提示,在请求成功后通过wx.hideToast关闭提示

wx.hideToast()

        3.wx.showModal模态对话框

wx.showModal({

      title: '标题',

      content: '告知当前状态,信息和解决方法',

      confirmText: '主操作',

      cancelText: '次要操作',

      success: function(res) {

        if (res.confirm) {

          console.log('用户点击主操作')

        } else if (res.cancel) {

          console.log('用户点击次要操作')

        }

      }

    })

十四、微信小程序中本地存储的方式

(一)同步

        1.存储:wx.setStorageSync('list', {age:5})

        2.获取:wx.getStorageSync('list')

  //本地同步缓存

  syncSet(){

    console.log('这是同步缓存');

    wx.setStorageSync('sync', {content:'这是同步缓存'})

  },

  //本地同步获取

  syncGet(){

    console.log(wx.getStorageSync('sync'));

  },

(二)异步

        1.存储:wx.setStorage({ })

        2.获取:wx.getStorage({ })

  //本地异步存储

  asyncSet(){

    wx.setStorage({

      key:'async',

      data:'这是异步存储的数据',

      success(){

        console.log('异步存储');

      }

    })

  },

  //本地异步获取

  asyncGet(){

    wx.getStorage({

      key:'async',

      success(res){

        console.log(res);

      }

    })

  },

十五、小程序间页面的跳转

1.wx.navigateTo
        保留当前页面,只能打开非 tabBar 页面,返回时返回该页面

wx.navigateTo({
  url: '路径地址',
})

2.wx.redirectTo
        关闭卸载当前页面,只能打开非 tabBar 页面,

wx.redirectTo({
  url: '路径地址'
})

3.wx.switchTab
        关闭所有非tabbar页面, 只能打开 tabBar 页面

wx.switchTab({
  url: '路径地址'
})

4.wx.reLaunch
        关闭卸载所有页面,可以打开任意页面

wx.reLaunch({
  url: '路径地址'
})

5.wx.navigateBack
        返回前面的页面,可以指定返回多少页,如果用过redirectTo,那么被关闭的页面将返回不去

wx.navigateBack({
  delta: 2  //返回的页面数,如果 delta 大于现有页面数,则返回到首页。
})

6.navigator标签

navigator标签中加的url地址可以跳转到非tabBar页面
若要跳转到tabBar页面可以增加一个open-type='switchTab'则可以跳转到tabBar页面,实质相当于wx.switchTab函数

十六、小程序页面的传参

        1.路由跳转传参

        路由跳转传参可以通过?的方式拼接参数。

wx.switchTab({

      url: '../todolist/todolist?id=789',

   })

//或者navigator标签

<navigator url="../detail/detail?id=666">带参数去detail</navigator>  

        跳转到指定界面之后,可以在该页面的onLoad方法中的options参数(本身是个对象)拿到路由跳转的参数。

  onLoad(options) {

    console.log(options);

  },

        2.若要传递标签中的数据参数,可以自定义属性,在对应事件中通过e来获取该参数,再拼接到事件跳转的路径中

 //wxml中

 <button bindtap="navigateTo" data-num="10">wx.navigateTo</button>

//js中

navigateTo(e){

    console.log(e.target.dataset.num);

    wx.navigateTo({

      url: '/pages/detail/detail?id=999&num='+e.target.dataset.num,

    })

  },

十七、wx.request的使用方式以及封装

        1.http的使用 (wx.request)

        url 开发者服务器接口地址。注意这里需要配置域名(注意项目配置、域名信息需要更改,去网页小程序开发者管理,修改,多个之间通过封号(;)分割)
        data   请求的参数
        header 设置请求的 header,header 中不能设置 Referer,默认header['content-type'] = 'application/json'
        method(需大写)有效值:OPTIONS, GET, HEAD, POST, PUT, DELETE, TRACE, CONNECT
        dataType json 回包的内容格式,如果设为json,会尝试对返回的数据做一次 JSON解析
        success 收到开发者服务成功返回的回调函数。
        fail 接口调用失败的回调函数
        complete 接口调用结束的回调函数(调用成功、失败都会执行)

wx.request({

      url: 'https://showme.myhope365.com/api/cms/article/open/list',

      method: "POST",

      data: {

        pageNum: 1,

        pageSize: 10

      },

      header: {

        "content-type": "application/x-www-form-urlencoded"

      },

      success: res => {

        console.log(res.data.rows)

      }

})

        2.http请求的封装

        作用:

  • 添加统一的请求配置
  • 可以添加请求拦截器和响应拦截器,在请求和响应之前加一些通用的处理。
function request(options) {

  // 请求拦截器

  //  ...

  // 1. 加一些统一的参数,或者配置

  if (!options.url.startsWith("https://") && !options.url.startsWith("http://")) {

    options.url = "https://showme.myhope365.com" + options.url

  }

// 默认的请求头

  let header = {

    "content-type": "application/x-www-form-urlencoded",

  };

  if (options.header) {

    header = {

      ...header,

      ...options.header

    }

  }

  return new Promise((reslove, reject) => {

    // 调用接口

    wx.request({

      // 默认的配置

      // 加载传入的配置

      ...options,

      header,

      success(res) {

        // 响应拦截器,所有接口获取数据之前,都会先执行这里

        //  1. 统一的错误处理

        if (res.statusCode != 200) {

          wx.showToast({

            title: '服务器异常,请联系管理员',

          })

        }

        reslove(res)

      },

      fail(err) {

        reject(err)

      }

    })

  })

}

export function get(url, options = {}) {

  return request({

    url,

    ...options

  })

}

export function post(url, data, options = {}) {

  return request({

    url,

    data,

    method: "POST",

    ...options

  })

}

十八、小程序中组件以及插槽的使用

(一)组件的使用

        1.新建components文件夹

        2. 新建文件夹生成component

Component({
  /**

   * 组件的属性列表

   */

  properties: {
  },

  /**

   * 组件的初始数据

   */

  data: {
  },

  /**

   * 组件的方法列表

   */

  methods: {
  }

})

        3.在要使用的文件的json文件中加入

{

  "usingComponents": {

    "组件名":"组件路径"

  }

}

(二)插槽的使用

(1)在组件内直接写的文本会放到默认插槽中

(2)默认情况下,一个组件的 wxml 中只能有一个 slot 。需要使用多 slot 时,可以在组件 js 中声明启用。

Component({
  options: {
    multipleSlots: true // 在组件定义时的选项中启用多 slot 支持
  },
  properties: { /* ... */ },
  methods: { /* ... */ }
})

//组件中

<slot name="before"></slot>

  <view>这里是组件的内部细节</view>

  <slot name="after"></slot>

 //使用的地方

<son1>这是放到默认插槽的文本

<!-- 这部分内容将被放置在组件 <slot name="before"> 的位置上 -->

  <view slot="before">这里是插入到组件slot name="before"中的内容</view>

    <!-- 这部分内容将被放置在组件 <slot name="after"> 的位置上 -->

    <view slot="after">这里是插入到组件slot name="after"中的内容</view>

</son1>

十九、父子组件传参的方式

        1.父传子:在父组件中使用的子组件标签上加自定义属性,在子组件中通过properties去接受,然后就可以再子组件中使用

//父组件

<son1 canshu='kaixuan'>这是放到默认插槽的文本

<!-- 这部分内容将被放置在组件 <slot name="before"> 的位置上 -->

  <view slot="before">这里是插入到组件slot name="before"中的内容</view>

    <!-- 这部分内容将被放置在组件 <slot name="after"> 的位置上 -->

    <view slot="after">这里是插入到组件slot name="after"中的内容</view>

</son1>

//子组件js

  properties: {

    canshu:{

      type:[Number,String],

      value:'默认值'

    }

  },

//子组件wxml

  <view style="color: red;"> 父传子 { {canshu}}</view>

        2.子传父:给子组件绑定一个方法,把给方法写到子组件js的methods中,通过this.triggerEvent来传递参数,再在父组件中用bind:给子组件标签绑定一个自定义事件,事件类型与子组件中的保持一致,事件名随便写,然后在父组件的对应事件中即可拿到并改变父组件的值从而使用

(1)给子组件绑定一个方法,把给方法写到子组件js的methods中,通过this.triggerEvent来传递参数

 methods: {

    //子传父

    toFather(){

         this.triggerEvent('myevent','子传父的数据')

    },

  }

(2)再在父组件中用bind:给子组件标签绑定一个自定义事件,事件类型与子组件中的保持一致,事件名随便写

<son1 bind:myevent='myevent'>这是放到默认插槽的文本

<!-- 这部分内容将被放置在组件 <slot name="before"> 的位置上 -->

  <view slot="before">这里是插入到组件slot name="before"中的内容</view>

    <!-- 这部分内容将被放置在组件 <slot name="after"> 的位置上 -->

    <view slot="after">这里是插入到组件slot name="after"中的内容</view>

</son1>

(3)然后在父组件的对应事件中即可拿到并改变父组件的值从而使用

//获取子传父的值

  myevent(res){

      console.log(res);

      this.setData({

        fromSon:res.detail

      })

  },

  

// 在父组件中使用

<view>{ {fromSon}}</view>

二十、Behavior的使用方式

        Behaviors 注册一个 behavior,接受一个 Object 类型的参数

module.exports = Behavior({

  created(){

console.log(1111);

  },

})

         在要使用的组件的js中引入

import Behavior from "../../behavior/behavior"

 

Component({

  behaviors:[Behavior], 

...

})

注意,生命周期都会走,但是如果混入和组件内的数据重名,下面的会覆盖上面的

同名字段的覆盖和组合规则

组件和它引用的 behavior 中可以包含同名的字段,对这些字段的处理方法如下:

  • 如果有同名的属性 (properties) 或方法 (methods):
    1. 若组件本身有这个属性或方法,则组件的属性或方法会覆盖 behavior 中的同名属性或方法;
    2. 若组件本身无这个属性或方法,则在组件的 behaviors 字段中定义靠后的 behavior 的属性或方法会覆盖靠前的同名属性或方法;
    3. 在 2 的基础上,若存在嵌套引用 behavior 的情况,则规则为:引用者 behavior 覆盖 被引用的 behavior 中的同名属性或方法。
  • 如果有同名的数据字段 (data):
    • 若同名的数据字段都是对象类型,会进行对象合并;
    • 其余情况会进行数据覆盖,覆盖规则为: 引用者 behavior > 被引用的 behavior 、 靠后的 behavior > 靠前的 behavior。(优先级高的覆盖优先级低的,最大的为优先级最高)
  • 生命周期函数和 observers 不会相互覆盖,而是在对应触发时机被逐个调用:
    • 对于不同的生命周期函数之间,遵循组件生命周期函数的执行顺序;
    • 对于同种生命周期函数和同字段 observers ,遵循如下规则:
      • behavior 优先于组件执行;
      • 被引用的 behavior 优先于 引用者 behavior 执行;
      • 靠前的 behavior 优先于 靠后的 behavior 执行;
    • 如果同一个 behavior 被一个组件多次引用,它定义的生命周期函数和 observers 不会重复执行。

二十一、WebSocket的使用

详情见我单独的另一篇文章连接如下:

(2条消息) WebSocket的使用_终将抵达丶的博客-CSDN博客icon-default.png?t=M85Bhttps://blog.csdn.net/gkx19898993699/article/details/128023620?spm=1001.2014.3001.5502

猜你喜欢

转载自blog.csdn.net/gkx19898993699/article/details/128020256