构建小程序总结

创建小程序

  • 创建小程序:没注册过的邮箱
  • appid:微信公众平台登陆小程序,开发栏可查看

小程序项目结构

APP(宏观主体): 
	app.js(创建app实例以及一些全局相关内容) 
	app.json(全局配置:window,tabbar等) 
	app.wxss  (全局的一些配置)

Page(页面):
	page.js(创建page实例的代码,以及相关内容)
	page.json:(业务单独的配置,比如页面对应的window配置,usingComponents)
	page.wxml:页面的wxml布局代码
	page.wxss:页面的样式配置
	
Component:
	component.js : 创建component实例的代码以及组件内部的内容
	component.json : 组件内部的配置,比如当前组件使用了别的组件
	component.wxml : 布局代码
	component.wxss : 样式代码
	

小程序三体验

1.数据绑定:
	在页面或者组件的中的js文件中的data定义 ,在wxml中使用{{}} 使用
	
2.列表渲染:
	<view wx:for='{{student}}'>{{item.name}}+{{item.age}}</view>: student为js中的数组数据 ,item为微信自动生成的变量,为遍历出的每一项数据
	
3.事件监听:
	bindTap:监听点击事件  
注意: 在js中修改数据的时候,不能直接修改,必须使用this.setData({})

小程序配置文件:project,sitemap

1.project : 小程序功能版本,一般不手动修改,而是在详情中修改

2.sitemap : 配置小程序搜索

3.app.json全局配置:
	1.所有使用的页面都必须在pages下注册
	2.window默认窗口配置:navigationBarBackgroundColor(导航颜色)navigationBarTextStyle(导航文字颜色) navigationBarTitleText(导航标题) enablePullDownRefresh(开启全局下拉刷新)
	3.底部tabbar:(配置图片可以将iconfont导出为图片进行使用)
	    =>list数组中每个对象都是一个tabbar,对象中可以配置item选中和未被选中的图标,和文字,图片就新建文件夹放在项目中,用绝对路劲使用
		=>和list同级,还可以设置选中tabbar的字体颜色,具体查文档
	4.page页面配置:  
		1.调用公共组件
		2.配置和全局不一样的属性(如:导航样式等等,具体查看文档)

小程序的双线程模型

谁是小程序的宿主环境呢?=>微信客户端
  宿主环境为了执行小程序的各种文件:wxml wxss js 提供了小程序的双线程模型
  wxml和wxss运行于渲染层 ,js运行为逻辑层   ,这两个线程都会经由微信客户端(native)进行中转交互

小程序的启动流程

 1.微信下载小程序包 ->  启动小程序  ->  加载解析app.json  -> 注册App() (也会执行App生命周期) -> 加载自定义组件代码(注册自定义组件) 
  -> (1.解析page.json 2.渲染层加载渲染page.wxml  3.逻辑层注册page()) ->执行Page生命周
  
 2.注册App做什么
App生命周期
  => onlaunch:小程序初始化完成执行 
  =>onShow(options):小程序页面显示之后执行
	1.可监听小程序的进入场景 可以通过options查看 
	2. 获取用户信息 wx.getUserInfo(这个接口即将废弃) 现行方案:使用按钮,让用户自己来确认,按钮设置  		属性:<button open-type=‘getUserInfo’ bindgetUserInfo=”method“>获取信息</button> 然后打印          传入默认参数的详情信息中就有 method(event){ console.log( event.details )}
	3.拓展:(可以不再生命周期中使用) 展示用户信息:<open-data></open-data> (可以在文档中的组件中查看使用 ->组件->开放能力)使用:<open-data type="user..."></open-data>具体查看文档
  =>onHide:界面被隐藏时执行
  =>onError:当程序出现错误的时候执行

3.注册Page做什么:
	=>1.在js的onload生命周期中发送数据请求 (设置this.setData的时候注意this的指向,微信提供的请求api       一般用箭头函数来解决this指向问题)
	=>2.在data中初始化一些数据
	=>3.监听上拉,触底事件

常用的内置组件

text组件:       
行内标签 其中的文本默认不能被选中 
1.可以设置能被选中 <text selectable=‘{{true}}’> helloWorld </text>  ->如果不用mastache语法,传入的是字符串,而不是布尔值,
2.还能设置space属性,设置空格大小      3.解码属性 decode :可用于大于号小于号等其他符号的解码

button组件:
1.默认块级元素,如果设置了size='mini',就会变为行内块元素
2.可以设置type来设置颜色
3.plain属性 边框
4.loading属性,加载小圆圈 
5.设置点击样式,添加属性hover-class=”ppd“ 然后再wxss中设置样式 .ppd{ color:red;....}

view组件:
容器组件,常用属性
1.hover-class 当用户按下后的属性 (当用户松手,会恢复原有的属性)
2.hover-style-time 样式停留时间
3.hover-stop-propagation 阻止冒泡

image组件:
1.lazy-load属性:图片懒加载
2.bindload:监听图片加载完成事件
3.还有长按识别小程序二维码的功能 
4.也有能设置图片在image盒子中的缩放拉伸模式

input组件:
1.value属性:input中的默认值
2.type属性:text ....
3.confirm-type属性:设置弹出键盘右下角的文字  还有一些input的事件具体查看文档

----------------------------------------------------------------------------
scroll-view组件:
实现局部滚动(水平滚动和垂直滚动)
=>水平滚动:
(scroll-view作为父盒子设置宽高和(white-space: nowrap不换行) ,子盒子inline-block (行内元素))
	 <scroll-view class=”container“ scroll-x>
		<view v-for="{{10}}"> 子盒子 </view>
	 </scroll-view>
=>垂直滚动:
 <scroll-view class=”container“ scroll-y>
		<view> 子盒子 </view>
  </scroll-view>
=>scroll-view的事件:
 bindscroll事件,可监听滚动的高度 ,还有类似事件和使用查看具体文档

-------------------------------------------------------------------------------
所有组件的共同属性: id  class  style  hidden(布尔值)  data- (自定义属性)  bind/catch 组件的事件

Mustache ,wxss,wxml,wxs

Mustache :
1.可以写入多个变量 {{ a + b }}
2.可以写表达式 {{ age>=10 ? '成年人': '未成年人' }} (题外话:获取当前时间 new   Date().toLocaleString)
3.如何点击按钮,切换某个元素的样式(小程序不允许使用DOM操作):
定义一个布尔值bool,在按钮的点击事件中每次点击都取反, 在需要变换的元素上使用Mustache语法 class=”box {{bool?‘active’:‘’}} “

wxss:
1.支持的选择器: .class #id  element ::after  ::before
2.扩展单位: rpx 规定屏幕宽度为750rpx (ipone屏幕宽度为375px ,相当于 1rpx = 2px)
3.样式导入,有时候可能会将样式分在多个wxss文件中  ,在页面或者组件中新建文件夹存放多个css,然后再主css中 @import ‘./xxx/xxx.css’
4.导入官方样式库:WeUI ,具体将WeUI在github上download下来,用微信开发工具跑起来,用什么就引用什么(注意一些组件除了css还绑定了很多js)
    
wxml:
wx:if  wx:elif wx:else  hidden  wx:for  wx:for-item  wx:for-index
1.=>使用变量控制某个元素的显示和隐藏 <view wx:if="{{isShow}}"></view>

2.=><view wx:if={{score >= 90}}>优秀</view>  <view wx:elif={{score >= 90}}>优秀</view>
    
3.=>hidden为true的隐藏 ,为false的时候显示 ,使用hidden的时候组件依然存在,只是没有显示,而使用wx:if组件跟本就没有被创建出来,当需要频繁切换的时候,推荐使用hidden

4.=>wx:for 一般用于列表数据:<view wx:for="{{list}}"> {{item}} <view> :item默认为列表数据中的每一项

5.=>block标签作用(不是组件):在使用wx:if,wx:for等指令的时候常常是一组标签配合使用,此时我们可以用block来包裹,也可以用view,但是使用view会创建额外的属性

6.=>wx:for-item , wx:for-index一般用于多层遍历,需要使用多个item和index,此时就要重命名来使用
	<block wx:for="{{nums}}" wx:for-item='n'> {{n}} </block>

7.=>列表渲染key:使用wx:for时会报警告,这个提示告诉我们,可以添加一个key提高性能
	为什么?大概阐述就是:没有key时,一旦涉及改变,被改变的元素以及后面的元素全部会被重新改变渲染,有key时,会识别复用的元素,元素会插入,而不是直接替换后面所有
    
wxs:
1.在wxml中是不能直接调用page中定义的函数的 {{ myfun( xxx) }}:错误 ,但是在某些情况我们需要过滤某些数据的时候,就需要使用wxs
2.定义一些公共方法,供其他地方调用,比如转换时间戳
3.使用:(详细步骤可看文档)根目录下创建wxs文件夹,创建wxs文件,书写函数,导出,在需要使用的页面或者组件中按需导入对应的方法即可

事件-对象-传递参数-冒泡和捕获

事件:
1.某些组件会有自己特性的事件类型,大家可以在使用组件时具体查看对应的文档
比如input有bindinput / bindblur / bindfocus 等  scroll-view有bindscrolltowpper  / bindscrolltolower 等 更多的事件查看文档

事件对象:
当某个事件触发时,会产生一个事件对象,并且这个对象被传入到回调函数中,事件对象有哪些常见的属性呢?
type 事件类型  
timeStamp  页面打开事件触发经过的事件
target  触发事件的组件的一些属性值集合   :记录产生事件的元素
currentTarget  当前组件的一些属性值集合	 :记录触发事件的元素
detail   额外的信息(点击的位置等)
touches  触摸事件,当前停留在屏幕中的触摸点信息的数组  :记录多个手指触摸
changeedTouches  触摸事件,当前变化的触摸点信息的数组  :本来有一个手指,再增加一个手指,触发一次

事件的传递参数:
有三个含有文本内容的view,我们需要点击获取view中的文本,如何获取?
首先,小程序中,不能再点击事件中直接传入 ,而是要使用data-xxx=‘xxx’   例:data-index=‘{{index}}’  在js中取值:event.currentTarget.dataset;

事件冒泡和事件捕获:
1.监听事件冒泡和捕获:capture-bind:tap  ( 必须使用: )  bind:tap
2.使用bind:一层层传递   catch:阻止事件的传递

组件化开发

一.组件化开发:
1.新建components目录,创建components组件
=>当创建组件的时候,.json中会默认加上属性"component": true (此属性代表这是自定义组件,不要随意删除)
2.使用自定义组件
=> 先在需要使用的页面或者组件的.json文件下的usingComponents下定义需要使用的组件才可以正常使用 { '使用时的组件名': ’调用的组件路径‘ }

二.使用自定义组件和细节:
1.自定义组件的标签名只能包含 小写字母,中划线 ,下划线  (一般使用中划线, 因为一些官方组件使用的也是中划线:scroll-view)
2.自定义组件中也能使用其他自定义组件,步骤和在页面中一样
3.在app.json添加usingComponents属性,可以做到全局注册,其他页面和组件直接使用

三.组件的样式细节:
1.在使用class来修改样式的时候,默认会有一个隔离,使页面和组件的样式相互不冲突,所以为了样式不错乱,一般不使用id、属性、标签选择器
2.如何让组件和页面样式能够被单向或者相互影响,在组件的js文件中,options属性下设置styleIssolation:’xxx‘ (具体查看文档)

给组件传递数据和样式

1.很多时候,组件内的展示内容,并不是在组件内写死的,而是由使用者来决定
=> 页面可以向组件传递 : 数据(properties) 样式(externalClasses) 标签(slot)
=> 组件向页面传递他发生的行为 : 自定义事件

2.传递数据的具体步骤:
=>1.在自定义组件中的properties中定义一个属性 title:String ,此属性可以直接在组件中用{{}}调用使用 , 然后再父组件中传入title属性值  <cpn title="哈哈哈" />
=>2.上面那种定义方式是最简单切无默认值的,可以设置对象值 title:{ type:String ,value:‘默认值’ ,observer:function(){...}   }   observer可以监听title的每次改变

3.传递样式的具体步骤:
=>1.给组件的标签添加一个样式titleclass
=>2.这个样式并不是自定义组件写的,而是由父组件传入  ,在自定义组件中定义一个内置属性来接收传入的样式:externalClasses:['titleclass']  (externalClasses与properties同级)
=>3.在父组件调用时,传入我们需要定制的样式  <cpn titleclass="red" />  <cpn titleclass="ool" />
=>4.传入的red/ool代表父组件中的类名 .red{color:red; } .ool {font-size:18px}
=>这样,自定义组件就成功使用了父组件中传入的样式

4.组件向外传递事件-自定义事件
=>由子组件发出,父组件接收,子组件传递的数据,默认在event当中可打印出 (具体使用时查看文档,和vue很像)

获取组件对象的方式

1.在组件外部修改组件数据,核心就是调用组件内部的this.setData({ }) => 组件对象.setData({})
2.获取组件对象 : this.selectComponent('class/id')   (文档搜索selectComponent)

插槽slot

1.组件的插槽是为了让我们封装的组件更加具有扩展性,让使用者决定组件内部的一些内容到底展示什么
2.插槽的使用:
=>单个插槽,直接在自定义组件中使用<slot></slot>
=>多个插槽:
	=>在自定义组件中给每一个插槽都添加一个name属性 <slot name=“slot1”></slot>  
	=>必须在component对象中添加一个选项:options     options:{ multipleSlots:true }
	=>使用的时候 <view slot="slot1"></view>

总结Component构造器

总结Component构造器:
1.properties:让使用者传入数据
2.data:定义组件内部的初始化数据
3.methods:用于定义组件内部的函数   (page页面中,函数方法可直接写在data下面,组件里不行,必须写在methods下)
4.options:组件的配置选项
5.externalClasses:外界给组件传入额外的样式
6.observers:可以监听properties/data的改变
7.pageLifetimes:页面生命周期  (查看文档)
8.lefetimes:组件生命周期  (查看文档)

小程序的网络请求

wx.request({
  url: 'http://123.207.32.32:8000/api/xxx',
  method:'post'   //不设置默认get
  data:{
     type:'sell',
     page:1
  },
  success:function(res){
    console.log(res);
  },
  fail:function(err){
    console.log('获取失败')
  }
})
除了url,method,data,success等属性,还有很多其他属性,具体查看文档

网络请求的封装:
新建js文件,使用promise封装小程序网络请求api,导出方法,在需要的地方直接调用
export default function request(options) {
  return new Promise((resolve, reject) => {
    wx.request({
      url: options.url,
      method: options.method || 'get',
      data: options.data || {},
      success: resolve,
      fail: reject
    })
  })
}
使用:
import request from '../../services/network.js'
request({
 url:'http://123.207.32.32:8000/api/m3/recommend'
}).then(res=>{
 console.log(res)
})

弹窗,分享,以及登陆流程

1.弹窗
官方文档 => API => 界面 => 交互
wx.showToast:显示提示框 (可设置时间,文本,icon,蒙版)
wx.showModal:显示模态框 (可以设置标题,内容,以及点击确定和取消的回调函数,也可以设置只有确定按钮,和更改按钮文本)
wx.showLoading:显示加载框 (需主动调用 wx.hideLoading 才能关闭提示框,一般切换页面,加载数据,请求数据的时候使用)
wx.showActionSheet:显示操作菜单 (设置弹出菜单,和菜单项,也有回调函数)

小程序中的分享

小程序文档 => 框架接口 => 页面 => page  => onShareAppMessage
调用小程序api:相当于页面生命周期:
onShareAppMessage:function(options){
    return:
}

分享按钮:
<button open-type="share"> 分享</button>

小程序的登陆流程

官方流程:
1.调用wx.login获取code

2.调用wx.request发送code到我们自己的服务器(我们自己的服务器会返回一个登陆态的标识,比如token)
	=>这个code客户端不需要用,是需要发送给服务端的,wx.request()发送code
	=>服务端拿到 code + appid + appsecret (后两个可在小程序控制台拿到),将这三个通过接口发送给微信官方       服务器,微信服务器就会返回session_key + appid
	=>服务端自定义登陆态  与 oppenid ,session_key关联 (项目可能除了微信登陆还需要账号密码)
	=>服务器返回自定义登陆态 (token)
	
3.将登陆态的标识token进行存储(可保存在storage),以便下次使用

4.请求需要登陆态标识的接口时,携带token
	=>请求一些需要登陆的接口时,就需要携带token
	
	
登陆伪代码演示:
    //1.先从缓存中取出token,如果没有,就需要重新登陆
    const token = wx.getStorageSync(token)
    //2.判断token是否有值
    if(token && token.length !==0){
      //此时已经有token,验证token是否过期
      wx.request({
        url: 'xxxx',
        header:{
          token
        },
        success:res =>{
          if(!res.data.errCode){
            this.globalData.token = token
          }else{
            //重新进行登陆操作,可封装成一个方法,到时候直接调用方法
          }
        },
        fail:err=>{

        }
      })
    }else{
      //登陆操作
      wx.login({
        //code只有五分钟的有效期
        success: (res) => {
          //1.获取code
          const code = res.code;

          //2.将code发送给我们的服务器
          wx.request({
            url: 'http://123.207.32.32:8000/api/m3/login',
            method: 'post',
            data: {
              code
            },
            success: (res) => {
              //1.取出token
              const token = res.data.token
              //2.将token保存到全局globalData中 :当别的页面或组件需要获取的时候=> const app=getApp()                                                 =>  app.globalData.token
              this.globalData.token = token

              //3.放到对象中,关闭小程序再开又要重新登陆,所以我们要记录到本地存储当中
              wx.setStorageSync('token', token)
            }
          })
        }
      })
    }

页面跳转,跳转时数据传递

页面跳转有两种方法:
1.通过navigator组件
2.通过wx的API跳转


=>1.通过navigator组件:
还有很多常用的属性,具体可以查看文档
<navigator  url="xxxx/xxx">跳转到详情页</navigator>

=>跳转过程中数据的传递
<navigator  url="xxxx/xxx ?name=why&age=18'>跳转到详情页</navigator>

=>如何在跳转的页面中拿到传过来的数据?
在页面生命周期函数onload中的默认参数options中可获取到
onLoad:function(options){
    console.log(options)
}

=>如何在跳转页面的时候修改数据
可以通过getCurrentPages来获取所有的页面,然后使用页面对象的setData({})函数来修改

=>2.通过代码跳转页面跳转
xxx(){
    wx.navigaTo({ url:'xxxx?...'})
    ...还有很多种方式的跳转,具体查看文档
}
原文地址:https://www.cnblogs.com/JCDXH/p/12864584.html