基础创建演示
第一步,新建一个小程序的项目目录。名字可以随便起,这里称为wechat-miniprogram-demo
。
第二步,在该目录里面,新建一个脚本文件app.js
。这个脚本用于对整个小程序进行初始化。
第三步,新建一个配置文件app.json
,记录项目的一些静态配置。 app.json 不能写注释
-
app.json
文件的内容,至少必须有一个pages
属性,指明小程序包含哪些页面。
// pages属性是一个数组,数组的每一项就是一个页面。
// 这个示例中,小程序只有一个页面,所以数组只有一项pages/home/home。
{
"pages": [ // pages
"pages/home/home"
]
}
pages/home/home是一个三层的文件路径。
所有页面都放在pages子目录里面。
每个页面有一个自己的目录,这里是pages下面的home子目录,表示这个页面叫做home。页面的名字可以随便起,只要对应的目录确实存在即可。
小程序会加载页面目录pages/home里面的home.js文件,.js后缀名可以省略,所以完整的加载路径为pages/home/home。home.js这个脚本的文件名也可以随便起,但是习惯上跟页面目录同名。
第四步,新建pages/home子目录。
然后,在这个目录里面新建一个脚本文件home.js
。该文件的内容如下。
Page({});
// `Page()`由小程序原生提供,它是一个函数,用于初始化一个页面实例。它的参数是一个配置对象,用于设置当前页面的行为属性。这里是一个空对象,表示不设置任何属性。
第五步,在pages/home
目录新建一个home.wxml
文件。WXML 是微信页面标签语言,类似于 HTML 语言,用于描述小程序的页面。
home.wxml
的内容很简单,就写一行hello world
。
hello world
到这一步,可以在开发者工具里面,看到运行结果了。
WXML 标签语言
<view>
<text> hello world </text>
</view>
// `<view>`标签表示一个区块,用于跟其他区块分隔,类似 HTML 语言的`<div>`标签。`<text>`表示一段行内文本,类似于 HTML 语言的`<span>`标签,多个`<text>`标签之间不会产生分行。
上面的代码用到了两个标签:<view>
和<text>
。
// 目前文件结构
|- app.json
|- app.js
|- pages
|- home
|- home.wxml
|- home.js
项目配置文件 app.json
window 用于设置小程序的状态栏、导航条、标题、窗口背景色 :
官网链接:https://developers.weixin.qq.com/miniprogram/dev/reference/configuration/app.html#window
最外层目录的app.json
文件用于整个项目的配置,对于所有页面都有效。
除了pages
属性,app.json
文件还有一个 (见上面官网链接),用来设置小程序的窗口。window
属性的值是一个对象,其中有三个属性很常用。
navigationBarBackgroundColor://导航栏的颜色,默认为#000000(黑色)。
navigationBarTextStyle://导航栏的文字颜色,只支持black(黑色)或white(白色),默认为white。
navigationBarTitleText://导航栏的文字,默认为空。
// 代码演示
{
"pages": [
"pages/home/home"
],
"window": {
"navigationBarBackgroundColor": "#ff0000",
"navigationBarTextStyle": "white",
"navigationBarTitleText": "小程序 Demo"
}
}
样式
-
外层目录放置一个
app.wxss
文件,里面采用 CSS 语法设置页面样式。这个文件的设置,对所有页面都有效。 -
在单个文件
pages/home
目录里面,新建一个home.wxss
文件,只对 home 页面生效
使用 CSS 样式,但是样式文件的后缀名一律要写成.wxss
。
<view>
<text class="title">hello world</text>
</view>
// app.wxss文件中
.title {
font-size: 24pt;
color: blue;
}
Flex 布局
page {
height: 100%;
width: 750rpx;
display: flex;
justify-content: center;
align-items: center;
}
这里单位是rpx
,而不是px
。rpx
是小程序为适
应不同宽度的手机屏幕,而发明的一种长度单位。
不管什么手机屏幕,宽度一律为750rpx
。它的好处是换算简单,如果一个元素的宽度是页面的一半,只要写成width: 375rpx;
即可。
样式导入
@import 可以导入外联样式表
@import '路径';
图片轮播
小程序原生的可以提供图片轮播效果。
<swiper>
组件的indicator-dots
属性设置是否显示轮播点,autoplay
属性设置是否自动播放轮播。它们的属性值都是一个布尔值,这里要写成{{true}}
。这种{{...}}
的语法,表示里面放置的是 JavaScript 代码。
// 代码演示
<view>
<swiper // <swiper>组件就是轮播组件
indicator-dots="{{true}}" //indicator-dots设置是否显示轮播点
autoplay="{{true}}" // autoplay设置是否自动播放轮播
style="width: 750rpx;">
<swiper-item> // 放置了三个<swiper-item>组件,表示有三个轮播项目,每个项目就是一个<image>组件。
<image src="https://picsum.photos/200"></image>
</swiper-item>
<swiper-item>
<image src="https://picsum.photos/250"></image>
</swiper-item>
<swiper-item>
<image src="https://picsum.photos/300"></image>
</swiper-item>
</swiper>
</view>
数据绑定
// 打开home.js文件
Page({
data: {
name: '张三'
}
});
//渲染到页面
<view>
<text class="title">hello {{name}}</text>
</view>
data
对象的所有属性,自动成为当前页面可以读取的全局变量。也就是说,home
页面可以自动读取name
变量。
全局数据
数据绑定只对当前页面有效,如果某些数据要在多个页面共享,就需要写到全局配置对象里面。
打开app.js
,改写如下。
App({
globalData: { // 随便起个对象名名字,用于在多个页面之间分享的值
now: (new Date()).toLocaleString()
}
});
// 其他页面使用共享的数据
const app = getApp();
Page({
data: {
now: app.globalData.now // 页面直接使用插值表达式就可以使用了 {{now}}
}
});
-
getApp()
函数是小程序原生提供的函数方法,从页面获取 App 实例对象。 -
拿到实例对象以后,就能从它上面拿到全局配置对象的
globalData
属性,从而把app.globalData.now
赋值给页面脚本的now
属性,进而通过数据绑定机制,变成页面的全局变量now
。
事件
也会有事件捕获和事件冒泡
tap://触摸后马上离开。
longpress://触摸后,超过 350ms 再离开。如果指定了该事件的回调函数并触发了该事件,tap事件将不被触发。
touchstart://触摸开始。
touchmove://触摸后移动。
touchcancel://触摸动作被打断,如来电提醒,弹窗等。
touchend://触摸结束。
在传播上分成两个阶段:
-
先是捕获阶段(由上层元素向下层元素传播),
-
然后是冒泡阶段(由下层元素向上层元素传播)。所以,同一个事件在同一个元素上面其实会触发两次:捕获阶段一次,冒泡阶段一次
// 指定是哪个阶段触发回调函数
capture-bind:捕获阶段触发。
capture-catch:捕获阶段触发,并中断事件,不再向下传播,即中断捕获阶段,并取消随后的冒泡阶段。
bind:冒泡阶段触发。
catch:冒泡阶段触发,并取消事件进一步向上冒泡。
案例演示:
前缀里面的冒号可以省略,即写成bindtap
也可以
<view>
<text class="title">hello {{name}}</text>
<button bind:tap="buttonHandler">点击</button> // bind:冒泡阶段触发。
</view>
// Page
Page({
data: {
name: '张三'
},
buttonHandler(event) {
this.setData({ // 事件回调函数内部的this,指向页面实例。
name: '李四' // 页面实例的 this.setData()方法,可以更改配置对象的data属性
});
}
});
动态提示 Toast
用来增强互动效果 如: 每次操作后,都显示一个动态提示
打开home.js
文件,为this.setData()
加上第二个参数。
这个参数函数内部,调用了wx.showToast()
方法,wx
是小程序提供的原生对象,所有客户端 API 都定义在这个对象上面,wx.showToast()
会展示微信内置的动态提示框,它的参数对象的title
属性指定提示内容,duration
属性指定提示框的展示时间,单位为毫秒。过了700毫秒,提示框就会自动消失。
//this.setData()方法第二个参数,这是一个函数,
// 它会在页面变更完毕后(即this.setData()执行完)自动调用。
Page({
data: {
name: '张三'
},
buttonHandler(event) {
this.setData({
name: '李四'
}, function () { // 第二个参数
//它的参数对象的 title 属性指定提示内容, duration 属性指定提示框的展示时间,单位为毫秒。
wx.showToast({ // // wx.showToast() 会展示微信内置的动态提示框,
title: '操作完成', // title指定提示内容
duration: 700 // duration展示时间,单位为毫秒。 过了700毫秒,提示框就会自动消失。
});
}),
}
});
对话框 Modal
小程序提供的wx.showModal()
方法,制作一个对话框,即用户可以选择”确定”或”取消”。
// 打开home.js文件
Page({
data: {
name: '张三'
},
buttonHandler(event) {
const that = this; // 赋值 this
wx.showModal({ // `wx.showModal()`方法的参数是一个配置对象
title: '操作确认', // `title`属性表示对话框的标题
content: '你确认要修改吗?', // `content`属性表示对话框的内容
success (res) { // `success`属性指定对话框成功显示后的回调函数
if (res.confirm) { // `confirm`属性为`true`,点击的就是"确定"按钮
that.setData({ //同上次动态提示案例代码 这里this不会指向页面实例,所以上面用变量接受以下this
name: '李四'
}, function () {
wx.showToast({
title: '操作完成',
duration: 700
});
});
} else if (res.cancel) { // 失败的 // `cancel`属性为`true`,点击的就是"取消"按钮
console.log('用户点击取消');
}
}
});
}
});
-
如果参数对象的
confirm
属性为true
,点击的就是”确定”按钮, -
cancel
属性为true
,点击的就是”取消”按钮。
注意,上面代码写的是that.setData()
,而不是this.setData()
。这是因为setData()
方法定义在页面实例上面,但是由于success()
回调函数不是直接定义在Page()
的配置对象下面,this
不会指向页面实例,导致this.setData()
会报错。解决方法就是在buttonHandler()
的开头,将this
赋值给变量that
,然后在success()
回调函数里面使用that.setData()
去调用。
WXML 渲染语法
WXML 的全称是微信页面标签语言(Weixin Markup Language),它不仅提供了许多功能标签,还有一套自己的语法,可以设置页面渲染的生效条件,以及进行循环处理。
// 数据
Page({
data: {
items: ['事项 A', '事项 B', '事项 C']
}
});
// 页面
<view>
// 数组有多少个成员,就会生成多少个<text>。渲染后的页面结构如下。
<text class="title" wx:for="{{items}}"> // 循环 类似Vue
{{index}}、 {{item}}
</text>
</view>
// 运行结果
/*
<view>
<text>...</text>
<text>...</text>
<text>...</text>
</view>
*/
客户端数据储存
// 一个输入框 一个按钮 实现点击按钮新增事项,渲染到页面
// input事件的监听函数inputHandler(输入内容改变时触发),
// 按钮有一个tap事件的监听函数buttonHandler(点击按钮时触发)。这两个监听函数负责处理用户的输入。
<view>
<text class="title" wx:for="{{items}}">
{{index}}、 {{item}}
</text>
<input placeholder="输入新增事项" bind:input="inputHandler"/> // 输入内容改变时触发
<button bind:tap="buttonHandler">确定</button> // tap:// 点击按钮时触发
</view>
// -------------
Page({
data: {
items: [],
inputValue: ''
},
inputHandler(event) {
this.setData({
inputValue: event.detail.value || '' // 有数据就给inputValue ,没有就给 ''
});
},
buttonHandler(event) {
const newItem = this.data.inputValue.trim(); // 去掉左右空格
if (!newItem) return; // 空的就return出去
const itemArr = [...this.data.items, newItem];
wx.setStorageSync('items', itemArr); // 本地缓存
this.setData({ items: itemArr }); // 新增data里面items的数据
},
// onLoad()方法,该方法属于页面的生命周期方法,页面加载后会自动执行该方法。它只执行一次,用于页面初始化
onLoad() {
const itemArr = wx.getStorageSync('items') || []; // 拿数据
this.setData({ items: itemArr }); // 给data
}
});
wx.setStorageSync()
方法用于将数据写入客户端储存。它接受两个参数,分别是键名和键值。与之配套的,
wx.getStorageSync()
方法,用于读取客户端储存的数据。它只有一个参数,就是键名。这两个方法都是同步的,小程序也提供异步版本,请参考。
远程数据请求
Page({
data: { items: [] },
onLoad() {
const that = this;
wx.request({
url: 'http://localhost:3000/items',
success(res) {
that.setData({ items: res.data });
}
});
}
});
< open-data >组件
如果要在页面上展示当前用户的身份信息,可以使用小程序提供的。
-
<open-data>
不需要用户授权,也不需要登录,所以用起来很方便。 -
但也是因为这个原因,小程序不允许用户脚本读取
<open-data>
返回的信息。
// home 文件
// <open-data>组件的type属性指定所要展示的信息类型,
// userAvatarUrl表示展示用户头像,
// userNickName表示用户昵称。
<view>
<open-data type="userAvatarUrl"></open-data>
<open-data type="userNickName"></open-data>
</view>
userAvatarUrl:用户头像
userGender:用户性别
userCity:用户所在城市
userProvince:用户所在省份
userCountry:用户所在国家
userLanguage:用户的语言
获取用户个人信息
如果想拿到用户的个人信息,必须得到授权。官方建议,通过按钮方式获取授权
<button>
标签的open-type
属性,指定按钮用于获取用户信息,bind:getuserinfo
属性表示点击按钮会触发getuserinfo
事件,即跳出对话框,询问用户是否同意授权。
<view>
<text class="title">hello {{name}}</text>
<button open-type="getUserInfo" bind:getuserinfo="buttonHandler">
授权获取用户个人信息
</button>
</view>
Page({
data: { name: '' },
buttonHandler(event) { //不管用户点击"拒绝"或"允许",都会执行这个函数
// 通过事件对象event有没有detail.userInfo属性,来判断用户点击了哪个按钮。如果能拿到event.detail.userInfo属性,就表示用户允许读取个人信息。这个属性是一个对象,里面就是各种用户信息,比如头像、昵称等等。
if (!event.detail.userInfo) return;
this.setData({
name: event.detail.userInfo.nickName
});
}
});
//实际开发中,可以先用wx.getSetting()方法判断一下,用户是否已经授权过。如果已经授权过,就不用再次请求授权,而是直接用wx.getUserInfo()方法获取用户信息。
页面跳转
方式一:
<navigator>
就是链接标签,相当于网页标签<a>
,只要用户点击就可以跳转到url
属性指定的页面(这里是第一页的位置)。
<view>
<text class="title">这是首页</text>
<navigator url="../second/second">前往第二页</navigator>
</view>
方式一:
wx.navigateTo() 页面跳转
<view>
<text class="title">这是首页</text>
<button bind:tap="buttonHandler">前往第二页</button>
</view>
// --------
Page({
//只要用户点击按钮,就会调用wx.navigateTo()方法。该方法的参数是一个配置对象,该对象的url属性指定了跳转目标的位置,自动跳转到那个页面。
buttonHandler(event) {
wx.navigateTo({
url: '../second/second'
});
}
});
请登录后查看回复内容