微信小程序开发 - 必备理论知识

发布时间:2024年01月15日

文章目录

小程序开发必备理论知识

一、自定义组件

1. 自定义组件 - 组件的创建与引用

1.1 创建组件

在小程序中,创建组件需要定义组件的结构、样式和行为。以下是一个简单的组件目录结构:

|- components
   |- custom-component
      |- custom-component.js
      |- custom-component.json
      |- custom-component.wxml
      |- custom-component.wxss
1.2 引用组件

引用组件可以通过在页面的 .json 文件中配置 usingComponents 字段,然后在页面的 .wxml 文件中以标签的形式引用组件:

pages/index/index.json:

{
  "usingComponents": {
    "custom-component": "/components/custom-component/custom-component"
  }
}

pages/index/index.wxml:

<view>
  <custom-component></custom-component>
</view>
1.3 局部引用组件

局部引用组件是指将组件引入到某个页面或组件内,而不是全局引用。这样做可以提高代码的灵活性和复用性。

pages/index/index.json:

{
  "usingComponents": {
    "custom-component": "/components/custom-component/custom-component"
  }
}

pages/index/index.wxml:

<view>
  <custom-component></custom-component>
</view>
1.4 全局引用组件

全局引用组件是指在整个小程序中都可以使用该组件,不需要在每个页面或组件内单独引用。

app.json:

{
  "usingComponents": {
    "custom-component": "/components/custom-component/custom-component"
  }
}

pages/index/index.wxml:

<view>
  <custom-component></custom-component>
</view>
1.5 全局引用 VS 局部引用

全局引用和局部引用各有优势,全局引用适用于在整个小程序中都需要使用的组件,而局部引用适用于只在某个页面或组件内使用的组件。

1.6 组件和页面的区别

组件和页面在小程序中有一些区别,包括生命周期函数的执行时机和组件的作用域。理解这些区别有助于更好地利用自定义组件进行开发。

2. 自定义组件 - 样式

2.1 组件样式隔离

小程序中的组件样式是默认隔离的,即组件内部的样式不会影响到外部页面或组件。这种隔离有助于保持代码的独立性。

2.2 组件样式隔离的注意点

在使用组件样式隔离时,需要注意一些细节,例如如何正确引用外部样式。

2.3 修改组件的样式隔离选项

开发者可以根据实际需求修改组件的样式隔离选项,灵活控制样式的作用范围。

2.4 styleIsolation 的可选值
可选值默认值描述
isolatedtrue组件样式仅对组件生效,不影响外部样式。
apply-sharedfalse组件样式对组件生效,同时会影响引入组件的外部样式。
sharedfalse组件样式对组件生效,同时也会影响引入组件的外部样式,且外部样式对组件也生效。

3. 自定义组件 - 数据、方法和属性

3.1 data 数据

组件内部可以定义 data 数据,用于存储组件的状态信息。

custom-component.js:

Component({
  data: {
    count: 0
  },
  // other properties and methods
})
3.2 methods 方法

methods 字段用于定义组件的方法,这些方法可以在组件内被调用。

custom-component.js:

Component({
  data: {
    count: 0
  },
  methods: {
    increaseCount() {
      this.setData({
        count: this.data.count + 1
      });
    }
  }
  // other properties
})
3.3 properties 属性

properties 字段用于定义组件的属性,属性可以由组件外部传入,从而实现组件与外部的数据交互。

custom-component.json:

{
  "component": true,
  "properties": {
    "title": {
      "type": String,
      "value": "Default Title"
    }
  }
}
3.4 data 和 properties 的区别

理解 dataproperties 的区别是使用自定义组件的关键,它们分别用于组件内部的状态管理和与外部数据的交互。

3.5 使用 setData 修改 properties 的值

在组件内部可以使用 setData 方法修改 properties 的值,从而实现动态更新组件的属性。

custom-component.js:

Component({
  properties: {
    title: {
      type: String,
      value: "Default Title",
      observer: function (newVal, oldVal) {
        console.log('title changed', newVal, oldVal);
      }
    }
  },
  methods: {
    changeTitle() {
      this.setData({
        title: "New Title"
      });
    }
  }
  // other properties
})

4. 自定义组件 - 数据监听器

4.1 什么是数据监听器

数据监听器用于监听组件内部 dataproperties 的变化,当数据发生变化时触发相应的操作。

custom-component.js:

Component({
  data: {
    count: 0
  },
  observers: {
    'count': function (newVal, oldVal) {
      console.log('count changed', newVal, oldVal);
    }
  },
  // other properties and methods
})
4.2 数据监听器的基本用法

通过定义监听器函数,可以在数据变化时执行自定义的逻辑。

4.3 监听对象属性的变化

数据监听器不仅可以监听基本类型的数据变化,还可以监听对象属性的变化,实现

更精细化的数据控制。

custom-component.js:

Component({
  data: {
    user: {
      name: 'John',
      age: 25
    }
  },
  observers: {
    'user.name': function (newVal, oldVal) {
      console.log('user name changed', newVal, oldVal);
    }
  },
  // other properties and methods
})

5. 自定义组件 - 纯数据字段

5.1 什么是纯数据字段

纯数据字段是一种特殊的数据形式,用于在组件内定义一些纯粹的数据,不参与视图层的渲染。

5.2 使用规则

纯数据字段的使用规则相对简单,只需要在组件的 json 文件中声明即可。

custom-component.json:

{
  "component": true,
  "pureData": {
    "fieldName": "fieldValue"
  }
}
5.3 使用纯数据字段改造数据监听器案例

通过使用纯数据字段,可以改造数据监听器,使得组件更加清晰和易维护。

custom-component.json:

{
  "component": true,
  "pureData": {
    "isListening": false
  },
  "observers": {
    'isListening': function (newVal) {
      if (newVal) {
        console.log('Start listening');
        // Start listening logic
      } else {
        console.log('Stop listening');
        // Stop listening logic
      }
    }
  }
}

6. 自定义组件 - 组件的生命周期

6.1 组件全部的生命周期函数

小程序中,组件有一系列的生命周期函数,包括 createdattachedreadymoveddetached 等。

custom-component.js:

Component({
  lifetimes: {
    created() {
      console.log('component created');
    },
    attached() {
      console.log('component attached');
    },
    ready() {
      console.log('component ready');
    },
    moved() {
      console.log('component moved');
    },
    detached() {
      console.log('component detached');
    }
  },
  // other properties and methods
})
6.2 组件主要的生命周期函数

了解组件的主要生命周期函数有助于合理地处理组件的初始化、渲染和销毁过程。

6.3 lifetimes 节点

lifetimes 节点用于定义组件的生命周期函数,包括 createdattachedreadymoveddetached 等。

7. 自定义组件 - 组件所在页面的生命周期

7.1 什么是组件所在页面的生命周期

组件所在页面的生命周期指的是组件在页面中的生命周期,包括 showhide 等。

custom-component.js:

Component({
  pageLifetimes: {
    show() {
      console.log('component show');
    },
    hide() {
      console.log('component hide');
    }
  },
  // other properties and methods
})
7.2 pageLifetimes 节点

通过 pageLifetimes 节点,可以定义组件所在页面的生命周期函数,实现组件与页面的协同工作。

7.3 生成随机的 RGB 颜色值

在页面生命周期函数中,可以实现一些动态的操作,例如生成随机的 RGB 颜色值,为用户提供更丰富的交互体验。

custom-component.js:

Component({
  pageLifetimes: {
    show() {
      const randomColor = `rgb(${Math.floor(Math.random() * 256)}, ${Math.floor(Math.random() * 256)}, ${Math.floor(Math.random() * 256)})`;
      console.log('generated random color', randomColor);
    }
  },
  // other properties and methods
})

8. 自定义组件 - 插槽

8.1 什么是插槽

插槽是一种用于在组件内部承载内容的机制,使得组件可以更加灵活地适应不同的使用场景。

custom-component.wxml:

<view class="container">
  <view class="header">Header</view>
  <slot></slot>
  <view class="footer">Footer</view>
</view>
8.2 单个插槽

组件可以定义单个插槽,用于承载外部传入的内容。

index.wxml:

<custom-component>
  <view>Content Goes Here</view>
</custom-component>
8.3 启用多个插槽

通过启用多个插槽,可以支持更复杂的内容布局和组合。

custom-component.wxml:

<view class="container">
  <view class="header">Header</view>
  <slot name="content"></slot>
  <view class="footer">Footer</view>
  <slot name="footer"></slot>
</view>
8.4 定义多个插槽

在组件内部,可以通过定义多个插槽,为不同的内容提供不同的展示方式。

index.wxml:

<custom-component>
  <view slot="content">Content Goes Here</view>
  <view slot="footer">Custom Footer</view>
</custom-component>
8.5 使用多个插槽

在页面中使用组件时,可以根据需要传入不同的内容到不同的插槽中,实现更灵活的布局。

9. 自定义组件 - 父子组件之间的通信

9.1 父子组件之间通信的 3 种方式

父子组件之间可以通过属性绑定、事件绑定和获取组件实例等方式进行通信,实现数据的传递和操作的触发。

9.2 属性绑定

通过属性绑定,父组件可以向子组件传递数据,实现数据的共享。

parent-component.wxml:

<child-component title="{{parentTitle}}"></child-component>

child-component.js:

Component({
  properties: {
    title: String
  },
  // other properties and methods
})
9.3 事件绑定

通过事件绑定,子组件可以向父组件发送事件,触发父组件中的相应逻辑。

child-component.js:

Component({
  methods: {
    onTap() {


      this.triggerEvent('customEvent', { data: 'Hello from Child' });
    }
  }
  // other properties
})

parent-component.wxml:

<child-component bind:customEvent="onChildEvent"></child-component>

parent-component.js:

Page({
  onChildEvent(event) {
    console.log('Received custom event from child:', event.detail.data);
  }
  // other methods
})
9.4 获取组件实例

通过获取组件实例,可以直接调用组件的方法,实现更直接的通信方式。

parent-component.js:

Page({
  onReady() {
    const childComponent = this.selectComponent('#child');
    childComponent.doSomething();
  }
  // other methods
})

parent-component.wxml:

<child-component id="child"></child-component>

10. 自定义组件 - behaviors

10.1 什么是 behaviors

Behaviors 是一种可复用的代码块,通过引入 behaviors,可以将一组方法、数据和生命周期函数注入到组件中。

10.2 behaviors 的工作方式

Behaviors 通过混入的方式工作,将 behaviors 中的内容合并到组件中,实现代码的复用。

10.3 创建 behavior

在小程序中,可以创建自定义的 behavior,定义其中的方法和数据。

custom-behavior.js:

module.exports = Behavior({
  data: {
    behaviorData: 'This is from behavior'
  },
  methods: {
    behaviorMethod() {
      console.log('Behavior method');
    }
  }
})
10.4 导入并使用 behavior

通过在组件的 behaviors 字段中导入并使用 behavior,实现代码的重用和模块化。

custom-component.js:

const customBehavior = require('/path/to/custom-behavior');

Component({
  behaviors: [customBehavior],
  // other properties and methods
})
10.5 behavior 中所有可用的节点
可用的节点类型是否必填描述
createdFunction组件生命周期函数,在组件实例刚刚被创建时执行。
attachedFunction组件生命周期函数,在组件实例进入页面节点树时执行。
readyFunction组件生命周期函数,在组件布局完成后执行。
movedFunction组件生命周期函数,在组件实例被移动到节点树另一个位置时执行。
detachedFunction组件生命周期函数,在组件实例被从页面节点树移除时执行。
dataObject组件的内部数据,用于页面渲染。
methodsObject组件的方法,可以在页面内调用。
propertiesObject组件的属性,用于接收父组件传递的数据。
lifetimesObject组件的生命周期函数集合,包括 created、attached、ready、moved、detached。
pageLifetimesObject组件所在页面的生命周期函数集合,包括 show、hide。
definitionFilterFunction用于过滤 behaviors 中定义的字段,返回 true 表示保留,返回 false 表示过滤。
10.6 同名字段的覆盖和组合规则

当组件和 behavior 中存在同名字段时,小程序有一套规则来确定最终的取值,包括覆盖和组合的方式。

二、使用npm包

1. 使用 npm 包 - Vant Weapp

1.1 官方文档地址

Vant Weapp官方文档

1.2 安装教程

Vant Weapp安装教程

1.3 CSS 变量的基本用法MDN文档

CSS 变量的基本用法MDN文档

1.4 Vant 官方配置文件

Vant官方配置文件

2. 使用 npm 包 - API Promise化

2.1 基于回调函数的异步 API 的缺点

传统的异步 API 多采用回调函数的方式,但这种方式存在回调地狱、可读性差等问题。

2.2 什么是 API Promise 化

API Promise 化是指将原本使用回调函数的异步 API 转化为返回 Promise 对象的形式,以更直观、便捷地处理异步操作。

2.3 实现 API Promise 化

使用 miniprogram-api-promise 这个第三方的 npm 包的 promisifyAll 方法,可以实现将小程序原生的异步 API 转化为 Promise 化的形式。

首先,安装 miniprogram-api-promise

npm install miniprogram-api-promise

然后,在小程序代码中使用:

//1.在小程序入口文件中调用一次 promisifyAll()方法
import { promisifyAll } from 'miniprogram-api-promise'
//2.声明一个常量,为一个空对象
const wxp = wx.p = {}
//3.调用 promisifyAll()方法
promisifyAll(wx, wxp)
2.4 调用 Promise 化之后的异步 API
  • 我们在 wx 全局对象上定义一个属性 p 让他和 wxp 指向同一个空对象
  • promisifyAll : 做的事就是将 wx 拥有的属性方法都 copy 并改造了一份给了 wxp 这个对象
  • 这样wxp和wx.p就都指向了同一个对象
//使用
async getInfo () {
  
  const { data: res } = await wx.p.request({
    url: 'https://www.escook.cn/api/get',
    method: 'GET',
    data: {
      name: 'zs',
      age: 19
    }
  })
	
  // res 处理
  
  console.log(res)
}

通过这种方式,可以更清晰、简洁地处理小程序的异步 API 调用。

三、全局数据共享

什么是全局数据共享

全局数据共享是指在小程序中,使数据能够在不同页面或组件之间进行共享,以便实现全局状态的管理和同步更新。

小程序中的全局数据共享方案

在小程序中,有多种全局数据共享方案,其中之一是使用第三方库 MobX。MobX 是一个简单、可扩展的状态管理库,可以帮助实现全局数据的响应式更新和共享。

1. 全局数据共享 - MobX

1.1 安装 MobX 相关的包

首先,安装 MobX 及其相关的包:

npm install mobx mobx-miniprogram
1.2 创建 MobX 的 Store 实例

创建一个 MobX 的 Store 实例,用于管理全局数据:

// store.js
const { observable, action } = require('mobx-miniprogram');

class AppStore {
  @observable globalData = {
    userInfo: null,
    // other global data
  };

  @action setUserInfo(userInfo) {
    this.globalData.userInfo = userInfo;
  }
}

module.exports = new AppStore();
1.3 将 Store 中的成员绑定到页面中

在需要使用全局数据的页面中,将 Store 中的成员绑定到页面:

// index.js
const app = getApp();
const store = require('../../store');

Page({
  onLoad() {
    this.setData({
      userInfo: app.store.globalData.userInfo,
    });

    // 监听 globalData 的变化
    this.dispose = store.observe(() => {
      this.setData({
        userInfo: app.store.globalData.userInfo,
      });
    });
  },
  onUnload() {
    // 移除监听
    this.dispose();
  },
});
1.4 在页面上使用 Store 中的成员

在页面中可以直接使用 Store 中的成员:

<!-- index.wxml -->
<view>{{ userInfo.nickName }}</view>
1.5 将 Store 中的成员绑定到组件中

在需要使用全局数据的组件中,也可以将 Store 中的成员绑定到组件:

// custom-component.js
const store = require('../../store');

Component({
  lifetimes: {
    attached() {
      this.setData({
        userInfo: store.globalData.userInfo,
      });

      // 监听 globalData 的变化
      this.dispose = store.observe(() => {
        this.setData({
          userInfo: store.globalData.userInfo,
        });
      });
    },
    detached() {
      // 移除监听
      this.dispose();
    },
  },
});
1.6 在组件中使用 Store 中的成员

在组件中同样可以直接使用 Store 中的成员:

<!-- custom-component.wxml -->
<view>{{ userInfo.nickName }}</view>

通过以上步骤,就实现了在小程序中使用 MobX 进行全局数据的共享和响应式更新。

四、分包

1、分包 - 基础概念

1.1 什么是分包

分包是指将小程序项目划分成不同的子包,每个子包都可以包含页面、组件、资源文件等,实现模块化管理和按需加载。

1.2 分包的好处
  • 减小小程序首次启动时的下载体积,提高启动速度。
  • 按需加载,优化用户体验。
  • 灵活管理项目结构,方便团队协作和代码维护。
1.3 分包前项目的构成

在进行分包前,项目可能是单一的整体,包含全部页面和资源。

1.4 分包后项目的构成

分包后,项目会被划分为主包和多个子包,每个子包可以包含特定的功能模块。

1.5 分包的加载规则

小程序在启动时会先下载主包,然后在需要时再下载子包。子包是按需加载的,用户访问对应的页面或组件时才会下载相关子包。

1.6 分包的体积限制

每个分包的体积不能超过 2MB,超过会导致分包加载失败。

2、分包 - 使用分包

2.1 配置方法

在小程序的 app.json 文件中使用 subpackages 字段配置分包信息,指定每个分包的路径和名字。

{
  "pages": [
    "pages/index/index"
  ],
  "subpackages": [
    {
      "root": "subpackage1",
      "pages": [
        "pages/subpage1/index",
        "pages/subpage1/detail"
      ]
    },
    {
      "root": "subpackage2",
      "pages": [
        "pages/subpage2/index",
        "pages/subpage2/detail"
      ]
    }
  ]
}
2.2 打包原则

主包中包含 app.jsonapp.jsapp.wxssproject.config.json 等文件,每个分包下都有一个独立的 package.json

2.3 引用原则

在主包中,可以直接引用主包和其他分包的页面和组件。在分包中,只能引用自己分包内的页面和组件。

3、分包 - 独立分包

3.1 什么是独立分包

独立分包是指一个分包中包含了完整的小程序结构,可以独立运行。主包和其他分包可以引用独立分包内的页面和组件。

3.2 独立分包和普通分包的区别

独立分包可以包含完整的小程序结构,具备更强的独立性。普通分包只能包含部分页面和资源。

3.3 独立分包的应用场景

适用于某个功能模块比较独立,可以独立运行的场景。

3.4 独立分包的配置方法

app.jsonsubpackages 中配置 "independent": true

{
  "subpackages": [
    {
      "root": "independent-package",
      "pages": [
        "pages/index/index",
        "pages/detail/detail"
      ],
      "independent": true
    }
  ]
}
3.5 引用原则

独立分包内的页面和组件可以被主包和其他分包引用。

4、分包 - 分包预下载

4.1 什么是分包预下载

分包预下载是指在小程序启动时,提前加载分包的部分代码和资源,加速分包的加载速度。

4.2 配置分包的预下载

app.json 中的 subpackages 中使用 "preloadRule" 配置预下载规则:

{
  "subpackages": [
    {
      "root": "subpackage1",
      "pages": [
        "pages/subpage1/index"
      ],
      "preloadRule": {
        "pages/subpage1/index": {
          "network": "all",
          "packages": ["subpackage1"]
        }
      }
    }
  ]
}
4.3 分包预下载的限制
  • 预下载的代码和资源会占用用户的存储空间。
  • 预下载仅在用户打开小程序时生效,离开小程序后失效。
  • 预下载的分包大小限制为 2MB。
文章来源:https://blog.csdn.net/u014158743/article/details/135608438
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。