微信小程序开发

文件和目录介绍

小程序包括两个部分:主体文件、页面文件。

主体文件由三部分组成:

  1. app.js:小程序入口文件
  2. app.json:小程序的全局配置文件
  3. app.wxss:小程序的全局样式

注意事项:主体文件名字必须是app、app.js和app.json文件是必须的

页面文件是每个页面所需的文件,小程序页面文件都存放在pages目录下,一个页面一个文件夹。

页面文件由四个文件组成,每个文件只对当前页面有效:

  1. .js:页面逻辑
  2. .wxml:页面结构
  3. .wxss:页面样式
  4. .json:小页面配置

注意事项:.js文件和.wxml文件是必须的

配置文件介绍

  1. app.json:小程序全局配置文件,用于配置小程序的一些全局属性和页面路由。
  2. 页面.json:小程序页面配置文件,也称局部配置文件,用于配置当前页面的窗口样式、页面标题等
  3. project.config.json:小程序项目配置的配置文件,用于保存项目的一些配置信息和开发者的个人设置。
  4. sitemap.json:配置小程序及其页面是否允许被微信索引,提高小程序在搜索引擎搜索到的概率。

全局配置-pages配置

pages字段:用来指定小程序由那些页面组成,用于让小程序知道由那些页面组成以及页面定义在那个目录,每一项对应一个页面的路径信息

注意事项:

  1. 页面路由不需要写文件后缀,框架会自动去寻找对应位置的四个文件进行处理。
  2. 小程序中新增/减少页面,都需要对pages数组进行修改。
  3. 未指定entryPagePath时,数组的第一项代表小程序的初始页面(首页)。

全局配置-window配置

window字段:用于设置小程序的状态栏、导航条、标题、窗口背景色。微信小程序页面配置文档icon-default.png?t=O83Ahttps://developers.weixin.qq.com/miniprogram/dev/reference/configuration/app.html

全局配置-tabbar配置

tabBar字段:定义小程序顶部、底部tab栏,用以实现页面之间的快速切换,可以通过配置tarBar配置项指定tab栏的表现,以及tab切换时显示的对应页面。

注意事项:

  1. tab按数组的顺序排序,list配置最少2个、最多5个tab

app.json配置如下

{
//页面路由
    "pages": [
        "pages/index/index",
        "pages/cate/cate",
        "pages/cart/cart",
        "pages/profile/profile",
        "pages/list/list"
    ],
    "window": {
      "navigationBarTitleText": "慕尚花坊",//小程序名称
      "navigationBarBackgroundColor": "#f3514f", //小程序title背景颜色
      "enablePullDownRefresh":true,//是否开启下拉刷新 
      "backgroundColor": "#efefef",
      "backgroundTextStyle":"light"
    },
    //导航栏配置
    "tabBar": {
      "selectedColor": "#f3514f",//选中的颜色
      "color": "#666",//字体颜色
      "list": [
        {
          "text":"首页",//名称
          "pagePath": "pages/index/index",//路径
          "iconPath": "/assets/tabbar/index.png", //没选中的icon
          "selectedIconPath": "/assets/tabbar/index-active.png"//选中的icon
        }, 
        {
          "text":"分类",
          "pagePath": "pages/cate/cate",
          "iconPath": "/assets/tabbar/cate.png",
          "selectedIconPath": "/assets/tabbar/cate-active.png"
        },
        {
          "text":"购物车",
          "pagePath": "pages/cart/cart",
          "iconPath": "/assets/tabbar/cart.png",
          "selectedIconPath": "/assets/tabbar/cart-active.png"
        },
        {
          "text":"我的",
          "pagePath": "pages/profile/profile",
          "iconPath": "/assets/tabbar/my.png",
          "selectedIconPath": "/assets/tabbar/my-active.png"
        }
      ]
    },
    "style": "v2",
    "sitemapLocation": "sitemap.json",
    "lazyCodeLoading": "requiredComponents"
}

页面配置

小程序的页面配置,也称局部配置,每一个小程序页面也可以使用自己的.json文件对本页面窗口表现进行配置。

需要注意的是:页面配置文件的属性和全局配置文件中的window属性几乎一致,只不过这里不需要额外指定window字段,因此如果出现相同的配置项,页面中配置项会覆盖全局配置文件中相同的配置项

微信小程序页面配置文档icon-default.png?t=O83Ahttps://developers.weixin.qq.com/miniprogram/dev/reference/configuration/page.html

 项目配置文件和配置sass

在创建项目的时候,每个项目的根目录生成两个config.json文件,用于保存开发者在工具上做的个性化配置,例如和编译有关的配置。当重新安装微信开发者工具或换电脑工作时,只要载入同一个项目的代码包,开发者工具就会自动恢复带当时开发项目时的个性化配置。

project.config.json:项目配置文件,常用来进行配置公共的配置

project.private.config.json:项目私有的配置,常用来配置个人的配置

注意事项:

  1. project.private.config.json写到.gitignore避免版本管理的冲突。
  2. 与最终编译结果有关的设置必须设置到project.config.json

项目配置文件官方文档icon-default.png?t=O83Ahttps://developers.weixin.qq.com/miniprogram/dev/devtools/projectconfig.html配置sass步骤如下

然后将wxss样式文件后缀名改成scss就可以在项目中使用sass了。

配置文件-sitemap.json 文件

sitemap.json文件:配置小程序及其页面是否允许被微信索引,提高小程序在微信内部被用户搜索到的概率。

注意事项:

  1. 注:没有sitemap.json则默认所有页面都能被索引
  2. {"action":"allow","page":"*"}是优先级最低的默认规则,未显式指明"disallow"的都默认被索引

小程序的样式和组件介绍

小程序中不能使用HTML表情按,也就没有DOM和BOM,css也仅仅支持部分选择器

小程序提供了wxml进行页面结构编写,同时提供了wxss进行页面的样式编写

小程序组件官方文档icon-default.png?t=O83Ahttps://developers.weixin.qq.com/miniprogram/dev/component/

 样式-尺寸单位rpx

小程序规定任何型号手机:屏幕宽都为750rpx

样式-全局样式和局部样式

全局样式:指在app.wxss中定义的样式规则,作用于每一个页面,例如:设置字号、背景色、宽高等全局样式。

局部央视:指在app.wxss中定义的样式规则,只作用在对应的页面,并会覆盖app.wxss中相同的选择器。

组件-组件案例演示

小程序常用的组件:

  1. view组件
  2. swiper和swiper-item组件
  3. image组件
  4. text组件
  5. navigator组件
  6. scroll-view组件
  7. 字体图标

页面跳转

在小程序中。如果需要进行跳转,需要用到navigation组件,常见的属性有两个:

1.url:当前小程序内的跳转链接

2.open-type:跳转方式

navigate:保留当前页面,跳转到应用内的某个页面,但是不能跳转到tabbar页面

redirect:关闭当前页面,跳转到应用内的某个页面,但是不能跳转到tabbar页面

switchTab:跳转到tabBar页面,并关闭其他所有非tabBar页面

reLaunch:关闭所有页面,打开到应用内的某个页面

navigateBack:关闭当前页面,返回上衣页面或多级页面

注意事项:

1.路径可以带参数。参数与路径之间使用?分隔,参数键与参数值用=相连,不同参数用&分隔

例如:/list?id=10&name=hua,在onLoad(options)生命周期函数中获取传递的参数

2.open-type="switchTab"时不支持传参

在进行页面跳转时,需要在路径前面添加  / 斜线,否则跳转不成功

小程序内字体图标的使用

首先去iconfont网站新建一个项目,然后找到自己需要的图标添加入库,再然后添加到项目中

 然后复制这个css文件到小程序中新建一个iconfont文件夹,里面放一个iconfont.scss

把复制过来的内容粘贴到这个scss文件里面,然后再在app.scss中引入这个文件,如下图

引入完成后,就可以使用字体图标了。

注意:真实项目不建议像我这样直接用,可以在那边把资源下载下来然后放到小程序里面,我这样用的话iconfont 网站要是有问题,那我们所引用的就都没用了。

这边这样引进来小程序会有个报错

解决的办法就是去iconfont网站,项目设置=>然后在字体格式勾上base64然后在生成一下,复制到小程序里面就解决了。

组件-背景图片的使用

注意:小程序的background-image不支持本地路径!!!  需要使用网络图片,或者base64,或者使用<image/>组件

事件系统-事件绑定和事件对象

小程序中绑定事件与在网页开发中绑定事件几乎一致,只不过在小程序不能通过on的方式绑定事件,也没有click事件,小程序中绑定事件使用bind方法,click事件也需要使用tap事件进行代替,绑定事件的方式有两种:

第一种:bind事件名,bind后面需要跟上冒号,冒号后面跟上事件名。例如:

<view bind:tap="fnName"></view>

第二种:bind事件名,bind后面直接跟上事件名,例如:<view bindtap="fnName"></view>

事件处理函数需要写到.js文件中,在.js文件中需要调用小程序提供的Page方法来注册小程序的页面,我们可以直接在Page方法中创建事件处理函数

事件分类以及阻止事件冒泡

事件分为:冒泡事件和非冒泡事件

冒泡事件:当一个组件的事件被触发后,该事件会向父节点传递

非冒泡事件:当一个组件的事件被触发后,该事件不会向父节点传递

使用bind绑定的事件,会触发事件冒泡,如果想阻止事件冒泡,可以用catch来绑定事件

这样就成功阻止了事件冒泡了

事件传参-data-*自定义数据

事件传参:在触发时间时,将一些数据作为参数传递给事件处理函数的过程就是事件传参。

在微信小程序中,我们经常会在组件上添加一些自定义数据,然后在事件处理函数中获取这些自定义数据,从而完成逻辑业务的开发。

在组件上通过 data-*的方式定义需要传递的数据,其中*是自定义的属性,例如:<view data-id="100" bindtap="handler"/> 然后通过事件对象进行获取自定义数据。

注意事项:

  1. event.target 是指事件触发者,event.currentTarget是指事件绑定者
  2. 使用data-方法传参数的时候,多个单词由连字符-连接,连字符写法会被转换成驼峰写法
  3. 使用data-方法传递参数的时候,而大写字符会自动转成小写字符

事件传参-mark 自定义数据

小程序进行事件传参的时候,除了使用data-*属性传递参数外,还可以使用mark标记传递参数

mark是一种自定义属性,可以在组件上添加,用来识别具体触发事件的target节点。同时mark还可以用于承载一些自定义数据。

在组件上使用mark:自定义属性的方式将数据传递给事件处理函数,例如:<view mark:id="100" bindtap="handler" />

mark和data-*很相似,主要区别在于:

mark包含从触发事件的节点到根节点上所有的mark:属性值

currentTarget.dataset或者target.dataset 只包含事件绑定者或者事件触发者那一个节点的data-*值。

wxml语法-声明和绑定数据

小程序页面中使用的数据均需要在Page() 方法的 data 对象中进行声明定义

在将数据声明好以后,在WXML使用Mustache语法(双大括号{{}})将变量包起来,从而将数据绑定

在{{ }} 内部可以做一些简单的运算,支持如下几种方式:

  • 算数运算
  • 三元运算
  • 逻辑判断
  • 其他...

注意事项:在{{}}语法中,只能写表达式,不能写语句,也不能调用js相关的方法

wxml语法-setData()修改数据

小程序中修改数据不推荐通过复制的方式进行修改,通过赋值的方式修改数据无法改变页面的数据,而是要通过调用setData()方法进行修改,setData()方法接受对象作为参数,key是需要修改的数据,value是最新的值

setData()方法有两个作用:

  1. 更新数据
  2. 驱动视图更新

wxml语法-setData()-修改对象类型数据

<!--index.wxml-->

<view>{{num}}</view>
<button type="primary" bind:tap="updateNum">更新 num</button>

<view>{{userInfo.name}}</view>
<view>{{userInfo.age}}</view>
<button type="warn" bind:tap="updateUserInfo">修改对象类型数据</button>
// index.js
Page({
  //在小程序页面中所需要使用的数据均来自于data对象
  data: {
    num: 1,
    userInfo: {
      name: 'tom',
      age: '10',
      test:111
    }
  },

  updateNum() {
    //获取数据
    console.log(this.data.num)
    //通过赋值的方式直接修改数据,能修改数据但是不能改变页面上的数据
    //this.data.num +=1
    // this.setData
    this.setData({
      //key 需要更新的数据
      // value 最新的值
      num: this.data.num += 1,
    })
  },
  updateUserInfo() {
    //新增单个/多个属性
    //  this.setData({
    //    //如果给对象新增属性,可以将key写成数据路径的方式 a.b.c
    //    'userInfo.name':'tom',
    //    "userInfo.age":10
    //  })
    //修改单个 / 多个属性
    // this.setData({
    //     //如果需要给对象修改属性,也可以将key写成数据路径的方式 a.b.c
    //     'userInfo.name':'jerry',
    //     'userInfo.age':15
    // })
    // 目前新增和修改都是使用数据路径,如果新增和修改的数据量比较小,还能接受
    //如果修改的数据很多,每次都写数据路径,就太麻烦了
    // 可以使用es6提供的展开运算符和Object.assign()
    
    
    //es6提供的展开运算符
    //通过展开运算符能够将对象中的属性复制给另外一个对象
    //后面的属性会覆盖前面的属性
    // const userInfo ={
    //   ...this.data.userInfo,
    //   name:'jerry',
    //   age:18
    // }
    
    // this.setData({
    //   userInfo
    // })
    
    //object.assign()  将多个对象合并为一个对象
    // const userInfo = Object.assign(this.data.userInfo,{name:'jerry'},{age:18})
    // console.log(userInfo)
    // this.setData({
    //   userInfo
    // })
    
    //删除单个属性
    // delete this.data.userInfo.age
    // this.setData({
    //   userInfo:this.data.userInfo
    // })
    
    //删除多个属性  rest 剩余参数
    const {age,test,...rest} = this.data.userInfo
    this.setData({
      userInfo:rest
    })
  }

})

wxml语法-setData()-修改数组类型数据

// index.js
Page({
  //在小程序页面中所需要使用的数据均来自于data对象
  data: {
    num: 1,
    userInfo: {
      name: 'tom',
      age: '10',
      test:111
    },
    list:[1,2,3]
  },

  updateList(){
   //新增数组元素
   //如果直接使用push方法,可以直接更新data,但是不能更新页面中的数据
  //  this.data.list.push(4)
  //  this.setData({
  //    list:this.data.list
  //  })
  
  // const newlist= this.data.list.concat(4)
  // this.setData({
  //   list:newlist
  // })

   //修改数组元素
  //  this.setData({
  //    'list[1]':6
  //  })

   //删除数组元素
   this.data.list.splice(1,1)
   this.setData({
     list:this.data.list
   })

  }

})

wxml语法-简易双向数据绑定

在wxml中,普通属性的绑定是单向的,例如:<input value="{{value}}" />

如果希望用户输入数据的同时改变data中的数据,可以借助简易双向绑定机制,在对应属性之前添加model:前缀即可:

例如 <input model:value="{{value}}"  />

注意事项:简易双向绑定的属性值如下限制:

  1. 只能是一个单一字段的绑定
  2. 尚不能写data路径,不支持数组和对象
<!-- <input type="text" value="{{value}}" /> -->

<!-- 双向绑定:数据能够影响页面,页面更新也能够影响数据 -->
<!-- <input type="text" model:value="{{value}}" /> -->
<!-- 如果需要获取复选框的选中效果,需要给checked 添加model: -->
<!-- <checkbox model:checked="{{isChecked}}">是否同意该协议</checkbox>{{isChecked}} -->
Page({
  //在小程序页面中所需要使用的数据均来自于data对象
  data: {
    value: 123,
    isChecked:false
  }

})

wxml-列表渲染-基本使用

列表渲染就是指通过循环遍历一个数组或对象,将其中的每个元素渲染到页面上

在组件上使用wx:for 属性绑定一个数组或对象,即可使用每一项数据重复渲染当前组件

每一项的变量名默认为item,下标变量名默认为index

在使用wx:for进行遍历的时候,建议加上wx:key属性,wx:key的值以两种形式提供:

  1. 字符串:代表需要遍历的array中的item的某个属性,该属性的值需要是列表中唯一的字符串或数字,其不能动态改变
  2. 保留关键字*this代表在for循环中的item本身,当item本身是一个唯一的字符串或者数字时可以使用

注意事项

  1. 如果不加wx:key,会报一个warning,如果明确知道该列表是静态,及以后数据不会改变,或者不必关注其顺序,可以选择忽略。
  2. 在给wx:key添加属性值的时候,不需要使用双大括号语法,直接使用遍历的array中item的某个属性
<view wx:for="{{list}}" wx:key="index">{{item}}</view>

wxml-列表渲染-进阶用法

1.如果需要对默认的变量名和下标进行修改,可以使用wx:for-itemwx:for-index

  • 使用wx:for-item可以指定数组当前元素的变量名
  • 使用wx:for-index可以指定数组当前下标的变量名

2.将wx:for用在<block/>标签上,以渲染一个包含多个节点的结构块

  • <block/>并不是一个组件,它仅仅是一个包装元素,不会在页面中做任何渲染,只接受控制属性
  • <block/>标签在wxml中可以用于组织代码结构,支持列表渲染、条件渲染等。

<view wx:for="{{fruitList}}" wx:key="id" wx:for-item="fruitItem" wx:for-index="i">
{{fruitItem.name}}{{i}}
</view>

<view wx:for="{{obj}}" wx:key="key" wx:for-item="objItem" wx:for-index="key">
{{objItem}}{{key}}
</view>

<block wx:for="{{fruitList}}" wx:key="id" wx:for-item="fruitItem" wx:for-index="i">
<view>名字:{{fruitItem.name}}</view>
<view>价格:{{fruitItem.price}}</view>
</block>

wxml语法-条件渲染

条件渲染主要用来控制页面结构的展示和隐藏,在微信小程序中实现条件渲染有两种方式:

1.使用wx:if、wx:elif、wx:else 属性组

2.使用hidden属性

wx:if和hidden二者的区别

  1. wx:if:当条件为true时将结构展示出来,否则结构不会进行展示,通过移除/新增节点的方式来实现
  2. hidden:当条件为true时将结构隐藏,否则结构会展示出来,通过display样式属性来实现的

生命周期-小程序运行机制

生命周期-小程序更新机制

// app.js
App({
   
  //onLaunch 是小程序的钩子函数,这个钩子函数在冷启动时肯定会执行到
  //当小程序冷启动时,会自动微信后台请求新版本的信息,如有新版本,会立即进行下载
 
 onLaunch(){
    // 使用 wx.getUpdateManager 方法监听下载的状态 
   const updateManager = wx.getUpdateManager()
   // 当下载完成新版本以后,会触发onUpdateReady 回调函数
   updateManager.onUpdateReady(function(){
     //  在回调函数中给用户提示
     wx.showModal({
       title: '更新提示',
       content: '新版本已经准备好,是否重启应用',
       complete: (res) => {
         if (res.confirm) {
           //强制当前小程序使用新版本并且会重启当前小程序
           updateManager.applyUpdate()
         }
       }
     })
   })
 } 

})

微信开发者工具可以模拟强制更新

先在编译模式这里添加编译模式=》然后保存刷新即可

生命周期-小程序生命周期介绍

应用生命周期是指应用程序进程从创建到消亡的整个过程

小程序的生命周期指的是小程序从启动到销毁的整个过程

一个小程序完整的生命周期由 应用生命周期、页面生命周期、和组件生命周期三部分来组成

小程序生命周期伴随着一些函数,这些函数由小程序框架本身提供,被称为生命周期函数,生命周期函数会按照顺序依次自动触发调用。帮助程序员在特定的时机执行特定的操作,辅助程序员完成一些比较复杂的逻辑。

生命周期-应用生命周期

应用生命周期通常是指一个小程序从启动=>运行=>销毁的整个过程

应用生命周期伴随着一些函数,我们称为应用生命周期函数,应用生命周期函数需要在app.js文件的App()方法中进行定义,App()方法必须在app.js中进行调用,主要用来注册小程序。

应用生命周期函数由 onLaunch、onShow、onHide三个函数组成

// app.js
App({ 
  /**
   * 当小程序初始化完成时,会触发onLaunch(全局只触发一次)
   */
 onLaunch(){
   //当进行冷启动时,才会触发 onLaunch 钩子函数
   //  如果是热启动,不会触发,onLaunch 钩子函数,会触发 onShow 钩子函数
   //因此呢 onLaunch (全局只触发一次)
    console.log('onLaunch 小程序初始化完成时')
 }, 

  /**
   * 当小程序启动,或从后台进入前台显示会触发onShow
   */
  onShow(){
    console.log('onShow 小程序启动,或从后台进入前台显示会触发')
  },
   /**
   * 当小程序从前台台进入后台显示会触发onHide
   */
  onHide(){
    console.log('onHide 当小程序从前台台进入后台显示会触发')
  }


})

生命周期-页面生命周期

页面生命周期就是指小程序页面从  加载=>运行=>销毁 的整个过程

页面生命周期函数需要在Page()方法进行定义

Page({

    /**
     * 页面的初始数据
     */
    data: {

    },

    /**
     * 生命周期函数--监听页面加载 --一个页面只会调用一次
     */
    onLoad(options) {
        console.log('onLoad 页面创建的时候执行')
    },

    /**
     * 生命周期函数--监听页面初次渲染完成 --一个页面只会调用一次
     */
    onReady() {
      console.log('onReady 页面初次渲染完成,代表页面已经准备妥当,可以和视图层进行交互')
    },

    /**
     * 生命周期函数--监听页面显示 -从后台进入前台也会触发
     */
    onShow() {
      console.log('onShow 页面在前台展示的时候')
    },

    /**
     * 生命周期函数--监听页面隐藏  -在当前小程序进入后台时,也会触发执行
     */
    onHide() {
      console.log('onHide 页面隐藏')
    },

    /**
     * 生命周期函数--监听页面卸载
     */
    onUnload() {
      console.log('onUnload 页面卸载,销毁')
    },
    /**
     * 页面相关事件处理函数--监听用户下拉动作
     */
    onPullDownRefresh() {

    },

    /**
     * 页面上拉触底事件的处理函数
     */
    onReachBottom() {

    },

    /**
     * 用户点击右上角分享
     */
    onShareAppMessage() {

    }
})

生命周期-生命周期两个细节补充

  1. tabBar 页面之间相互切换,页面不会被销毁
  2. 点击左上角,返回上一个页面,会销毁当前页面

小程序API-小程序API介绍

小程序API-网络请求

发起网络请求回去服务器的数据,需要使用wx.request()接口API

wx.request请求的域名必须在微信公众平台进行配置,如果使用wx.request请求未配置的域名,在控制台会有相应的报错。 

可以测试这个接口地址  :https://gmall-prod.atguigu.cn/mall-api/index/findBanner

  //如果需要发起网络请求,需要使用wxwx.request  API
    wx.request({
      //接口地址
      url: 'https://gmall-prod.atguigu.cn/mall-api/index/findBanner',
      //请求方式
      method: 'GET',
      //请求参数
      data: {},
      //请求头
      header: {},
      // API调用成功后的回调
      success: (res) => {
         if(res.data.code ===200){
           this.setData({
             list:res.data.data
           })
           console.log(this.data.list)
         }
      },
      // 失败的回调
      fail: (err) => {
        console.error(err)
      },
      // API 不管调用成功还是失败以后,执行的回调
      complete: () => {}
    })

小程序API-界面交互-loading提示框

小程序提供了一些用于界面交互的API,例如:loading提示框、消息提示框、静态对话框等API

loading提示框常配合网络请求来使用,用于增加用户体验,对应的API有两个:

  1. wx.showLoading()显示loading提示框
  2. wx.hideLoading()关闭loading提示框
   //显示loading 提示框
    wx.showLoading({
      //用来显示提示的内容
      //提示的内容不会自动换行,如果提示的内容比较多,因为在同一行显示
      //多出来的内容就会被隐藏
      title: '数据正在加载中...',
      // 是否展示透明蒙层,防止触摸穿透
      mask:true,
    })

小程序API-界面交互-模态对话框-消息提示框

wx.showModal()  : 模态对话框,常用于用户是否执行一些操作

例如:询问用户是否退出登录、是否删除商品等

wx.showToast()  消息提示框,根据用户的某些操作来告知操作的结果

例如:退出成功给用户提示,提示删除成功等

 async delHandler(){

    const res =  await wx.showModal({
       title: '是否删除商品',
       content: '羽毛球',
     })
     
     if(res.confirm){
        // showToast 消息提示框
        wx.showToast({
          title: '删除成功',
          icon:'none',
          duration:2000
        })
     }else{
       wx.showToast({
         title: '取消删除',
         icon:'error',
         duration:2000
       })
     }
  }

小程序API-本地存储

小程序本地存储是指在小程序中使用API将数据存储在用户的设备上,以便小程序运行时和下次启动时快速地读取这些数据

//将数据存到本地
  setstorage(){
    //第一个参数:本地存储中指定的key
    //第二个参数:需要存储的数据
    //wx.setStorageSync('num',1)
    //在小程序中
    //如果存储的是对象类型数据,不需要使用JSON.stringify 和JSON.parse 进行转换
    //直接进行存储和获取即可
    // wx.setStorageSync('obj', {
    //   name:'tom',
    //   age:10
    // })
    
    //---异步API

    wx.setStorage({
      key:'num',
      data:1
    })

    wx.setStorage({
      key:'obj',
      data:{
         name:'jerry',
         age:18
      }
    })

  },
  async getstorage(){
    //从本地存储的数据中获取 key 的数据
    // const num =wx.getStorageSync('num')
    // const obj =wx.getStorageSync('obj')

    //---异步API
    const num = await wx.getStorage({
      key:'num'
    })
    const obj = await wx.getStorage({
      key:'obj'
    })
    console.log(num,obj)
  },
  delstorage(){
    //从本地移除指定key的数据,内容
    // wx.removeStorageSync('num')

    //---异步API

    wx.removeStorage({
      key:'num'
    })
  },
  clearstorage(){
    //清空本地存储的全部数据
    //wx.clearStorageSync()

    //---异步API
    wx.clearStorage()
  }

小程序API-路由与通信

在小程序中实现页面的跳转,有两种方式:

  1. 声明式导航:navigator组件
  2. 编程式导航:使用小程序提供的API

小程序API-页面处理函数-上拉加载

上拉加载是小程序中常见的一种加载方式,当用户滑到页面底部时,会自动加载更多的内容,以便用户继续浏览

小程序中实现上拉加载的方式

  1. 在app.json  或者 page.json 中配置距离页面底部距离:onReachBottomDistance;默认50px
  2. 在页面.js中定义onReachBottom事件监听用户上拉加载

小程序API-页面处理函数-下拉刷新

下拉刷新是小程序中常见的一种刷新方式,当用户下拉页面时,页面会自动刷新,以便用户获取到最新的内容。

小程序中实现下拉刷新的方式

  1. 在app.json或者page.json中开启允许下拉,同时可以配置 窗口、loading 样式等
  2. 在页面.js中定义  onPullDownRefresh 事件监听用户下拉刷新

自定义组件-创建-注册-使用组件

小程序目前已经支持组件化开发,可以将页面中功能模块抽取成自定义组件,以便在不同的页面中重复使用;也可以将复杂的页面拆分成多个低耦合的模块,有助于代码维护。

开发中常见的组件有两种:

  1. 公共组件:将页面内的功能模块抽取成自定义组件,以便在不同的页面中重复使用。
  2. 页面组件:将复杂的页面拆分成多个低耦合的模块,有助于代码维护

如果是公共组件,建议放在项目根目录的components文件夹中

如果是页面组件,建议放在对应页面的目录下

建议:一个组件一个文件夹

开发中常见的组件分为公共组件页面组件两种,因此注册组件的方式也分为两种:

  1. 全局注册:在app.json文件中配置usingComponents进行注册,注册后可以在任意页面使用
  2. 局部注册:在页面的json文件中配置usingComponents进行注册,注册后只能在当前页面使用

在usingComponents中进行组件注册时,需要提供自定义组件的组件名和自定义组件文件路径

在将组件注册后以后,直接将 自定义组件的组件名当成组件标签名使用即可

自定义组件-组件的数据以及方法

组件数据和方法需要在.js的component方法中进行定义,component创建自定义组件

  1. data:定义组件的内部数据
  2. methods:在组件中事件处理程序需要写到methods方法中才可以

自定义组件-组件的属性

Properties是指组件的对外属性,主要用来接收组件使用者传递租界内内部的数据,和data一同用于组件的模板渲染

组件注册完成后使用,这边的数据有点类似与vue中的父传子

然后在组件的.js文件中,接收

然后就直接在组件页面元素上直接用就可以了

注意事项:

设置类型属性需要使用type属性,属性类型是必填项,value属性为默认值

属性类型可以为String、Number、Boolean、Object、Array,也可以为null表示不限制类型

自定义组件-组件wxml的slot-插槽

按照一下用法使用即可

自定义组件-组件样式以及注意事项

自定义组件拥有自己wxss样式,组件wxss文件的样式,默认只对当前组件生效。

自定义组件-组件样式隔离

自定义组件-数据监听器

数据监听器主要用于监听和响应任何属性(properties)和数据(data)的变化,当数据发生变化时就会触发对应回调函数,从而方便开发者进行业务逻辑的处理

在组件中如果需要进行数据监听 需要使用observers字段

用法如下

<view>{{num}}</view>
<view>{{count}}</view>
<view>{{obj.name}}</view>
<view>{{arr[1]}}</view>
<view>{{label}}</view>
<button type="warn" plain bind:tap="updateDate">
  更改数据
</button>
// components/custom04/custom04.js
Component({
  /**
   * 组件的属性列表
   */
  properties: {
     label:{
       type:String,
       value:'测试'
     }
  },

  /**
   * 组件的初始数据
   */
  data: {
    num: 10,
    count: 100,
    obj: {
      name: 'Tom',
      age: 10
    },
    arr: [1, 2, 3]
  },
  //用来监听数据变化
  observers: {
    //key :需要监听的数据
    //value :就是一个回调函数、形参:最新的参数
    //  num:function(newNum){
    //   //  对data中的数据进行监听,如果数据没有发生变化,监听不会执行
    //     console.log('变化了',newNum)
    //  },
    //  count:function(newCount){
    //    console.log(newCount)
    //  }

    //同时监听多个
    // 'num,count': function (newNum, newCount) {
    //   console.log(newNum, newCount)
    // }

    //支持监听属性以及内部数据的变化
    // 'obj.name': function (newObjName) {
    //   console.log(newObjName)
    // },
    // 'arr[1]':function(newItem){
    //     console.log(newItem)
    // }
    
    //使用通配符
    // 'obj.**':function(newObj){
    //    console.log(newObj)
    // }

    label:function(newLabel){
      //主要使用者传递了数据,这时在监听器中就能获取的数据
      // 也就是说,监听器立即就执行了
      console.log(newLabel)
    }

  },

  /**
   * 组件的方法列表
   */
  methods: {
    //更改数据
    updateDate() {
      this.setData({
        num: this.data.num + 1,
        // count: this.data.count - 1
        // 'obj.name': 'jerry',
        // 'arr[1]': '4'

      })
    }
  }
})

自定义组件-组件通信-父往子传值

自定义组件-组件通信-子传父

子组件如果需要向父组件传递数据,可以通过小程序提供的事件系统实现,可以传递任意数据。

  1. 自定义组件内部使用triggerEvent方法发射一个自定义的事件,同时可以携带任意数据
  2. 自定义组件标签上通过bind方法监听发射的事件,同时绑定事件处理函数,在事件函数中通过事件对象获取传递的数据

子组件

<button type="primary" plain bind:tap="sendData">传递数据</button>
Component({
    /**
     * 组件的属性列表
     */
    properties: {

    },

    /**
     * 组件的初始数据
     */
    data: {
        num:666
    },

    /**
     * 组件的方法列表
     */
    methods: {
      //传递数据给父组件
      sendData(){
        //如果需要将数据传递给父组件
        //需要使用 triggerEvent 发射自定义事件
        //第二个参数,是携带的参数
         this.triggerEvent('myevent',this.data.num); 
      }
    }
})

父组件

<view>{{num}}</view>
<!-- 需要在自定义组件标签上通过 bind方法绑定自定义事件,同时绑定事件处理函数 -->
<custom05 bind:myevent="getData"></custom05>

Page({
    data:{
      num:''
    },
  getData(event){

    //可以通过事件对象.detail 获取子组件传递给父组件的数据
    console.log(event)

    this.setData({
      num:event.detail
    })
  }
  
})

自定义组件-组件通信-获取组件实例

父组件可以通过 this.selectComponent方法,获取子组件实例对象,这样就可以直接访问子组件的任意数据和方法

this.selectComponent 方法在调用时需要传入一个匹配选择器  selector

首先在子组件上添加class或者id

<custom05 bind:myevent="getData" class="child" id="child"></custom05>

然后在父组件上操作即可

<button type="primary" plain  bind:tap="getChild">获取子组件的实例对象</button>
// pages/cart/cart.js
Page({
    data:{
      
    },
  getChild(){
  const res  =   this.selectComponent('.child')
  console.log(res)
  }
  
})

这样就可以获取到子组件的实例对象了。

自定义组件-组件生命周期

组件的生命周期:指的是组件自身的一些钩子函数,这些函数在特定的时间节点时被自动触发

组件的生命周期函数需要在 lifetimes字段内进行声明

组件的生命周期函数有5个:created、attached、ready、moved、detached

// components/custom06/custom06.js
Component({
  data:{
    name:'tom'
  },
  //组件生命周期声明对象
  lifetimes:{
    // created:组件实例被创建好以后执行
    created(){
        console.log('组件  created')
        //所以载cerated 钩子函数中不能调用setdata
        //可以给组件添加一些自定义的属性,可以通过this的方式进行添加
        this.test = '测试'
        // this.setData({
        //   name:'jerry'
        // })
    },
    //attached:组件初始化完毕,模板解析完成,已经把组件挂载到页面上
    attached(){
      console.log('组件  attached')
      console.log(this.test)
      //一般页面中的交互会在attached 钩子函数中进行执行
       this.setData({
          name:'jerry'
        })
    },
    //组件被销毁
    detached(){
      console.log('组件  detached')
    }
  }   
})

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

// components/custom06/custom06.js
Component({
  data:{
    name:'tom'
  },
 
  // 组件所在页面的生命周期
  pageLifetimes:{
    //监听组件所在的页面展示(后台切前台)状态
    show(){
       console.log('组件所在的页面被展示')
    },
    //监听组件所在的页面隐藏(前台切后台,点击tabBar)状态
    hide(){
      console.log('组件所在的页面被隐藏')
    }
  }   
})

 自定义组件-小程序生命周期总结

自定义组件-使用Component构造页面

简而言之就是用构建组件的Component  方法来替换掉page 方法,相比于page来说,Component 提供的方法更多

1.正常新建页面

2.然后将page方法改成Component 在 detail.js中

Component({
  // 为什么需要使用  Component 方法进行构造页面
  //Component  方法功能比Page方法强大很多
  //如果使用Component 方法构造页面,可以实现更加复杂的页面逻辑开发

  //小程序页面也可以使用Component方法进行构造
  //注意事项:
  //1.要求.json文件中必须包含usingComponents字段
  //2.里面的配置项需要和 Component中的配置项保持一致
  //3.页面中Page方法有一些钩子函数,时间监听方法,这些钩子函数、事件监听方法必须放在methods对象中
  //4.组件的属性  properties  也可以接收页面的参数,在onLoad 钩子函数中可以通过this.data 进行获取
  properties:{
     id:String,
     title:String
  },
  data: {
    name: 'tom'
  },
  methods: {
    //更新name
    updateName() {
      this.setData({
        name: 'jerry'
      })
    },
    onLoad(options){
      // console.log('页面创建',options)
      console.log(this.data.id)
      console.log(this.data.title)
    }
  }

})

3.datail.json  中必须要有  usingComponents

{
    "usingComponents": {}
}

4.从其他页面传递过来的参数现在就可以有联众方式接收

1. 组件的properties方法

2.生命周期onLoad 函数

<navigator url="/pages/detail/detail?id=10&title=测试">跳转到详情页面</navigator>

自定义组件-拓展:组件复用机制behaviors 

const behavior =  Behavior({
      /**
     * 组件的属性列表
     */
    properties: {
      label:{
        type:String,
        value:'我已同意该协议'
      }
    },

    /**
     * 组件的初始数据
     */
    data: {
        name:'Tom',
        obj:{
          name:'Tyke'
        }
    },

    /**
     * 组件的方法列表
     */
    methods: {
        updateName(){
           this.setData({
             name:'Jerry'
           })
        }
    },
    lifetimes:{
      attached(){
        console.log('我是组件behavior生命周期函数')
      }
    }


})

export default behavior;

// components/custom08/custom08.js
import behavior from './behavior'
Component({
  behaviors:[behavior],

  //在以后开发中,使用 behaviors 进行代码复用的时候
  //组件和 behaviors 可能存在相同字段

  //如果存在相同的properties,就近原则,使用组件内部的数据

  properties:{
    label:{
      type:String,
      value:'匿名提交'
    }
  },
  //如果存在相同的data
  //如果是对象类型,属性会进行合并
  //如果不是对象类型的数据,就近原则,展示的以组件内部为准
  data:{
    name:'组件中的name',
    obj:{
      name:'组件中的name',
      age:100
    }
  },
  //如果存在相同的方法,就近原则,使用组件内部的方法
  methods:{
    updateName(){
      console.log('我是组件内部的方法!!!')
    }
  },
  //如果存在相同的生命周期函数,生命周期函数都会被触发
  lifetimes:{
    attached(){
      console.log('我是组件内部的生命周期函数')
    }
  }
  
})

 自定义组件-拓展:外部样式类

 

这样就能在外面修改组件的样式了。

自定义组件-总结自定义组件

npm支持-如何使用npm包

目前小程序已经支持使用npm安装第三方包,因为node_modules目录中的包不会参与小程序项目的编译、上传和打包,因此在小程序项目中要使用npm包,必须走一遍构建npm的过程。

在构建成功以后,默认会在小程序项目根目录,

也就是 node_modules同级目录下生成miniprogram_npm目录,

里面存放着构建完成以后的npm 包,也就是小程序运行过程中真正的包

vant微信小程序版icon-default.png?t=O83Ahttps://vant-ui.github.io/vant-weapp/

以vant 为例  先安装  ,安装好后就会有node_modules 目录,然后再到工具=>构建npm =>就会生成

miniprogram_npm目录

这边要注意安装的时候可能会报错,退出微信小程序开发工具,然后以管理员身份运行应该就可以解决了。

注意事项:

小程序运行在微信内部,因为运行环境的特殊性,这就导致并不是所有的包都能够在小程序使用

我们在小程序中提到的包指专为小程序定制的npm 包,简称小程序包 npm 包,在使用包之前需要先确定改包是否支持小程序

开发者如果需要发布小程序包,需要参考官方规范

npm支持-自定义构建npm

在实际的开发中,随着项目的功能越来越多、项目越来越复杂、文件目录也越来越繁琐,为了方便进行项目的开发,开发人员通常会对目录结构进行调整优化,例如:将小程序源码放miniprogram 目录下

这时候就需要开发者在project.config.json中 指定node_modules的位置和目标miniprogram_npm 的位置

具体配置如下

  1. 配置project.config.json的miniprogramRoot指定小程序源码的目录
  2. 配置project.config.json的setting.packNpmManually为true,开启自定义node_modules的位置和目标miniprogram_npm 位置 的构建 npm方式
  3. 配置project.config.json的setting.packNpmRelationList项,指定package.JsonPath和miniprogramNpmDistDir的位置

npm支持-vant weapp组件库的使用

在使用vant提供的组件时,只需要两个步骤:

  1. 将组件在app.json中进行全部注册或者index.json中进行局部注册
  2. 在引入组件后,可以直接在wxml中直接使用组件

注意事项:

将app.json中的style:v2去除,小程序的新版基础组件强行加上了许多样式,难以覆盖,不关闭将造成部分组件样式混乱。

npm支持-vant weapp组件样式覆盖

vant weapp基于微信小程序的机制,为开发者提供了3种修改组件样式的方法

  1. 解除样式隔离:在页面中使用vant组件时,可直接在页面的样式文件中覆盖样式
  2. 使用外部样式类:需要注意的是普通央视和外部样式类的优先级是未定义的,使用时需要添加 !important保证外部样式的优先级
  3. 使用css变量:在页面或全局对多个组件的样式做批量修改以进行主题样式的定制

分包加载-小程序分包加载

分包加载-配置分包加载以及打包、引用原则

小程序如果需要进行分包加载,需在app.json中,通过 subPackages或者subpackages定义分包结构

每个分包结构含三个常用字段:

  1. root:分包的根目录,该目录下的所有文件都会被打包成一个独立的包
  2. name:分包的别名,用于在代码中引用该分包
  3. pages:指定当前分包中包含那些页面

例如:配置商品模块分包,分包包含:商品列表、商品详情两个页面

 分包加载-独立分包

分包加载-分包预下载

开放能力-获取微信头像

<view>
<button class="btn" open-type="chooseAvatar" bindchooseavatar="chooseavatar">
<image class="avatar" src="{{avatarUrl}}" mode="aspectFill"></image>
</button>
</view>
// index.js
Page({
  //在小程序页面中所需要使用的数据均来自于data对象
  data: {
    avatarUrl:'../../assets/banner/banner.jpg'
  },

  //获取微信头像
  chooseavatar(event){
      console.log(event)
      const {avatarUrl} = event.detail;
      this.setData({
        avatarUrl
      })
  }


})

.btn{
  background-color: transparent;

}
.btn::after{
  border: none;
}
.avatar{
  width: 200rpx;
  height: 200rpx;
  border-radius: 50%;
}

开放能力-获取微信昵称

<form bindsubmit="onSubmit">
<input type="nickname" name="nickname" placeholder="请输入昵称" />
<button type="primary" plain form-type="submit">点击获取昵称</button>
</form>
// index.js
Page({
  //在小程序页面中所需要使用的数据均来自于data对象
  data: {
    
  },
  //获取微信昵称
  onSubmit(event){
    console.log(event)
  }


})
input{
  border: 1px solid #179c16;
  margin: 20rpx ;
  height: 60rpx;
  border-radius: 20rpx;
  padding-left: 20rpx;
}

开放能力-转发功能

// pages/cate/cate.js
Page({

    /**
     * 页面的初始数据
     */
    data: {

    },

    /**
     * 用户点击右上角分享
     */
    onShareAppMessage(obj) {
      console.log(obj)
      
      return{
        title:'这是一个非常神奇的页面',
        path:'/pages/cate/cate',
        imageUrl:'../../assets/banner/banner.jpg'
      }

    }
})
<button open-type="share">转发</button>

开放能力-分享到朋友圈

开放能力-手机号验证组件

<button type="primary" open-type="getPhoneNumber" bindgetphonenumber="getphonenumber">快速验证组件</button>

<button type="warn" plain open-type="getRealtimePhoneNumber" bingetrealtimephonenumber="getrealtimephonenumber">实时验证组件</button>

 

// pages/cart/cart.js
Page({
    data:{
      num:''
    },
    // 手机号快速验证
    getphonenumber(event){
      //通过事件对象,可以看到,在event.detail中可以获取到code
      //code动态令牌,可以使用code换取用户手机号
      //需要将code发送给后端,后端在接收到code以后
      //也需要调用API,换取用户的真正手机号
      //再会将手机号返回给前端
     console.log(event)
    },
    //手机号实时验证
    getrealtimephonenumber(event){
      console.log(event)
    }
  
})

个人开发者账号没办法使用,会提示没有权限。

开放能力-客服功能

补充-框架接口-getApp()

App.js

// app.js
App({ 
   //全局共享的数据
   globalData:{
     token:''
   },
   //全局共享的方法
   setToken(token){
      //如果想获取token,可以使用this的方式进行获取
      this.globalData.token = token;
      
      //在 App() 方法中如果想获取实例,直接通过this就可以获取到

   }

})

 其他页面使用

<button type="primary" plain bind:tap="login">登录</button>
//getApp() 方法用来获取全局唯一的App()实例

const appInstance = getApp()

Page({
  data:{
      num:1,
  },
  
  login(){
    // console.log(appInstance)
    appInstance.setToken('hdhhhdhdhhhdhdh')
  }

})

补充-页面间通信

 

当前页面

 

<button type="warn" plain bind:tap="handler">跳转到列表页面</button>
// index.js
Page({
   //点击按钮触发的事件处理函数 
  handler(){

    wx.navigateTo({
      url: '/pages/list/list',
      events:{
         //key  被打开页面通过  EventChannel 发射的事件
         //value  回调函数
         //为事件添加一个监听器,获取到被打开页面传递给当前页面的数据
         currentevent:(res)=>{
            console.log(res)
         }   
      },
      success(res){
       console.log(res)
       //通过success 回调函数的形参,可以获取eventChannel 对象
       //eventChannel 对象给提供了emit 方法,可以发射事件,同时携带参数
       res.eventChannel.emit('myevent',{
         name:'tom'
       })
      }
    })
  }

})

跳转页面

// pages/list/list.js
Page({
   onLoad(){
     //通过 this.getOpenerEventChannel() 可以获取 EventChannel 对象
     const EventChannel=  this.getOpenerEventChannel()
     //通过 EventChannel 提供的 on 方法 监听页面发射的自定义事件
     EventChannel.on('myevent',(res)=>{
       console.log(res)
     })

     //通过 EventChannel 提供的 emit 方法也可以向上一级页面传递数据
     //需要emit定义自定义事件,携带需要传递的参数
     EventChannel.emit('currentevent',{age:10})

   }
    
})

补充-组件通信-事件总线

1.先安装  pubsub.js这个包

npm install pubsub-js

这边要注意!!!!  微信开发者工具可能会由于权限问题报错,可以先退出一下然后使用管理员身份运行,在安装就可以了

2.安装好包后,记得在工具中构建下npm

组件a 代码

<view class="a">
子组件a
  <button bind:tap="sendData">传递数据给兄弟</button>
</view>

 


import PubSub from 'pubsub-js'

Component({
    data:{
       name:'TOM'
    },
    /**
     * 组件的方法列表
     */
    methods: {
        
      sendData(){
        // publish 发布,发射自定义事件
        //1.自定义事件的名称
        //2.需要传递的数据
        PubSub.publish('myevent',{
          name:this.data.name,
          age:10
        })

      }
    }
})

组件b接收兄弟组件a传递的数值

<view class="b">
子组件b  收到的参数为 
<view>{{name}}</view>
</view>
// components/custom04/custom04.js
import PubSub from 'pubsub-js'

Component({
  /**
   * 组件的初始数据
   */
  data: {
    name:''
  },
 

  /**
   * 组件的方法列表
   */
  methods: {

  },
  lifetimes:{
    attached(){
      //subscribe 订阅、监听自定义的事件
      //1.需要订阅、监听的自定义事件名称
      //2.回调函数,回调函数有两个参数
      // msg  自定义事件的名称
      // data  传递过来的数据

      PubSub.subscribe('myevent',(msg,data)=>{
       console.log(msg,data)
     this.setData({
       name:data.name
     })

      })
    }
  }
})

补充-自定义导航栏

小程序上线发布

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值