当前位置: 首页 > news >正文

【第二周】基础语法学习

0.png


目录

  • 前言
  • 初始化项目
  • 文件介绍
  • 基本介绍
    • JS
    • WXML
    • WXSS
  • 常见组件
    • 基础组件
    • 视图容器
      • match-media
      • movable-area/view
      • page-container
      • scroll-view
      • swiper
    • 表单组件
    • 自定义组件
  • 模板语法
    • 数据绑定
      • 单向数据绑定
      • 双向数据绑定
    • 列表渲染
    • 条件渲染
    • 模板引用
  • 事件系统
    • 事件类型
    • 事件绑定
    • 阻止冒泡
    • 互斥事件
    • 事件参数
  • 页面切换
  • 生命周期
  • 数据通信
    • 全局通信
      • localStorage(本地存储)
      • globData(小程序全局存储)
    • 父 => 子
    • 父 => 父
    • 子 => 父
      • triggerEvent
      • selectComponent
    • 子 => 子
  • 网络请求
  • 第三方组件
    • Vant/weapp 1.11
    • Tailwind
  • 拓展功能
  • 提问改善


前言

8.png
当前教程的示例代码已经在 Github 开源,大家开源下载简易的示例对照学习,https://github.com/bosombaby/wechat_tutorial

在进行一个完整的小程序项目开始时,建议阅读一遍小程序开发的设计指南。
微信小程序设计指南 | 微信开放文档

微信小程序的编码规范链接如下:
https://juejin.cn/post/7047299287264264206

初始化项目

1.png
简单介绍一下初始化项目文件、文件夹的用法和配置

  1. 打开微信开发者工具,通过目录打开本地文件的空文件夹(项目名称识别为目录名称)
  2. AppID 获取流程参考第一周的学习内容
  3. 后端服务学习阶段选择不使用云服务
  4. 模板选择我们工作中使用的 JS 基础模板

文件介绍

1.png
2.png3.png

5.png

  1. 微信开发者工具的使用教程可跳转到第一章查看
  2. 初始化不同文件的含义对比图参见上图
  3. 鼠标右键可以添加页面和组件,同时需要确保在 app.json 配置中被顺利引入

基本介绍

JS

和 js的用法一致,注意的是响应式机制和 vue 前端框架有所不同。

1.在这里定义数据
data: {msg:'Hello WeChat'
}2.获取数据
this.data.msg3.更新数据
this.setData({msg:'更新数据'
})

WXML

https://developers.weixin.qq.com/miniprogram/dev/framework/view/wxml/
和原生的 html 标签的逻辑一致,但是有部分标签不可用,小程序也内置了相关的标签组件。

HTML通用标签:<div>, <span>, <a>, <img>, <p>, <h1><h6>, <strong>, <em>, <ul>, <ol>, <li> 
WXML专用标签:<view>, <text>, <image>, <button>, <navigator>, <swiper>, <scroll-view>, <picker>, <form> 

WXSS

https://developers.weixin.qq.com/miniprogram/dev/framework/view/wxss.html
rpx是微信小程序中css的尺寸单位,可以根据屏幕宽度进行自适配。
规定屏幕宽度为750px,譬如iphone6,屏幕宽度为375px,共有750个物理像素,则1rpx = 0.5px,后续可以扩展讲解一下 em rem px rpx 逻辑像素 物理像素 等原理,目前只需要了解在标准开发下 1rpx = 0.5px 就行。
其余样式的用法和原生 css 差不多,只是只有一个标签名和类名定义变量

常见组件

基础组件

最常用的就是 view text,相当于html 的 div span 标签

视图容器

match-media

1.png
https://developers.weixin.qq.com/miniprogram/dev/component/match-media.html
相当于前端的媒体查询,页面宽高在一定的范围内才会触发,注意这里是 px 不是 rpx

示例代码如下:

<match-media min-width="300" max-width="600"><view>当页面宽度在 300 ~ 500 px 之间时展示这里</view>
</match-media>
<match-media min-width="1200"><view>当页面宽度在 300 ~ 500 px 之间时展示这里</view>
</match-media>

movable-area/view

https://developers.weixin.qq.com/miniprogram/dev/component/movable-area.html
2.png

QQ截图20240621141606.png
可以移动拖拽的区域或者视图组件,通常用在验证码、需要交互拖拽的场景中,比如购物车的左滑移动删除
示例代码:

<movable-area class="movable-area"><movable-view x="{{x}}" y="{{y}}" direction="all" class="movable-view" bindtap="handleAreaMove"></movable-view>
</movable-area>this.setData({x: 30,y: 30,
});

page-container

主要是底部弹出的对话框,效果类似于 popup 弹出层。
https://developers.weixin.qq.com/miniprogram/dev/component/page-container.html
3.png

  1. tip: 当前页面最多只有 1 个容器,若已存在容器的情况下,无法增加新的容器
  2. tip: wx.navigateBack 无法在页面栈顶调用,此时没有上一级页面

示例代码:

<page-container show="{{isShowPage}}" position="bottom" bind:afterleave="afterLeave"><view class="poup-content">这里是弹窗内容,哈哈哈哈哈</view>
</page-container>

scroll-view

可以滚动的视图区域
https://developers.weixin.qq.com/miniprogram/dev/component/scroll-view.html
5.png
示例代码:

<scroll-view scroll-y="true" class="scroll-view-list" scroll-into-view="{{scrollToView}}" scroll-top="{{scrollTop}}" scroll-with-animation="true"><view id="demo1" class="scroll-view-item" style="background-color: cadetblue;">1</view><view id="demo2" class="scroll-view-item" style="background-color:chartreuse;">2</view><view id="demo3" class="scroll-view-item" style="background-color:crimson;">3</view>
</scroll-view><view class="flex-bc"><button type="primary" bindtap="scrollToTop">顶部</button><button type="primary" bindtap="scrollToTarget">特定元素</button>
</view>

swiper

小程序相关的轮播图教程,可以使用微信小程序官方提供的** api(推荐)**或者其他的第三方组件库
6.png

<swiper class="scroll-view-list" indicator-dots="true" autoplay="true" interval="500" circular="true"><swiper-item id="demo1" class="scroll-view-item" style="background-color: cadetblue;">1</swiper-item><swiper-item id="demo2" class="scroll-view-item" style="background-color:chartreuse;">2</swiper-item><swiper-item id="demo3" class="scroll-view-item" style="background-color:crimson;">3</swiper-item>
</swiper>

表单组件

0.png
https://developers.weixin.qq.com/miniprogram/dev/component/button.html
和原生的 html 标签差不多,用到的话可以去查

自定义组件

https://developers.weixin.qq.com/miniprogram/dev/framework/custom-component/
https://developers.weixin.qq.com/miniprogram/dev/framework/custom-component/wxml-wxss.html

  • 自定义组件的流程:定义 => 注册 => 引入
  • 比普通的 Page 的生命周期不同,多了一个 properties 传参

Slot | 微信开放文档
插槽 slot 用法如下:

1. 单个插槽
<my-component parentName="常见组件学习"><view style="color:cornflowerblue">我是单个插槽</view>
</my-component>2. 多个插槽
<view slot="before">组件slot name="before"</view>
<view slot="after">组件slot name="after"</view>

模板语法

WXML是框架设计的一套标签语言,结合常见组件、事件系统 可以构建出页面的结构。

数据绑定

单向数据绑定

概述:data=>页面
3.png

<view>{{message}}</view>data: {message: "你好,数据绑定",
}

和 VUE 的插值表达式一致,允许你将JavaScript表达式的值嵌入到模板字符串中,并且小程序会自动更新DOM以反映该表达式值的变化。

双向数据绑定

概述:data<=>页面
6.png
简易双向绑定 | 微信开放文档

<input model:value="{{num}}" class="input-num" />
<view>{{num}}</view>

在 WXML 中,普通的属性的绑定是单向的,一般都监听数值的变化然后通过方法操作。但是目前微信小程序双向绑定只支持单一字段、不支持对象,可以在组件中自定义双向绑定。

列表渲染

5.png

<text class="second-level-title">2.列表渲染</text>
<view wx:for="{{arrayList}}" wx:key="id" wx:for-index="idx" wx:for-item="myItem">{{idx}} -- {{myItem.content}}
</view>arrayList: [{ id: "1-1", content: "测试数据1" },{ id: "1-2", content: "测试数据2" },{ id: "1-3", content: "测试数据3" },{ id: "1-4", content: "测试数据4" },{ id: "1-5", content: "测试数据5" },
]

https://blog.csdn.net/qq_53673551/article/details/127167029
WXML 的列表渲染语法需要提供为唯一值 key ,它是虚拟 DOM 比较的标识

条件渲染

7.png
在框架中,使用 wx:if=“” 来判断是否需要渲染该代码块,如果要一次性判断多个组件标签,可以使用 仅仅是一个包装元素,不会在页面中做任何渲染,只接受控制属性。

<text class="second-level-title">3.条件渲染</text>
<input model:value="{{score}}" class="input-num" />
<view wx:if="{{score >= 90}}"> 优秀 </view>
<view wx:elif="{{ score >= 70}}"> 良好 </view>
<view wx:elif="{{ score >= 60}}"> 及格 </view>
<view wx:else> 不及格 </view>

wx:if 和 hidden 的区别就是 v-if 和 v-show 的区别
7.png

模板引用

模板 template 相当于简易的自定义组件,感觉有点像 VUE 里面的插槽(slot),示例如下:
8.png

<text class="second-level-title">4.模板引用</text>
<template name="odd"><view>{{item}} is 奇数 </view>
</template>
<template name="even"><view>{{item}} is 偶数 </view>
</template><block wx:for="{{[1, 2, 3, 4, 5]}}"><template is="{{item % 2 == 0 ? 'even' : 'odd'}}" data="{{item}}" />
</block>

跨文件使用的导入方式如下:

  1. 单个导入 template ,一层关系依赖,不可用递归引入
<template name="header"><text style="color: red;"> 头部区域模板 {{score}}</text>
</template><import src="./header.wxml" />
<template is="header" data="{{score}}" />
  1. 导入除了 外的整个代码,相当于拷贝,后续可以专注于 wxml 组件的拆分(局部组件)
<include src="./header.wxml" />
<div>这里是内容区域</div>
<include src="./footer.wxml" />

事件系统

事件类型

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

类型触发条件版本
touchstart手指触摸动作开始
touchmove手指触摸后移动
touchcancel手指触摸动作被打断,如来电提醒,弹窗
touchend手指触摸动作结束
tap手指触摸后马上离开
longpress手指触摸后,超过350ms再离开,如果指定了事件回调函数并触发了这个事件,tap事件将不被触发1.5.0
longtap手指触摸后,超过350ms再离开(推荐使用longpress事件代替)
transitionend会在 WXSS transition 或 wx.createAnimation 动画结束后触发
animationstart会在一个 WXSS animation 动画开始时触发
animationiteration会在一个 WXSS animation 一次迭代结束时触发
animationend会在一个 WXSS animation 动画完成时触发
touchforcechange在支持 3D Touch 的 iPhone 设备,重按时会触发1.9.90

注:除上表之外的其他组件自定义事件如无特殊声明都是非冒泡事件,如 form 的submit事件,input** 的input事件,scroll-view 的scroll事件,(详见各个**组件)

事件绑定

10.png

1. bind:[事件名称]="[事件绑定函数名称]"
2. 事件绑定函数名称 是一个字符串,指向在 .ts/.js 文件的 Page 函数中定义的处理函数名。
<button bind:tap="openDialog">点击弹窗</button>

阻止冒泡

8.png

除 bind 外,也可以用 catch 来绑定事件。与 bind 不同, catch 会阻止事件向上冒泡。
<view id="outer" bind:tap="handleTap1">outer view<view id="middle" catch:tap="handleTap2">middle view<view id="inner" catch:tap="handleTap3">inner view</view></view>
</view>

互斥事件

除了 bind 和 catch 外,还可以使用 mut-bind 来绑定互斥事件
所有 mut-bind 绑定都是互斥的,只会触发其中一个绑定函数
不会影响bind 和 catch 绑定的事件

事件参数

和 VUE 直接向方法函数传参不同外,他的事件系统需要自定义属性去获取,示例如下:
11.png
target 触发事件的源组件,currentTarget 事件绑定的当前组件,比如冒泡事件举例:

<view id="outer" data-name="outer" data-msg="hello" bind:tap="handleTap4">outer view<view id="middle">middle view<view id="inner">inner view</view></view>
</view>handleTap4(event) {const name = event.currentTarget.dataset.name;const msg = event.currentTarget.dataset.msg;console.log("outer", event);console.log(name, msg);
}

页面切换

https://juejin.cn/post/7079045451948916744
https://blog.csdn.net/weixin_47124112/article/details/126466315
https://bosombaby.blog.csdn.net/article/details/122012979
10.png

  • 获取当前小程序应用的页面栈使用 getCurrentPages ,后续页面栈(后进先出,也就是数组)过多可以通过这个条件进行清除。
  • 使用 navigateTo 跳转,页面最上方会出现返回上一级的按钮,可以便捷调用 navigateBack

38.png
在微信小程序中的实践结果如下图所示:

  • 动态记录和管理用户在小程序中页面访问顺序和跳转关系的栈结构,支持导航、参数传递、生命周期管理,并具有容量限制。
  • 入栈即使路由路径相同也会添加,本质是由微信小程序定义的 **wxExparserNodeId**唯一
  • wx.navigateTo**(添加新的页面栈,新加入的页面从头渲染,之前的页面 onHide 隐藏,为了使用 navigateBack 走缓存 onShow )**
  • wx.redirectTo(原理和 navigateTo一致,但是这样就没法走 navigateBack 缓存返回)

生命周期

https://juejin.cn/post/7151402790823133215
https://developers.weixin.qq.com/miniprogram/dev/framework/app-service/page-life-cycle.html
跟vue、react框架一样,微信小程序框架也存在生命周期,实质也是一堆会在特定时期执行的函数
小程序中,生命周期主要分成了三部分:

  • 应用的生命周期
  • 页面的生命周期
  • 组件的生命周期

一般页面渲染流程(navigateTo 方法,即页面栈只增加的清空下,A B 代表不同页面):

  • onLaunch(App) => onShow(App)
  • onLoad(A)=> onShow(A)=> onReady(A)=> onHide(A)
  • onLoad(B)=> onShow(B)=> onReady(B)=> onUnload(B)
  • onShow(A)

一般组件的渲染流程(navigateTo 方法,即页面栈只增加的清空下,A B C 代表不同页面和组件):

  • created(C)=> attached(C)
  • onLoad(A)=> onShow(A)=> ready(C)=> onReady(A)=> onUnload(A)=> detached(C)

子组件先完成渲染,父组件先完成卸载

数据通信

https://juejin.cn/post/6995875058224726030
这里父一般指 Page(页面),子一般指组件(Component),通信有很多的技术实现方案,但是自己只列举出最常用的几种方式:

全局通信

localStorage(本地存储)

setStorageSync和setStorage的区别-CSDN博客

wx.setStorageSync("index-data", "哈哈哈哈");const storageData = wx.getStorageSync("index-data");
if (storageData) {console.log("当前存储的数据", storageData);
}

优点:简单操作,易理解
缺点:调用到 storage,有可能设置失败;且设置后是持久缓存,可能污染原逻辑,应及时删除

globData(小程序全局存储)

const app = getApp();本质是 app.js 看作一个大的对象,通过 getApp() 获取实例并调用
app.调用具体的方法、变量

优点:简单操作,易理解;直接操作globalData对象,相比于storage执行效率更高
缺点:设置后是小程序生命周期内都可访问,可能污染原逻辑,应及时删除

父 => 子

父到子传值一般采用 property 的方式,具体实现代码如下:

<ty-child-a parentName="{{name}}" />properties: {parentName: "父组件传值",
}

父 => 父

EventChannel | 微信开放文档
通过 wx.navigateTo 中的events和eventChannel实现页面间的通信,因为 navigateTo 会加入新页面到页面栈,所以从头开始渲染,能够触及到 onLoad 的 options 方法。

// A 页面
wx.navigateTo({url: link + "?a=1&b=2",events: {calculateResult(data) {console.log("计算的结果为", data);},},success: function (res) {res.eventChannel.emit("multiplication", { result: 100 });},
});// B 页面
const a = Number(options.a);const b = Number(options.b);const eventChannel = this.getOpenerEventChannel();if (Object.keys(eventChannel).length) {eventChannel.emit("calculateResult", { result: a + b });eventChannel.on("multiplication", function (data) {console.log("相乘之后的结果", data);});}// 计算的结果为 {result: 3}
// 相乘之后的结果 {result: 100}
  • 上面代码主要利用 事件频道进行出发操作,B页面触发A页面的事件,进行传递参数
  • B 页面也可以监听自己的事件,然后等待 A 页面触发
  • 这种方式有一个坏处就是单独刷新页面会导致** eventChannel 为空,所以相关的事件可能会出问题。而同驿/优采**的做法就只是传递参数,这里需要主要传递的参数都会变成 **字符串 **类型。

子 => 父

triggerEvent

10.png

<my-component parentName="常见组件学习" bind:send-msg="sendMsg" />sendMsg(data) {console.log("来自子组件的数据", data);
}this.triggerEvent("send-msg", { id: 111, content: "这里是子组件的内容" });

selectComponent

8.png

// 引入组件的时候需要定义好 id 名称
<my-component id="my-component" parentName="常见组件学习" />const child = this.selectComponent("#my-component");
console.log("子组件实例", child);
  • 这种方式直接让父组件获取到子组件的所有数据和方法,会让父子组件耦合在一起,代码很容易出现bug,一般不推荐这种方式,除非数据交互非常频繁的场景下

子 => 子

这种情况一般很少出现,两个子组件相互通信的概率很少,可以利用全局数据通信或者上述的方法进行通信,使用方法一致

网络请求

// 设置请求的统一配置
const defaultOptions = {method: "GET", // 默认请求方法data: {}, // 请求参数header: {}, // 请求头complete: function () {}, // 完成回调
};function request(url, options) {const newOptions = { ...defaultOptions, ...urloptions };newOptions.header = {"Content-Type": "application/json",Authorization: "Bearer your-token-here", // 示例,根据需要设置...newOptions.header,};return new Promise((resolve, reject) => {wx.request({url: url,method: newOptions.method,data: newOptions.data,header: newOptions.header,success: function (res) {// 统一处理响应数据if (res.statusCode === 200) {resolve(res.data);} else {reject(err);}resolve(res.data);},fail: function (err) {// 统一处理请求失败reject(err);},complete: function () {// 请求完成的统一处理},});});
}function get(url, data) {return request(url, {method: "GET",data,});
}function post(url, data) {return request(url, {method: "POST",data,});
}export { get, post };

微信小程序有自己的一套请求机制,使用 wx.request ,但是实际场景使用的时候需要利用 Promise 异步优化一下,这里大家可以先了解,后续进行项目开发的时候根据应用场景详细讲解一下。

第三方组件

Vant/weapp 1.11

https://juejin.cn/post/7229891190900277285

Tailwind

https://weapp-tw.icebreaker.top/
引入成本过高,暂时没必要

拓展功能

后续的分包内存优化、导航栏配置、打包上线流程留到下次课程项目实战去讲解。

提问改善

Q1:xxxxx?

相关文章:

  • 征求意见《第三方运维服务水平评价指南 工业废水处理设施》
  • Unity发布PC限制本地访问exe次数
  • 从单点到全景:视频汇聚/安防监控EasyCVR全景视频监控技术的演进之路
  • 苍穹外卖项目 常用注解 + 动态sql
  • 华为昇腾×实在智能:让国产AI科技实实在在“飞得更高”
  • 游戏AI的创造思路-技术基础-深度学习(5)
  • 【neo4j图数据库】入门实践篇
  • ubuntu server 24.04 使用记录
  • 从二元一次方程组到二阶行列式再到克拉默法则
  • 实现Spring Boot与RabbitMQ消息中间件的无缝集成
  • 广州自闭症机构哪家好
  • 利用STM32的定时器输出PWM方波
  • 10分钟完成微信JSAPI支付对接过程-JAVA后端接口
  • JVM专题九:JVM分代知识点梳理
  • mysql8 锁表与解锁
  • 【140天】尚学堂高淇Java300集视频精华笔记(86-87)
  • 【vuex入门系列02】mutation接收单个参数和多个参数
  • Android 架构优化~MVP 架构改造
  • Fabric架构演变之路
  • Java读取Properties文件的六种方法
  • LeetCode18.四数之和 JavaScript
  • PHP 7 修改了什么呢 -- 2
  • react-core-image-upload 一款轻量级图片上传裁剪插件
  • uva 10370 Above Average
  • webgl (原生)基础入门指南【一】
  • 从零开始学习部署
  • 基于OpenResty的Lua Web框架lor0.0.2预览版发布
  • 日剧·日综资源集合(建议收藏)
  • 使用SAX解析XML
  • 首页查询功能的一次实现过程
  • 自定义函数
  • Hibernate主键生成策略及选择
  • 继 XDL 之后,阿里妈妈开源大规模分布式图表征学习框架 Euler ...
  • ​3ds Max插件CG MAGIC图形板块为您提升线条效率!
  • ​力扣解法汇总1802. 有界数组中指定下标处的最大值
  • ​水经微图Web1.5.0版即将上线
  • ​一文看懂数据清洗:缺失值、异常值和重复值的处理
  • $NOIp2018$劝退记
  • (04)Hive的相关概念——order by 、sort by、distribute by 、cluster by
  • (function(){})()的分步解析
  • (博弈 sg入门)kiki's game -- hdu -- 2147
  • (收藏)Git和Repo扫盲——如何取得Android源代码
  • (四)鸿鹄云架构一服务注册中心
  • ./include/caffe/util/cudnn.hpp: In function ‘const char* cudnnGetErrorString(cudnnStatus_t)’: ./incl
  • .NET Core 中的路径问题
  • .NET 中创建支持集合初始化器的类型
  • .net反编译的九款神器
  • .net实现客户区延伸至至非客户区
  • 。。。。。
  • /etc/skel 目录作用
  • /usr/lib/mysql/plugin权限_给数据库增加密码策略遇到的权限问题
  • @converter 只能用mysql吗_python-MySQLConverter对象没有mysql-connector属性’...
  • [240621] Anthropic 发布了 Claude 3.5 Sonnet AI 助手 | Socket.IO 拒绝服务漏洞
  • [Android]如何调试Native memory crash issue
  • [ArcPy百科]第三节: Geometry信息中的空间参考解析