02小程序

255 阅读7分钟

App实例

每个小程序都需要在app.js中调用App函数注册小程序示例;

  • 在注册时,可以绑定对应的生命周期函数;
  • 在生命周期函数中,执行对应的代码;

developers.weixin.qq.com/miniprogram…

image.png

注册App时,我们会做哪些操作?

  • 1.判断小程序的进入场景;
  • 2.监听生命周期函数,在生命周期中执行对应的业务逻辑,比如在某个生命周期函数中进行登录或者网络请求;
  • 3.因为App()实例只有一个,并且是全局共享的(单例对象),所以我们可以将一些共享数据放在这里;

小程序没有提供状态共享库(Vuex/Pinia)

App()中共享一些简单的数据还行,大的数据共享就不太行了,后续我们再详谈;

判断进入场景

小程序常见的打开场景:群聊会话中打开、小程序列表中打开、微信扫一扫打开、另一个小程序中打开:

developers.weixin.qq.com/miniprogram…

如何确定场景?

  • onLaunchonShow生命周期回调函数中,会有options参数,其中这个参数有一个scene值:

image.png

// app.js
App({
  // 生命周期函数
  onLaunch(options){
    // 生命周期回调——监听小程序初始化。
    console.log(options);
  },

  // 生命周期回调——监听小程序启动或切前台。	
  onShow(options){
    // 通过options判断小程序进入场景
    console.log('onShow');
  },

  // 生命周期回调——监听小程序切后台。
  onHide(){
    console.log('onHide');
  }
})

定义全局App的数据

存储全局数据的属性名是自定义的,但是最好做到见名知意的:

// pages/order/order.js
Page({
  data: {
    userInfo: {}
  },

  onLoad() {
    // 获取共享的数据: App实例中数据
    // 1.获取app实例对象
    const app = getApp()

    // 2.从app实例对象获取数据
    const token = app.globalData.token
    const userInfo = app.globalData.userInfo
    console.log(token, userInfo);

    // 3.拿到token目的发送网络请求
    
    // 4.将数据展示到界面上面,如果不是setdata保存数据,则不是响应式的
    this.setData({ 
        userInfo:userInfo
    })
    
    //简写:this.setData({userInfo })
    
    console.log(this.data.userInfo);
  }
})
App({
  // 作用二: 共享数据
  // 数据不是响应式, 这里共享的数据通常是一些固定的数据
  globalData: {
    token: "",
    userInfo: {}
  },
})

image.png

生命周期函数

在生命周期函数中,完成应用程序启动后的初始化操作:

onLaunch

  • 比如登录操作
  • 比如读取本地数据(类似于token,然后保存在全局,方便使用)
  • 比如请求整个应用程序需要的数据

一登录,onLaunch中的数据就会被保存起来

//app.js
App({
    onLaunch(options){
        //1.从本地获取token/userInfo
        const token = wx.getStoreageSync("token")
        const userInfo = wx.getStorageSync("userInfo")
    
        //2.进行登录操作(逻辑判断)
        //将登陆成功的数据,保存到storeage中
        //只有当没有数据的时候,才会来到这里,进行存储数据
        if(!token || !userInfo){
            wx.setStorageSync("token","kobeToken")
            wx.setStorageSync("userInfo",{
                //存储对象
                nickname:"Kobe",
                level:100
            })
        }
        
        //3.将获取到的数据保存在globalData中
        this.globalData.token = token
        this.globalData.userInfo = userInfo
    }
})

代码组件方式调整

pages中保存的页面不能有中文:

image.png

<!-- home首页 -->
<view class="pages">
  <block wx:for="{{pages}}" wx:key="name">
    <button
      type="primary" 
      bindtap="onBtnClick"
      data-item="{{item}}"
    >
      {{ item.name }}
    </button>
  </block>
</view>
// index.js
Page({
  data: {
    pages: [
      { name: "01_初体验", path: "/pages/01test/index" },
      { name: "02_页面配置", path: "pages/02_页面配置/index" }
    ]
  },
  onBtnClick(event) {
    // 1.获取item
    const item = event.target.dataset.item

    // 2.跳转路径
    wx.navigateTo({
      url: item.path,
    })
  }
})

注册页面-Page函数

小程序中的每个页面,都有一个对应的js文件,其中调用Page函数注册页面实例:

  • 在注册时,可以绑定初始化数据、生命周期回调、事件处理函数等;

developers.weixin.qq.com/miniprogram…

注册一个Page页面时,我们一般做:

  • 1.在生命周期函数中,发送网络请求,从服务器中获取数据;
  • 2.初始化一些数据,以方便被wxml引用展示;
  • 3.监听wxml中的事件,绑定对应的事件函数;
  • 4.其他一些监听(比如页面滚动、上拉刷新、下拉加载更多等)

image.png

developers.weixin.qq.com/miniprogram…

小程序开的2个线程,一个是:ViewThread(渲染页面),还有一个是:AppService Thread(执行js代码)的线程;

当我们创建一个页面时,会生成wxml、wxss、js、json文件,实际上4个页面会生成2个线程,ViewThread线程读取wxml、wxss文件,他会等待一会儿才会渲染,而AppServiceThread线程用来解析js、json文件;

ViewThread会等待AppserviceTHread进行onLoad、onShow初始化数据,并发送给ViewThread线程,这个时候ViewThread中有数据了,就会FirstRender第一次渲染,发送通知,AppserviceThread就会onReady,页面就渲染好了,当数据发生变化的时候,AppServiceThread又会sendData再次发送数据,然后ViewThread又会Rerender重新渲染,重复此步骤;如果用户把页面关闭,数据会发送到后台set to background,然后回调onHide,一旦打开后,又会set to foreground回到前台,然后回调onShow

当页面切换的时候,就会执行onUnload生命周期,也就是销毁;

//index.js
onShow(){

}
onReady(){

}
onHide(){

}
onUnload(){

}

组件

image.png

Text文本组件

image.png

Text组件,类似于span标签

  • 通过设置user-select属性决定文本内容是否可以让用户选中;
  • 设置decode:true可以解析特殊字码,比如&gt等;

button组件

button组件是一个块级元素,和HTML不同!!!

image.png

  • mini属性:设置button大小,default是默认大小,size是小尺寸;
  • type属性:primary绿色、default白色、warn红色;
  • plain属性:设置按钮是否镂空,也就是背景色是透明;
  • disabled:设置按钮是否禁用;
  • loading:按钮前面有一个loading动画
  • hover-class:指定按钮按下去后的样式类,当hover-class='none'时,没有点击效果

image.png

按钮的open-type

image.png

  • contact:open-type=contact会跳转到客服会话,跳转到微信客服会话;
  • 现在想要拿到用户信息,必须通过触发bindgetuserinfo,通过wx.getUserProfile才能拿到用户信息;

返回的是一个Promise

<button size="mini" type="primary" bindgetuserinfo="getUserInfo">

Page({
//绑定函数调用:
    getUserInfo(event){
        //调用API,获取用户信息
        wx.getUserProfile({
            desc:'desc',//必传的
        }).then(res)=>{
            console.log(res)
        }
    }
})

获取用户手机号,绑定bindgetphonenumber:如果是个人,是不可以获取手机号的,除非是企业级

<button size="mini" type="primary" open-type="getPhoneNumber" bindgetphonenumber="getPhoneNumber">
手机号码
</button>

Page({
    getPhoneNumber(event){
        
    }
})

View组件解析

View组件类似于HTML中的div

image.png

View也有hover-class属性,hover-starat-timehover-stay-time属性:

<view bindtap='onViewClick' hover-class="active"></view>

Image组件的使用

image.png

developers.weixin.qq.com/miniprogram…

/可以表示根目录,image元素默认宽高是:320*240,并且是一个行内块级(HTML中是行内替换元素)所以不自己设置一下样式,会存在问题;

//index.wxml
<image src = '/assets/zznh.png'/>
<image src = '网络图片的地址'/>

图片中非常重要的属性:mode

  • top:裁剪模式,不缩放图片,只显示图片顶部
  • bottom:裁剪模式,不缩放图片,只显示图片底部
  • top right:裁剪模式,不缩放图片,只显示右上角
  • scaleToFill:缩放模式,不保持纵横比缩放图片,使图片的宽高完全拉伸至填满 image 元素
  • aspectFill:缩放模式,保持纵横比缩放图片,只保证图片的短边能完全显示出来。也就是说,图片通常只在水平或垂直方向是完整的,另一个方向将会发生截取。
  • aspectFit:缩放模式,保持纵横比缩放图片,使图片的长边能完全显示出来。也就是说,可以完整地将图片显示出来。但是左右两边可能会存在空白
  • widthFix:缩放模式,宽度不变,高度自动变化,保持原图宽高比不变;(宽度为320的情况下,高度自适配,常用)
  • heightFix:高度是240,宽度自适配(用得不多)

大多数情况下,这些方式我们都不常用,最常用的是widthFix

<image src ='...' mode="top"/>
<image src ='...' mode="bottom"/>
<image src ='...' mode="top right"/>
<image src ='...' mode="scaleToFill"/>
<image src ='...' mode="aspect"/>

选择本地图片,通过一个API:wx.chooseMedia

//index.wxss
<button bindtap='onChooseImage'>选择图片</button>
<image src="{{chooseImageUrl}}/">

//index.js
Page({
    data:{
        chooseImageUrl:""
    }
    onChooseImage(){
        wx.chooseMedia({
            //选择手机中的图片
            mediaType:"image",
        }).then(res=>{
            cosnt imagePath=res.tempFiles[0].tempFilePath
            this.setData({chooseImageUrl:imagePath})
        })
    }
})

developers.weixin.qq.com/miniprogram…

scroll-view

image.png

上下滚动(y轴滚动,设置scroll-y)

//index.wxml
<scroll-view class="container scroll-x" scroll-y enable-flex>
    <block wx:for="{{viewColors}}" wx:key="*this">
        <view class="item">{{item}}</view>
    </block>
</scroll-view>

//index.wxss
.container{
    background-color:orange;
    height:
}

.item{
    width:100px;
    height:100px;
}

如果想要flex布局生效,还需要在scroll-view元素中开启
.scroll-x{
    display:flex;
}

scroll-view滚动监听

<scroll-view 
    bindscrolltoupper="onScrollToUpper"
    bindscrolltolower="onScrollToLower"
    bindscroll="onScroll"
>
</scroll-view>

Page({
    onScrollToUpper(){
        console.log('滚动到最顶部/左边')
    },
    onScrollToLower(){
        console.log('滚动到最底部/右边')
    },
    onScroll(event){
        console.log('scrollView发生滚动',event)
        event.scrollLeft //已经滚动的值
        event.scrollHeight //已经滚动的值
        event.scrollWidth //可以滚动的距离
    }
})

组件共同属性和input组件的双向绑定

image.png

input默认是没有背景的,直接就是一个输入框

<input type="text" model:value="{{双向绑定}}"/>


//index.wxss
input{
    width:200px;
    height:30px;
    border:1px solid orange;
}