微信小程序开发

微信小程序

微信小程序开发app安装、使用

微信开发者工具 app下载

https://developers.weixin.qq.com/miniprogram/dev/devtools/download.html

注册、登录

https://mp.weixin.qq.com/

小程序开发主页

https://mp.weixin.qq.com/wxamp/index/index?lang=zh_CN

1、项目基础

1.1项目目录

在这里插入图片描述

1.2启动

  1. 项目—>新建项目—>目录(选择项目文件)—>AppID–>小程序—>不使用云服务、不使用模版。
  2. 详情—>本地设置—>调试基础库(选择版本)—>勾选:不校验合法域名、web-view(业务域名)、TLS版本以及HTTPS证书。
  3. 确认开发权限(把微信号发给管理者,添加项目的开发权限)
  4. 微信扫码快捷登录
  5. 工具—>构建npm—>构建成功
    6.普通编译 —>添加编译模式。
    在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

2、tabBar配置

在 app.json 中,windows 同级的位置,写入:

{
  "windows": {
    ...
  },
  "tabBar": {
    "color": "#909192",
    "selectedColor": "#0600B8",
    "list": [{
      "pagePath": "pages/home/home",
      "text": "首页",
      "iconPath": "images/bar/bar1_1.png",
      "selectedIconPath": "images/bar/bar1.png"
    },{
      "pagePath": "pages/menu/menu",
      "text": "菜单",
      "iconPath": "images/bar/bar2_2.png",
      "selectedIconPath": "images/bar/bar2.png"
    },{
      "pagePath": "pages/new/new",
      "text": "新品",
      "iconPath": "images/bar/bar3_3.png",
      "selectedIconPath": "images/bar/bar3.png"
    },{
      "pagePath": "pages/kefu/kefu",
      "text": "小二",
      "iconPath": "images/bar/bar4_4.png",
      "selectedIconPath": "images/bar/bar4.png"
    }]
  }
}

#pagePath  页面路径
#text      tabBar文字信息
#iconPath  tabBar图片路径
#selectedIconPath   tabBar选中的图片路径

在pages的同级目录下新建images文件,在里面新建bar文件放图片

在这里插入图片描述

3、配置页面

在app.json:

{
	"pages": [
		"pages/home/home"
    ],
    ...
}

在这里插入图片描述

4、页面文件介绍

pages 目录下,每个页面就是一个文件夹,一个页面包含wxml、wxss、js和json文件,其中:

wxml:相当于html文件
wxss:相当于css文件
#1、标签
标签分单双标签,书写格式与html完全一样,但在微信小程序里,没有div、span、p、h1-h6这些标签,它只有非常简单的两个最基本的标签:view(即:div) 与 text(即:span)。当然,还有其他经过封装的组件,我们后面会再做介绍。

#2、JavaScript
微信小程序与vue.js框架用法大致相同,同属MVVM框架,都是由数据驱动视图更新。因此,js事件和变量的书写,也会与原生JS稍有差异。

5、数据绑定

在 home.wxml 页面写入:

<view>{{msg}}</view>

在 home.js 写入:

Page({
  data: {
    msg: '你好,世界'
  }
})

如此,便完成了数据绑定。

可以看到,动态变化的数据,我们统一放在data里面。这里跟vue做个区别,vue中规定组件内data必须是函数,而小程序不用,使用一个对象表示即可。

小程序中,我们要记住,凡是调用data中的数据,在wxml文件使用时,就需要加 {{}},这语法便是著名的:mustache语法,也称胡子语法。

6、双向数据绑定

#1、修改data中的数据
小程序中,使用 this.setData() 来修改data中的数据。

#2、方法绑定
一个标签需要调用一个函数(或称:方法),需要在标签上绑定事件,如绑定触摸事件(即:pc上的点击事件):

<button bindtap="tapFn">按钮</button>

然后在js中:

Page({
  data: {
    ...
  },
  tapFn(){
    // do something...
  }
})

#3、实现双向数据绑定
我们来实现双向数据绑定:

在 home.wxml 中:

<input value="{{msg}}" bindinput="iptFn"></input>
<view>{{msg}}</view>

在js中:

Page({
  data: {
    msg: '你好,世界'
  },
  // input值被修改时触发的函数
  iptFn(e){
    this.setData({
      msg: e.detail.value
    })
  }
  //修改数据是同步的,但视图更新是异步的
})

#4、事件传值bindtap、data-xxx

<view  data-thisIndex="{{index}}" bindtap="bindViewTap">
  删除
</view>

bindViewTap(e) {
  let _index = e.currentTarget.dataset.thisIndex;
  console.log(_index );   
 }

7、 列表循环的基础用法

<view>
<view wx:for="{{list}}" wx:key="index">{{item}}</view>
</view>

wx:key可以不写,但会报警告

wx:key 的值有三种写法

1、wx:key=“property” ,其中property是代表在 for 循环的 array 中 item 的某个 property,该 property 的值需要是列表中唯一的字符串或数字,且不能动态改变。类似于字典的key值

2、wx:key=“*this”, 保留关键字 *this 代表在 for 循环中的 item 本身,这种表示需要 item 本身是一个唯一的字符串或者数字

3、wx:key=“index”,代表每一项的索引

比较推荐*this

自定义列表渲染:
当有多个循环时,可以写wx:for-index=“ind”,wx:for-item=“items”,来区分每一个循环。

<view>
<view wx:for="{{list}}" wx:key="*this" wx:for-item="items" wx:for-index="ind">{{ind}} {{items}}
</view>
</view>

ind/items都是自定义名称,其中的ind为索引,items为数组每一项。

8、显示与隐藏

if 和 hidden

wx:if 有更高的切换消耗,hidden有更高的初始渲染消耗
例1

<text wx:if="{{isShare==false}}" bindtap="bindAccount" >点我分享</text>
<text wx:if="{{isShare==true}}" >分享成功</text>

例2

<text wx:if="{{isShareStatus==0}}" bindtap="bindAccount" >点我分享</text>
<text wx:elif="{{isShareStatus==1}}" >分享成功</text>
<text wx:else>分享失败</text>

例3

<view hidden="{{isShow}}">显示与隐藏</view>

hidden与if相反,isShow的值为false的时候上面的view才会显示

  data: {
    isShow:false
  }

9、事件汇总

bindtap 点击事件(冒泡的)
catchtap 点击事件(非冒泡的)

bindinput 键盘输入事件
bindconfirm 回车事件
bindfocus 输入框聚焦事件
bindblur 输入框失焦事件
bindchange 值改变事件

触摸事件
bindtouchstart 动作开始
bindtouchend 动作结束
bindtouchmove 触摸移动
bindtouchcancel 触摸动作被打断

表单重置事件

<form  bindreset="formReset" >
<button type="warn" form-type="reset">重置</button>
</form>

表单提交事件

<form  bindsubmit="formSubmit"" >
<button type="primary" form-type="submit"">提交</button>
</form>

10、使用模板

类似于vue的插槽
在pages > home 下新建文件夹 templates ,然后在里面新建test.wxml :

<!--  模板1 -->
<template name="box1">
<view bindtap="btnFn">box1 :{{content}}</view>
</template>
<!--  模板2 -->
<template name="box2">
<view bindtap="btnFn">box2 :{{content}}</view>
</template>
<!--  模板3 -->
<template name="box3">
<view bindtap="btnFn">box3 :{{content}}</view>
</template>

在 home.wxml中:

<import src="./templates/test"  />
<template is="box3" data="{{content: txt}}"></template>

这里通过import标签引入模板,template标签使用模板,is属性指定对应的模板,data属性传值

在 home.js中:

Page({
  data: {
    txt: 999
  },
  btnFn() {
    console.log('打印');
  }
})

以上在需要使用模板的 home.js 里面定义了内容txt 和方法btnFn

11、WXS 模块

WXS 代码可以编写在 wxml 文件中的 标签内,或以 .wxs 为后缀名的文件内。

模块
每一个 .wxs 文件和 标签都是一个单独的模块。

每个模块都有自己独立的作用域。即在一个模块里面定义的变量与函数,默认为私有的,对其他模块不可见。

一个模块要想对外暴露其内部的私有变量与函数,只能通过 module.exports 实现。

wxs写法1:
在 pages > home 文件夹下新建 tools.wxs 文件,并定义方法fn,通过module.exports 导出

function fn (a,b){
  return a+b
}
module.exports ={
  fn:fn
}

home.wxml 中 通过src属性引入模块,module属性定义当前模块名称

<wxs src="./tools.wxs" module="foo"></wxs>
<view>{{foo.fn(1,4)}}</view>

写法二:
在home.wxml 中:

<wxs module="koo">
function add (val){
  var a = val + 1
  return a
}
module.exports={
  add:add
}
</wxs>

<view >{{koo.add(0)}}</view>

12、组件化开发

  1. 在app.json 中创建组件

和创建页面一样,只是把pages改成components
新增 “components/product/product”

{
    "pages": [
        "pages/home/home",
        "components/product/product"
    ],
    .....
 }
  1. 组件中写入结构样式,并声明

在product.wxml中:
写好页面结构

<view class="product_list">
  <view wx:for="{{showArr}}" wx:key="*this" class="product_list_box">
    <image class="img"  src="{{item.imgSrc}}"></image>
    <view class="txt">{{item.imgTxt}}</view>
  </view>
</view>

在product.js中:
写好数据,图片我放在images文件下的home文件

// 注意注意:这里的Page()方法改成了Component()方法
Component({
  data: {
    showArr: [{
        imgTxt: "卡布奇诺",
        imgSrc:"../../images/home/logo1.jpg"
      },
      {
        imgTxt: "白咖啡",
        imgSrc:"../../images/home/logo2.jpeg"
      },   
      {
        imgTxt: "拿铁咖啡",
        imgSrc:"../../images/home/logo3.jpeg"
      }  
    ]
  },
})

在product.wxss中:
写好样式


.product_list{
  display: flex;
  padding: 20rpx 2%;
  justify-content: space-between;
  flex-wrap: wrap;
}

.product_list_box{
  width: 49%;
  box-shadow: 0 0 6rpx #ccc;
  border-radius: 10rpx;
  overflow: hidden;
  margin-bottom: 20rpx;
}

.product_list_box .img{
  width: 100%;
  display: block;
  height: 280rpx;
}

.product_list_box .txt{
  height: 50rpx;
  line-height: 50rpx;
  text-align: center;
  background-color: #eee;
}

在product.json中:
声明组件 “component”: true

{
  "usingComponents": {},
  "component": true
}
  1. 调用组件

在home.json 中:
注册组件

{
  "usingComponents": {
    "product-block": "/components/product/product"
  }
}

在home.wxml 中 :
引入组件

<product-block />
或:
<product-block></product-block>

13、组件传值

考虑到组件需要复用,那么数据应该在父组件传过来。

父传子
我们将该组件的数据迁移到父组件 Home.js 中,然后通过父传子传过来:
父组件
在home.wxml :

<product-block  showArr="{{showArr}}" ></product-block>

在home.js :

Page({
  data: {
    showArr: [{
        imgTxt: "卡布奇诺",
        imgSrc: "../../images/home/logo1.jpg"
      },
      {
        imgTxt: "白咖啡",
        imgSrc: "../../images/home/logo2.jpeg"
      },
      {
        imgTxt: "拿铁咖啡",
        imgSrc: "../../images/home/logo3.jpeg"
      }

    ]
  }
  })

子组件

在product.js :

Component({
//通过properties接收父组件传过来的值,类似于vue的props
  properties:{
    showArr:{
      //定义数据类型
      type:Array,
      //定义数据的初始值
      value:[]
    }
  }
})

子传父
我们可以通过子组件的自定义事件this.triggerEvent ,点击product 组件中的任意一项,来触发父组件的事件。
子组件
在product.wxml :

<view class="product_list">
  <view wx:for="{{showArr}}" wx:key="*this" class="product_list_box" bindtap="productFn">
    <image class="img"  src="{{item.imgSrc}}"></image>
    <view class="ve">{{item.imgTxt}}</view>
  </view>
</view>

在product.js :

Component({
//组件中写方法需要写上methods
   methods:{
     productFn(){
     //子传父通过triggerEvent, 类似vue的$emit
       this.triggerEvent('eventFn','触发了事件')
     }
    }
  })

父组件
在home.wxml :

<!-- 标签上使用bind来接收子组件传过来的事件 -->
<product-block  showArr="{{showArr}}" bind:eventFn="homeEvent"></product-block>

在home.js :

Page({
  ...,
  // 页面无需写methods
  homeEvent(val) {
    console.log(val.detail);
  }
})

点击之后,控制台打印了 :触发了事件。

14、全局变量globalData

定义全局变量globalData,在app.js中:

// app.js
App({
  globalData: {
    name: '张三'
  }
})

调用的方法有:

【方法一(推荐)】通过调用app获取,需要在第一行声明app的实例

const app = getApp()
Page({
  onLoad: function () {
    console.log(app.globalData.name);
  },
})

【方法二】直接通过getApp().globalData获取,不需要写const app = getApp()实例

Page({
  onLoad: function () {
      console.log(getApp().globalData.name);
  },
})

修改global的方法【借助方法一】:

app.globalData.name = "李四";

15、路由跳转

1、跳转到非tabBar 的页面(js)

wx.navigateTo({
    url: '/pages/nav/nav'
})

// url携带参数的形式:
wx.navigateTo({
    url: '/pages/nav/nav?pid=123',
})

// 如何获取参数?
onLoad: function (options) {
    console.log(options.pid)		// 123
},
    
// 携带复杂参数的形式
 wx.navigateTo({
      url: '/pages/nav/nav?pid=123',
      //跳转成功,通过eventChannel向被打开页面传送数据
      success:function(res){
          res.eventChannel.emit('pageInfo',{name:'用户'})
      }
    })

// 接收复杂参数的形式
onLoad: function (options) {
    console.log(options.pid); //123
    const channel = this.getOpenerEventChannel() 
    //使用getOpenerEventChannel()方法,通过.on方法获取
    channel.on('pageInfo',function(data){
      console.log(data); //{name: "用户"}
    })
},
    
// 当前页反向发射数据到上一页
onLoad: function (options) {
     const channel = this.getOpenerEventChannel() 
     //使用getOpenerEventChannel()方法,通过.emit方法触发
     channel.emit('fanxiang',{arr:[11,22,33]})
},
    
// 上一页接收反向发射的数据
wx.navigateTo({
  url: '/pages/nav/nav?pid=123',
      // events中写反向发射的函数
  events:{
        fanxiang(res){
          console.log(res.arr); //[11,22,33]
        }
      }
})

2、跳转到非tabbar页面(wxml)

<navigator url="/pages/logs/logs"></navigator>

3、跳转到tabbar页面(js)

wx.switchTab({
    url: '/pages/user/user'
})

16、小程序生命周期

页面生命周期
onLoad > onShow > onReady >onHide > onShow > onUnload
组件生命周期

Component({
  lifetimes: {
    created	: function() {
      // 在组件实例刚刚被创建时执行	1.6.3版本以上
    },
    attached: function() {
      // 在组件实例进入页面节点树时执行  1.6.3版本以上
    },
    detached: function() {
      // 在组件实例被从页面节点树移除时执行  1.6.3版本以上
    },
    ready: function() {
      // 在组件在视图层布局完成后执行	1.6.3版本以上
    },
    moved: function() {
      // 在在组件实例被移动到节点树另一个位置时执行	 1.6.3版本以上
    }
   
    
  },
   // 以下是旧式的定义方式,可以保持对 <2.2.3 版本基础库的兼容
  attached: function() {
    // 在组件实例进入页面节点树时执行
  },
  detached: function() {
    // 在组件实例被从页面节点树移除时执行
  },
  // ...
})

组件所在页面的生命周期:

Component({
  pageLifetimes: {
    show: function() {
      // 页面被展示  2.2.3版本以上
    },
    hide: function() {
      // 页面被隐藏  2.2.3版本以上
    },
    resize: function(size) {
      // 页面尺寸变化  2.4.0版本以上
    }
  }
})

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值