邂逅小程序开发

343 阅读3分钟

一、邂逅小程序开发

1.1 小程序的准备工作

1.2 VSCode开发小程序

  • 推荐以下插件

    image.png

1.3 整体结构

  • 整体结构

    image.png

  • 补充:新建页面步骤

    • pages 页面下新建文件夹,然后点击文件夹鼠标右键新建 page
    • app.json 的pages中写下文件路径,会自动生成文件夹

1.4 小程序开发体验

  • 数据绑定

  • 列表展示

  • 计数器案例

    <!-- 1.动态绑定message属性 -->
    <view class="message">{{ message }}</view>
    
    <!-- 2.动态展示列表数据 -->
    <view class="movies">
      <!-- for循环: block -->
      <block wx:for="{{movies}}" wx:key="*this">
        <view>
          {{ item }}-{{ index }}
        </view>
      </block>
    </view>
    
    <!-- 3.事件绑定: 计数器案例 -->
    <view class="counter">
      <view class="count">当前计数: {{ counter }}</view>
      <button size="mini" type="primary" bindtap="increment">+1</button>
      <button size="mini" type="warn" bindtap="decrement">-1</button>
    </view>
    
    // 实例化: 页面实例
    Page({
      data: {
        // 1. 数据绑定 mustache语法
        message: "Hello World",
    
        // 2. 列表数据
        movies: ["少年派", "大话西游", "星际穿越", "独行月球"],
    
        // 3. 计数器
        counter: 0
      },
    
      // 监听的事件方法
      increment() {
        // 修改data中的数据, 但是你的修改并不会引起页面的刷新(自动检测你的新数据重新渲染页面, 在小程序中不会, 在react中也不会)
        // this.data.counter += 1
        // console.log(this.data.counter);
    
        // 修改data, 并且希望页面重新渲染, 这里必须使用this.setData()
        this.setData({
          counter: this.data.counter + 1
        })
      },
      decrement() {
        this.setData({
          counter: this.data.counter - 1
        })
      }
    })
    

1.5 小程序的MVVM架构思想

  • Vue的MVVM和小程序MVVM对比

    image.png

  • MVVM为什么好用?

    • DOM Listeners: ViewModel层可以将DOM的监听绑定到Model层
    • Data Bindings: ViewModel层可以将数据的变量, 响应式的反应到View层

二、小程序的架构和配置

2.1 小程序的双线程模型

  • 小程序的宿主环境是:微信客户端

    • 宿主环境可以执行小程序的各种文件(wxml、wxss、js)
  • 当小程序运行在 WebView 环境下时,会有什么问题呢?

    • JS 逻辑、DOM 树创建、CSS 解析、样式计算、Layout、Paint (Composite) 都发生在同一线程中
    • 在 WebView 上执行过多的 JS 逻辑可能阻塞渲染,导致界面卡顿
  • 小程序考虑到性能与安全的问题,采用了「双线程模型」的架构

    • WXML模块和WXSS样式运行于渲染层,渲染层使用WebView线程渲染

      • 当一个程序有多个页面时,会使用多个WebView的线程
    • JS脚本(app.js等)运行于 逻辑层,逻辑层使用 JsCore 运行 JS脚本

      • 这两个线程都会经由微信客户端(Native)进行中转并交互

      image.png

  • Skyline (beta)

    • Skyline 创建了一条渲染线程来负责 Layout, Composite 和 Paint 等渲染任务,并在 AppService 中划出一个独立的上下文,来运行之前 WebView 承担的 JS 逻辑、DOM 树创建等逻辑。
    • 官方文档

2.2. 常见的配置文件

  • project.config.json 项目名称、appId

    • project.private.config.json (私有配置)
      • 项目名字,是否开启热重载, 是否开启地址检查,当前版本库的版本号
      • 这个文件中设置的内容会覆盖掉project.config.json文件中的相同设置
      • 与project.config.json配置不同时会改变这个文件中的配置
  • sitemap.json

    • 配置小程序及其页面是否允许被微信索引

2.3. app.json配置文件

  • 应用程序配置
    • pages:页面路径列表

      • 用于指定小程序由哪些页面组成,每一项都对应一个页面的 路径(含文件名) 信息。

      • 小程序中所有的页面都是必须在pages中进行注册的
    • window:全局默认窗口

    • tabBar:底部 tab 栏

      {
        "tabBar": {
          "selectedColor": "#ff8189",
          "list": [
            {
              "text": "首页",
              "pagePath": "pages/index/index",
              "iconPath": "assets/tabbar/home.png",
              "selectedIconPath": "assets/tabbar/home_active.png"
            },
            {
              "text": "我的",
              "pagePath": "pages/profile/profile",
              "iconPath": "assets/tabbar/profile.png",
              "selectedIconPath": "assets/tabbar/profile_active.png"
            }
          ]
        },
      }
      

2.4. page.json配置文件

  • 覆盖全局的配置

    {
      "usingComponents": {},
      "navigationBarTitleText": "个人信息",
      "navigationBarBackgroundColor": "#f00",
      "enablePullDownRefresh": true,
      "onReachBottomDistance": 100
    }
    
  • 下拉刷新/上拉加载更多

    • Page({ onPullDownRefresh, onReachBottom })

      Page({
        data: {
          listCount: 30
        },
      
        // 监听下拉刷新
        onPullDownRefresh() {
          // 模拟网络请求: 定时器
          setTimeout(() => {
            this.setData({ listCount: 30 })
      
            // API: 停止下拉刷新
            wx.stopPullDownRefresh({
              success: (res) => {
                console.log("成功停止了下拉刷新", res);
              },
              fail: (err) => {
                console.log("失败停止了下拉刷新", err);
              }
            })
          }, 1000)
        },
      
        // 监听页面滚动到底部
        onReachBottom() {
          this.setData({
            listCount: this.data.listCount + 30
          })
        }
      })