微信小程序


前情:一般微信小程序大小不能超过2mib(兆),图片文件一般都是引入在线图片的形式。

一、基本语法

基本结构
尽量参考官网组件的样式

1. 列表渲染和条件渲染

<!-- 1. {{}} 和vue一样,可以写单行js表达式,直接使用js文件里面data函数中的数据 -->
<view>
  <text>name:{{name}} -- age:{{age}}</text>
</view>

<!-- 2. 列表渲染。微信小程序指令是wx开头wx:for 遍历数组或者对象,重复生成对应的组件。和vue的v-for用法相同。默认索引是index,默认变量的元素是item。需要指定唯一key值,提高diff算法对比效率 -->
<view wx:for="{{user}}" wx:key="index">
  <text>{{index}}-name: {{item.name}}--age: {{item.age}}</text>
  <view>是否成年:{{item.age>=18?'Yes':'No'}}</view> 
</view>

<!-- 3. 修改默认的index索引值和 item元素变量名称 -->
<view wx:for="{{user}}" wx:for-index="i" wx:for-item="o" wx:key="name">
  <view>{{i}} - 姓名:{{o.name}}</view>
  <view>年龄:{{o.age}}</view>
</view>

<!-- 4. wx:if 条件渲染 -->
<view wx:if="{{age>=18}}">成年人</view>
<view wx:elif="{{age>12}}">青少年</view>
<view wx:else>未成年</view>

<!-- 6. include 引入外部的wxml文件 -->
  <include scr="/home/home.wxml"></include>

<!-- 7. 事件,点击事件是bindtap,点击组件触发点击事件,可以执行js创建的函数 -->
  <view bindtap="goClick">点击事件</view>
  <view>error</view>

<!-- 8. 组件跳转页面 -->
  <navigator url="/pages/index/index">跳转到首页</navigator>

js

Component({
  data: {
    name:"anna",
    age:19,
    user:[
      {name:'zs',age:19},
      {name:'fs',age:29},
      {name:'jsa',age:15},
      {name:'op',age:16},
    ],
  },
  goClick(){
    console.log("success!");
  },
})

2. 模版 template

template定义需要name,使用需要用 is

  1. 第一种
<!-- 模版: 可以把代码片段写到template组件里面,在需要的地方调用模版。
2. 创建模版需要用name取模版名称
3.模板就可以直接使用传递过来的数据
 -->
 <template name="demo">
   <view>hello!!</view>
   <view>{{user[0].name}}-{{user[0].age}}</view>
 </template>
<!-- 调用模版需要使用is属性指定调用的模版 模板不调用不会显示内容 
3. 模版可以用过data属性传递数据
-->
 <template is="demo" data="{{user}}"/>
  1. 可以创建一个template文件夹专门放template文件
    template.wxml
<template name="tem1">
  <view class="tem">
    <view class="left">left</view>
    <view class="right">right</view>
  </view>
</template>

index.wxml

<!-- import标签引入 <import src=""/> -->
<import src="../../template/template"/>
<template is="tem1" data=""/>

<!-- index.wxss引入template的样式 -->
@import '../../template/template.wxss';

3. 模板传递数据

index.wxml

<!-- 引入模板 -->
<import src="../../template/template"/>
<!-- 模板传递数据 -->
<view wx:for="{{info}}" wx:key="index">
  <template is="tem1" data="{{...item}}"/>
</view>

template.wxml

<template name="tem1">
  <view class="tem">
  <!-- 模板可以直接拿到传递的数据 -->
    <view class="left">{{img}}</view>
    <view class="right">{{text}}</view>
  </view>
</template>

4. wxss 单位rpx

wxss 样式文件,私有样式,当前页面才生效。是微信小程序的样式语言,用于描述wxml样式。
wxss 支持大部分css样式,对css进行一些扩展
页面里面的wxss是局部样式,app.wxss文件是全局样式

微信小程序里面的样式推荐使用rpx为单位。不管屏幕尺寸大小,都把当前屏幕设置为750rpx。 如果设计稿不是750px(1px!=1rpx),需要计算出1px是多少rpx

如: 375px宽度的设计搞。
750rpx ?
375 1px 750/375=2rpx。

  1. @import 导入外部的wxss样式文件:@import "../home/home.wxss"
  2. 支持style内联样式,建议尽量不用内联样式,影响渲染速度 <view style="color:red;">hello style</view>

二、自定义组件 components

data 对象 一般存储私有数据
properties 对象 一般存储外部传递过来的数据

1. 自定义组件方法

需要定义在 methods 节点中

methods: {
    addNum(){
      this.setData({
        num:this.data.num + 10
      })
      this._showNum()
    },
    _showNum(){ // 自定义内部使用的方法 建议 _开头
      wx.showToast({ // 弹框
        title: 'num值为'+this.data.num,
        icon:"none"
      })
    },
}

2. 组件样式的使用

自定义组件的样式只对当前组件有效,不会影响其他组件以及小程序的页面样式。只有class样式有隔离效果,id、属性、标签选择器都没有隔离效果,但不建议使用!

自定义组件不能使用外部样式包括全局样式,需要把样式传入到自定义组件,并通过继承实现。
components.js

Component({
// 自定义组件不能使用外部样式包括全局样式,需要把样式传入到自定义组件,并通过继承实现
// 每一个样式当做一个prop属性,组件内部才能使用
  externalClasses:["bgwhite","padding20","borderb"],
  data: { },
})

需要把样式传到自定义组件上

<!-- 引入组件 -->
<!-- 把全局样式作为自定义组件传 -->
<textCom bgwhite="bg-white" padding20='padding-20' borderb='border-b'/>

3.父 --> 子 (通过properties属性 / 插槽)

传递数据

父:
index.wxml

<!-- 可以用{{}}给属性 绑定变量(动态属性)-->
<user title='user components!' peo="{{user}}" />

index.js

// 路由组件Page
Page({
  data: {
    user:{
      name:'zs',
      age:28,
    }
  },
})

子:(components组件)
user.js

// 自定义组件Component
Component({
  /* 组件的属性列表,相当于vue的props属性 */
  properties: { // 两种写法
    title:{
      type:String, //属性类型
      value:"title" // 默认值 -- 传递值会覆盖默认值
    },
    peo: Object, // 不需要默认值可以简化,直接写定义的类型
  },
})

user.wxml

<view>
  <view>姓名:{{title}}</view>
  <view>姓名:{{peo.name}}</view>
  <view>年龄:{{peo.age}}</view>  
</view>

插槽

父:
index.wxml

<view>
  <user peo="{{user}}">
    <view>这是一个其他页面</view>
  </user>
</view>

子:(components组件)
user.wxml

<!-- 插槽,可以显示组件包含的内容 -->
<slot></slot>

4.子 --> 父

1. 通过事件触发

步骤:

  • 一、
// 1. 在父组件中定义一个触发事件 --最后可用 
// 4. e.detail获取子组件传参过来的值
  parEvent(e){
    this.setData({
      count:e.detail.count
    })
  },
<!-- 2. 绑定 自定义的事件 -->
<son bind:sonEvent="parEvent" count="{{count}}" />
  • 二、
  methods: {
    addCount(){
      this.setData({
        count:this.data.count + 10
      })
// 3. 通过this.triggerEvent()触发自定义事件,并可以传参回去
      this.triggerEvent("sonEvent",{count:this.data.count})
    },
  }

父:
index.wxml

<!-- user组件自定义事件myEvent,通过子组件触发myEvent事件执行myEventHandle函数并且传递参数 -->
  <user bind:myEvent="myEventHandle" peo="{{user}}">
    <view>这是一个其他页面</view>
  </user>

index.js

Page({
  data: {
  },
  myEventHandle(e){
    // e是事件对象,e.detail就是子组件触发事件的第二个参数,detail对象
    console.log(e.detail); //{name: "zs", age: 19}
  }
})

子:(components组件)
user.wxml

<view bind:tap="emitMyevent">给父组件传值</view>

user.js

Component({
  /* 组件的属性列表,相当于vue的props属性 */
  properties: {
  },
  methods: {
    emitMyevent(){
      // 触发自定义事件,第一个参数是自定义事件名称,
      // 第二个参数是detail对象,也就是需要传递给事件触发函数的参数对象
      // 第三个参数是时间触发选项对象,可以配置事件的冒泡,捕获等(一般默认空)
      this.triggerEvent("myEvent",{name:'zs',age:19},{})
    }
  }
})

2. selectComponent 获取子组件的实例对象

调用this.selectComponent获取子组件的实例对象,可以直接访问子组件的任意数据和方法,调用时传入一个选择器

<!-- 2. 给子组件提供class/id选择器 -->
<son class="customA" id="cA" bind:sonEvent="parEvent" count="{{count}}" />
<!-- 1. 定义一个触发事件 -->
<button bind:tap="getChild">获取子组件的实例</button>
// 3. 
getChild(){
  const child = this.selectComponent(".customA")
  child.setData({ // 这里不能用this,this是当前页面的实例对象
    count:child.data.count + 9 // 调用子组件的数据
  })
  child.addCount() // 调用子组件的方法
},

5. 监听器 observers

监听器 使用键值对的形式 键是监听字段对象上的某个属性,值是处理函数
注意:不支持箭头函数,会改变this指向问题

  // 监听器 使用键值对的形式 键是监听字段,值是处理函数
  observers:{ // 监听多个字段用 , 隔开
    'n1,n2':function(newN1,newN2){
      this.setData({
        sum:newN1 + newN2
      })
    }
  },
  
  methods: {
    change1(){
      this.setData({
        n1:this.data.n1 + Math.floor(Math.random()*10)
      })
    },
    change2(){
      this.setData({
        n2:this.data.n2 + Math.floor(Math.random()*10)
      })
    },
  }

6. 触发自定义事件 triggerEvent

第一个参数是自定义事件名称,
第二个参数是detail对象,也就是需要传递给事件触发函数的参数对象
第三个参数是时间触发选项对象,可以配置事件的冒泡,捕获等(一般默认空)

this.triggerEvent("myEvent",{name:'zs',age:19},{})

三、绑定事件与冒泡

1. bind 和 catch 点击事件

<view bindtap="fatherTap">
  <!-- bind:xxx 绑定的事件会有冒泡 -->
  <view bind:tap="childTap">点击冒泡事件</view>
  <!-- catch:xxx 绑定的事件不会冒泡 -->
  <view catch:tap="childTap">点击非冒泡事件</view>
</view>

2. 小程序的函数传参

微信的事件不能加()传递参数, 小程序给函数传递参数只能通过自定义数据方式传递。通过事件对象上去拿你传递的参数。

  • 事件传参:data-参数名 = '参数值'
    如果定义的参数名结构:data-user-name='zs'userName(小驼峰)
    data-userName='zs'username(全小写)
  • 拿参数值:e.target.dataset.参数名

user.wxml

<!-- 微信的事件不能加()传递参数, 传递参数需要使用自定义数据的方式传递 -->
<view bind:tap="addCount" data-num="2">点击+</view>

user.js

Component({
/*组件的属性列表*/
  properties: {
  },
/*组件的初始数据*/
  data: {
    count:1,
  },
/*组件的方法列表 */
  methods: {
    addCount(e){
      // e是获取元素组件对象,e.target获取组件的自定义数据
      // console.log(e);
      const num = Number(e.target.dataset.num)
      this.setData({
        count:this.data.count+num
      })
    }
  }
})

组件对象

3. setDate方法

setDate函数用于将数据从逻辑层发送到视图层,同时改变对应的this.data的值。
注意:直接修改this.data而不调用this.setData是无法改变页面状态的,还会造成数据不一致。

<button bind:tap="changeShow">显示/隐藏</button>
<view class="box" wx:if="{{show}}"></view>
Page({
  data: {
     show:true,
  },
  changeShow(){
    this.setData({
      show:!this.data.show
    })
  },
})

4. bindtap / bindinpunt

  1. bindtap 点击事件的处理函数
    传参需要data-*=" ",事件对象拿参数e.target.dataset.x
<button bindtap="changeCount" data-x="{{2}}"></button>
<input bindinput="change"/>
changeCount(e){
      console.log(e.target.dataset.x);
    },
  1. bindinpunt input文本框的事件处理函数
    事件对象中拿文本框的输入值 e.detail.value
<!-- 文本框和data之间的数据同步 -->
<input value="{{msg}}" bindinput="changeMsg"/>
data: {
    msg:'Hello,'
},
changeMsg(e){ // 同步到msg
	// console.log(e.detail.value);
	 this.setData({
	   msg:e.detail.value
	 })
},

四、behavior

behavior.js

// 遵循common.js 的规范
// 可以理解成vue的混入mixin,主要放一些公共属性
module.exports = Behavior({
  data:{
    sex:"man"
  },
  methods:{
    changeSex(){
      this.setData({
        sex:"woman"
      })
    }
  },
})

哪个组件使用直接引入
user.js

// 引入文件
const behavior = require('../../com/behavior')
Component({
  // 用behaviors属性引入,[]可以有多个混入文件
  behaviors:[behavior],
})

user.wxml

<!-- 可使用behavior的属性 -->
<view>{{sex}}</view>
<view bindtap="changeSex">改变sex</view>

五、小程序的字体图标(不支持css)

小程序不支持css文件,不能直接使用阿里巴巴字体图标库文件,需要自定义字体方式创建字体图标

app.wxss

/* 把icon图标放在公共样式组件内 */
/* 可以直接在线生成链接 复制源码 */
@font-face {
  font-family: "iconfont"; /* Project id 4267261 */
  src: url('//at.alicdn.com/t/c/font_4267261_4nl2h5taidh.woff2?t=1701342946186') format('woff2'),
        url('//at.alicdn.com/t/c/font_4267261_4nl2h5taidh.woff?t=1701342946186') format('woff'),
        url('//at.alicdn.com/t/c/font_4267261_4nl2h5taidh.ttf?t=1701342946186') format('truetype');
}
.iconfont {
  font-family: "iconfont" !important;
  font-size: 16px;
  font-style: normal;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}
.icon-shouye:before {
  content: "\e600";
}

.icon-liulan:before {
  content: "\e647";
}
<!-- 使用icon字体图标 -->
<text class="iconfont icon-liulan"></text>
<text class="iconfont icon-shouye"></text>

六、小程序方法

1. getCurrentPages() 获取页面栈

getCurrentPages() 获取微信小程序页面数组。[page1,page2,page3] 最后一个数组元素是当前页面,倒数第二个是上一个页面…需要倒着取。

const pages = getCurrentPages()
//console.log(pages);
const prePage = pages[pages.length-2] // 获取当前页面的上一个页面(倒数第二个页面)

// navigateBack 关闭当前页面,返回上一页面
wx.navigateBack()

2. 声明式导航 navigator

<!-- 跳转到tabbar页面 open-type要写! -->
<navigator url="/pages/index/index" open-type="switchTab">跳转到tabbar页面</navigator>
<!-- 跳转到非tabbar页面 open-type属性可以省略 -->
<navigator url="/pages/home/home">跳转到非tabbar页面</navigator>
<!-- 后退 delta后退几页(后退1页delta可省) -->
<navigator open-type="navigateBack" delta="2">返回</navigator>

3. 编程式导航

// 1.跳转tabbar页面
wx.switchTab({
  url: '/pages/index/index',
})

// 2.跳转非tabbar页面
wx.navigateTo({
  url: '/pages/home/home',
})

// 3.navigateBack 关闭当前页面,返回上一页面或多级页面
wx.navigateBack({
  delta: 2 //返回前几页面 
})
wx.navigateBack() // 返回 1页

4. 导航传参

<!-- 导航传参 ?name=zn&age=19 -->
<navigator url="/pages/home/home?name=zn&age=19">导航传参</navigator>

可以在跳转的页面onLoad()钩子拿到传递过来的参数

/* 生命周期函数--监听页面加载 */
  onLoad(options) {
    console.log(options); //{name: "zn", age: "19"}
  },

5. 下拉刷新 onPullDownRefresh

一般是用于重置页面样式

  /* 页面相关事件处理函数--监听用户下拉动作 */
  onPullDownRefresh() {
    this.setData({
      count:0 // count重置为0
    })
    // 方法重置完后,调用自动关闭下拉刷新方法
    wx.stopPullDownRefresh()
  },

6. 上拉加载 onReachBottom

一般用于请求多条数据时 (注意:请求数据需要使用节流阀,避免多次请求数据)
默认在距离底部50px时触发,可以在全局或者局部 json去配置距离:"onReachBottomDistance": 150

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

节流阀的使用

Page({
  data: {
    msg:[], // 请求的数据
    // 1.定义节流阀 false可以发送网络请求,true是阻止
    isLoading:false
  },
  getMsg(){
    this.setData({isLoading:true}) // 2.正在发送网络请求,阻止再发送
    // 展示Loading效果
    wx.showLoading({
      title: '数据加载中...',
    })
    // 请求后台数据
    wx.request({
      url: 'url',
      method:'GET',
      success:(res)=>{
        this.setData({msg:[...this.data.msg,...res.data]})
      },
      complete:()=>{ 
        wx.hideLoading() // 数据请求成功or失败都需要关闭Loading效果
        this.setData({isLoading:false}) // 3.数据请求完并可以继续数据请求
      } 
    })
  },

/* 页面上拉触底事件的处理函数 */
  onReachBottom() {
    if(this.data.isLoading) return // 4.判断:true表示还在数据请求中,阻止请求
    this.msg() // 否则可以请求
  },
})
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值