小程序基础示例
小程序基础
基础视图组件
view
<view
hover-class="hoverClass"
hover-start-time="{{ 1000 }}"
hover-stay-time="{{ 1000 }}"
hover-stop-propagation
></view>
text
<text user-select space="nbsp" decode>\nt ext></text>
icon
<icon type="success" size="46" color="#000" />
<!-- https://www.iconfont.cn/ -->
button
<button
type="primary"
size="mini"
plain
loading
bindtap="onSayHello"
open-type="feedback"
></button>
input
<input
type="text" confirm-type="send"
password
placeholder="请输入"
placeholder-style="font-weight: bold"
placeholder-class=""
model:value="{{ inputVlaue }}"
/>
radio
<radio-group bindchange="">
<radio value="1" checked color="red" disabled> true </radio>
<radio value="2"color="blue"> false </radio>
</radio-group>
checkbox
<checkbox-group bindchange="">
<checkbox value="1" checked color="red" disabled>篮球</checkbox>
<checkbox value="2">乒乓球</checkbox>
<checkbox value="3">羽毛球</checkbox>
</checkbox-group>
textarea
<textarea
class="textarea"
placeholder="请输入您的兴趣爱好"
placeholder-class="plClass"
placeholder-style="font-weight: bold"
disabled="{{ false }}"
confirm-type="send"
model:value="{{ value }}"
/>
switch
<switch
checked
type="switch"
color="#FF0000"
disabled="{{ false }}"
bindchange=""
/>
form
<form bindsubmit="handleSubmit" bindreset="handleReset">
<input
name="userName"
class="input"
type="text"
placeholder="请输入您的姓名"
/>
<radio-group name="userGender">
<radio value="1"/> 男
<radio value="2"/> 女
</radio-group>
<button form-type="submit" type="primary">Submit</button>
<!-- 直接清空 form-type="reset" -->
<!-- 复杂逻辑 handleReset -->
<button form-type="reset" >Reset</button>
</form>
template
<!-- 声明 template -->
<template name="line">
<view>Line 1</view>
<view>Line 2</view>
<view>Line 3</view>
<view>{{ name }}</view>
</template>
<!-- 使用 template -->
<template is="line" data="{{ name }}" />
<!-- 声明外部的 template -->
<!-- /templete/header.wxml -->
<template name="header">
<view>我是 header</view>
</template>
<view>
我是 header template 之外的所有的内容
</view>
<!-- 引用外部的 template -->
<import src="./template/header"/>
<import src="./template/footer"/>
<template is="header" />
Content
<template is="footer"/>
<include src="./template/header" />
<!-- 组件公共属性 -->
<view id class style hidden data-* bind*/catch*></view>
跳转
1 标签 2 api
navigate eventChannel | uni 全局事件监听(主要)
<!-- url: 页面路径 相对/绝对路径 -->
<!-- open-type: navigate 默认值 -->
<navigator url="/pages/index/index" open-type="navigate">
跳转到 index
</navigator>
wx.navigateTo({
url: '/pages/index/index?name=coderMonkey&age=18',
events: {
sayHello(name, age) {
console.log('hello', name, age)
}
},
success: (result) => {
// off 用于取消一个事件的监听
result.eventChannel.off('sayHello')
result.eventChannel.emit('sayWorld', 'codercoder', '20')
},
fail: (res) => {},
complete: (res) => {},
})
// 目标页面
onLoad(options) {
console.log('onLoad', options)
// uni:
// import { getCurrentInstance } from 'vue'}
// const eventChannel = getCurrentInstance().ctx.getOpenerEventChannel()
const eventChannel = this.getOpenerEventChannel()
// emit 触发一个事件
eventChannel.emit('sayHello', 'coderMonkey', 18)
// on 监听方法 once 只监听一次
eventChannel.on('sayWorld', (name, age) => {
console.log('world', name, age)
})
},
uni.$on/once('aaa', (a, b) => console.log('aaa', a, b))
// 在任何页面中监听
uni.$emit('aaa', 1, 2)
uni.$off('aaa')
返回
<!-- delta="999" 回到首页 -->
<navigator open-type="navigateBack" delta="1">返回上一页</navigator>
wx.navigateBack({
delta: 1,
success: (res) => {},
fail: (res) => {},
complete: (res) => {},
})
// 查看页面栈中的页面
console.log(getCurrentPages())
redirectTo
<!-- 会销毁起始页面 -->
<navigator url="/pages/pageThree/pageThree" open-type="redirect">
跳转到 pageThree
</navigator>
wx.redirectTo({
url: '/pages/pageTwo/pageTwo?name=coderMonkey&age=99',
success: (res) => {},
fail: (res) => {},
complete: (res) => {},
})
switchTab
<!-- 不能传递参数 -->
<!-- open-type="redirect": 模拟器上效果是有问题的 真机查看 -->
<navigator url="/pages/profile/profile"open-type="switchTab">
跳转到 home
</navigator>
// 只可以跳转到 tabbar 的页面 并且 url 不能传递参数
wx.switchTab({
url: '/pages/profile/profile',
success: (res) => {},
fail: (res) => {},
complete: (res) => {},
})
reLaunch
<!-- 会销毁所有页面 -->
<navigator url="/pages/home/home" open-type="reLaunch">
跳转
</navigator>
wx.reLaunch({
url: '/pages/pageTwo/pageTwo?name=coderMonkey&age=10000',
success: (res) => {},
fail: (res) => {},
complete: (res) => {},
})
生命周期
页面
// uni:
// import { onLoad } from '@dcloudio/uni-app';
// onLaunch((options) => {
// console.log('onLaunch', options)
// })
Page({
// 1. onLoad - 监听页面的加载 做一些初始化的操作
onLoad(options) {
console.log('onLoad', options)
},
// 2. onShow - 监听页面的显示 更新数据或者状态 重新执行一些方法
onShow() {
console.log('onShow')
},
// 3. onHide - 监听页面的隐藏 保存用户当前的状态
// 清除页面中多余的定时器
onHide() {
console.log('onHide')
},
// 4. onUnload - 监听页面的卸载 清空页面的状态和多余的操作
onUnload() {
console.log('onUnload')
},
// 5. onPullDownRefresh - 监听页面下拉
onPullDownRefresh() {
console.log('onPullDownRefresh')
},
// 6. onReachBottom - 上拉触底
onReachBottom() {
console.log('onReachBottom')
},
// 7. onPageScoll - 页面滚动
onPageScroll(res) {
console.log('res', res)
}
})
应用
import { onLaunch, onShow, onHide, onError, onPageNotFound, onUnhandledRejection, onThemeChange } from '@dcloudio/uni-app';
事件交互
捕获和冒泡
<!-- 执行顺序 捕获-外 -> 捕获-内 -> 冒泡-内 -> 冒泡-外 -->
<view bindtap="冒泡-外" capture-bind:touchstart="捕获-外">
outer
<view bindtap="冒泡-内" capture-bind:touchstart="捕获-内">
inner
</view>
</view>
事件对象 event / e
<!-- type: 事件类型
timeStamp: 页面打开到触发事件所经历的毫秒数
target: 触发事件源组件
currentTarget: 触发事件当前组件
dataset: 用于获取自定义数据 (驼峰命名大写 转小写;中横线命名小写 转大写)
mark: 收集触发事件这条线上的自定义属性 (不会转化驼峰和中横线,同名属性子组件会覆盖父组件)
pageX pageY 距离文档左上角的距离
clientX clientY 距离页面可显示区域左上角的距离
detail: 通常用于在表单中获取最新 value 值 -->
<view
mark:heightOut = "200"
mark:width-out = "200"
mark:height = "200"
id="tapEvent2"
bind:tap="handleTap2"
>
outter
<view
class="view"
mark:height="100"
mark:width="100"
data-userName="coderMonkey"
data-user-age="100"
id="tapEvent"
bind:tap="handleTap"
>
inner 我是一些内容
</view>
</view>
交互反馈
onToast() {
wx.showToast({
title: '操作成功',
duration: 100000, // 默认值 1500 ms
// icon: "error",
image: '/img/about.png',
mask: true, // 透明遮罩,防止其他事件触发
success: (res) => {
console.log(res)
},
fail: (res) => {
console.log(res)
},
complete: (res) => {
console.log(res)
},
})
// wx.hideToast({
// noConflict: 0,
// success: (res) => {},
// fail: (res) => {},
// complete: (res) => {},
// })
},
onModal() {
wx.showModal({
cancelColor: '#00FF00',
cancelText: '考虑一下',
confirmColor: '#FF0000',
confirmText: '确认',
content: '确认之后就会提交哦!',
editable: true,
placeholderText: '请输入您的信息',
showCancel: true,
title: '确认操作',
success: (result) => {
// 如果说是可编辑的那么点击确定之后就可以在 result.content 中获取到结果
console.log('result', result)
},
fail: (res) => {
console.log(res)
},
complete: (res) => {
console.log(res)
}
})
},
onLoading() {
wx.showLoading({
title: 'loading...',
mask: true,
success: (res) => {},
fail: (res) => {},
complete: (res) => {},
})
setTimeout(() => {
wx.hideLoading({
noConflict: true, // loading和toast不混用
success: (res) => {},
fail: (res) => {},
complete: (res) => {},
})
}, 2000)
},
onActionSheet() {
wx.showActionSheet({
itemList: ['111', '222', '333', '444'], // string 最大 7 个
alertText: '提醒',
itemColor: '#FF0000',
success: (result) => {
console.log('result', result.tapIndex)
},
fail: (res) => {
console.log(res)
},
complete: (res) => {},
})
}
数据请求(案例)
<view>
<view>表单实战</view>
<!-- get -->
<view>
<view>获取用户信息</view>
<view>姓名:{{ name || '-' }}</view>
<view>身高:{{ height || '-' }}</view>
<button type="primary" bind:tap="handleGetUserInfoById">GET</button>
</view>
<!-- post -->
<view>
<view>更新用户信息</view>
<input
type="text"
placeholder="姓名"
bind:input="handleInputName"
/>
<input
type="text"
placeholder="身高"
bind:input="handleInputHeight"
/>
<button type="primary" bind:tap="handleUpdateUserInfoById">POST</button>
</view>
</view>
const { getUserInfoById, updateUserInfoById } = require('./api/index.js')
Page({
onRequest() {
// 原生
// 获取用户列表
wx.request({
url: 'http://121.4.100.140:9091/info',
// data: {},
// method: 'GET',
// timeout: 0,
success: (result) => {
console.log(result.data)
},
fail: (err) => {},
complete: (res) => {},
})
// 修改用户信息
wx.request({
url: 'http://121.4.100.140:9091/info/15',
data: {
name: 'coderMonkey-1',
height: 1001
},
method: 'POST',
timeout: 60000,
success: (result) => {
console.log(result.data)
},
fail: (err) => {},
complete: (res) => {},
})
},
// 表单案例(封装的request)
data: {
name: '',
height: '',
currentName: '',
currentHeight: ''
},
handleGetUserInfoById() {
getUserInfoById(15).then(res => {
if (res.code === 0) {
this.setData({
name: res.data.name,
height: res.data.height
})
} else {
wx.showToast({
title: res.message,
icon: 'none',
mask: true
})
}
}).catch(err => {
console.log(err)
})
},
handleUpdateUserInfoById() {
const name = this.data.currentName
const height = +this.data.currentHeight
updateUserInfoById(15, { name, height }).then(res => {
if (res.code === 0) {
console.log('res.data', res.data)
} else {
wx.showToast({
title: res.message,
icon: 'none',
mask: true
})
}
}).catch(err => {
console.log(err)
})
},
handleInputName(e) {
this.setData({
currentName: e.detail.value
})
},
handleInputHeight(e) {
this.setData({
currentHeight: e.detail.value
})
}
})
/http/index.js 封装 request 类
class Request {
constructor(domain) {
this.domain = domain
}
request(path, data, method) {
wx.showLoading({ title: 'loading...' })
return new Promise((resolve, reject) => {
wx.request({
url: `${this.domain}${path}`,
method,
data,
timeout: 60000,
success(res) {
resolve(res.data)
},
fail(err) {
reject(err)
},
complete () {
wx.hideLoading()
}
})
})
}
get(path, data) {
return this.request(path, 'GET', data)
}
post(path, data) {
return this.request(path, 'POST', data)
}
}
const request = new Request('http://121.4.100.140:9091')
module.exports = {
request
}
/api/user.js 封装接口请求
const { request } = require('../http/index.js')
const userApi = {
// 获取所有的用户信息
getUserInfoList() {
return request.get('/info')
},
// 根据 id 获取用户信息
getUserInfoById(id) {
return request.get(`/info/${id}`)
},
// 根据 id 修改用户信息
updateUserInfoById(id, data) {
return request.post(`/info/${id}`, data)
},
}
module.exports = userApi
/api/index.js
const userApi = require('./user.js')
module.exports = {
...userApi
}
数据存储
Page({
// 同步缓存
handleTap1() {
wx.setStorageSync('token', '111')
const token = wx.getStorageSync('token')
wx.removeStorageSync('token')
wx.clearStorageSync()
},
// 异步缓存
handleTap2() {
wx.setStorage({
key: 'token',
data: '222',
encrypt: true,
success(res) {
console.log(res)
},
fail(res) {
console.log(res)
},
complete(res) {
console.log(res)
}
})
wx.getStorage({
key: 'token',
encrypt: true,
success(res) {
console.log(res)
},
fail(res) {
console.log(res)
},
complete(res) {
console.log(res)
}
})
wx.getStorageInfo({
success(res) { console.log(res) }
})
wx.removeStorage({
key: 'token',
success(res) {
console.log(res)
},
fail(res) {
console.log(res)
},
complete(res) {
console.log(res)
}
})
wx.clearStorage({
success(res) {
console.log(res)
},
fail(res) {
console.log(res)
},
complete(res) {
console.log(res)
}
})
}
})
app.js
/**
* 生命周期
* 全局数据、方法
* 错误监听
*/
App({
// 创建全局数据
/**
* 在其他页面使用
* const app = getApp()
* const userInfo = app.globalData.userInfo
* app.globalData.userInfo.age = 999
* app.updateUserAge(888)
*/
globalData: {
userInfo: wx.getStorageSync('userInfo') || null
},
updateUserAge(age) {
this.globalData.userInfo.age = age
},
onLaunch(options) {
console.log(this.globalData)
}
})
app.json
{
"entryPagePath": "pages/element/element",
"pages": [
"pages/element/element",
"pages/navigate/navigate",
"pages/request/request"
],
"window": {
"navigationBarTitleText": "learn-mp",
"navigationBarTextStyle": "white",
"navigationBarBackgroundColor": "#000",
"navigationStyle": "default",
"navigationStyle2": "custom"
},
"tabBar": {
"color": "#aaa",
"selectedColor": "#fff",
"borderStyle": "black",
"backgroundColor": "#000",
"position": "bottom",
"custom": false,
"list": [
{
"pagePath": "pages/element/element",
"text": "视图组件",
"iconPath": "/img/index.png",
"selectedIconPath": "/img/active-index.png"
},
{
"pagePath": "pages/request/request",
"text": "数据请求",
"iconPath": "/img/profile.png",
"selectedIconPath": "/img/active-profile.png"
}
]
},
"style": "v2",
"networkTimeout": {
"request": 20000,
"connectSocket": 20000,
"downloadFile": 20000
},
"permission": {
"scope.userLocation": {
"desc": "用于给您提供更精确的服务"
}
},
"sitemapLocation": "sitemap.json"
}
project.config.json | project.private.config.json
项目私有配置文件。此文件中的内容将覆盖 project.config.json 中的相同字段。项目的改动优先同步到此文件中。详见文档:https://developers.weixin.qq.com/miniprogram/dev/devtools/projectconfig.html
sitemap.json
{
"desc": "收录配置(关于本文件的更多信息,请参考文档 https://developers.weixin.qq.com/miniprogram/dev/framework/sitemap.html)",
"rules": [
{
"page": "pages/index/index",
"action": "disallow",
"priority": 2
},
{
"page": "pages/profile/profile",
"action": "allow",
"params": ["id"],
"matching": "exact",
"priority": 3
},
{
"page": "*",
"action": "allow"
}
]
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具