【 0 】前言
【 0 】
// pages/banner/banner.js
Page({
/**
* 页面的初始数据
*/
data: {
},
/**
* 生命周期函数--监听页面加载
*/
onLoad(options) {
},
/**
* 生命周期函数--监听页面初次渲染完成
*/
onReady() {
},
/**
* 生命周期函数--监听页面显示
*/
onShow() {
},
/**
* 生命周期函数--监听页面隐藏
*/
onHide() {
},
/**
* 生命周期函数--监听页面卸载
*/
onUnload() {
},
/**
* 页面相关事件处理函数--监听用户下拉动作
*/
onPullDownRefresh() {
},
/**
* 页面上拉触底事件的处理函数
*/
onReachBottom() {
},
/**
* 用户点击右上角分享
*/
onShareAppMessage() {
}
})
<!--pages/banner/banner.wxml-->
<image src="/images/31.jpg" mode=""/>
<view> ----事件基本使用------ </view>
<button size="mini" type="warn" loading bind:tap="handShow"> 点击看控制台!!! </button>
-
app.wxss
-
这个分两种情况在小应用程序就是局部使用
-
只在一个页面使用的样式
/* pages/log/log.wxss */
text {
font-size: 50px;
color: aqua;
}
button{
/* 距离顶部30rpx */
margin-top: 300rpx;
/* 距离底部30rpx */
margin-bottom: 30rpx;
/* 优先以这个样式为准 */
background-color: rgb(147, 145, 255) !important;
}
view {
font-size: 50px;
background-color: aqua;
}
{
"pages": [
"pages/banner/banner",
"pages/log/log"
],
"window": {
"enablePullDownRefresh": false,
"backgroundColor": "#00FFFF",
"backgroundTextStyle": "dark"
},
"style": "v2",
"sitemapLocation": "sitemap.json"
}
【 1 】快速上手
-组件:view,text,button,icon,image 。。。。
-组件属性属性
-尺寸单位和样式
-rpx :等比例缩放
-样式:app.wxss xx.wxss--->局部会覆盖全局
【 2 】 tabbar使用
-app.json 中:背景图
【 3 】 首页案例
-轮播图
-公告:样式
-flex布局
-通知
-宫格
【 4 】引入矢量图
# 1 打开 https://www.iconfont.cn/
-注册成功
# 2 搜索想要的图标
-加入购物车
-在购物车中添加至项目
# 3 我的项目--项目设置--》打开base64
# 4 选择font class --》生成代码--》点击链接地址打开
# 5 把打开的链接地址内容复制到项目中
-static/css/iconfont.wxss
# 6 在app.wxss中引入
@import "/static/css/iconfont.wxss";
# 7 在想用图标的位置,加入text组件
<text class="iconfont icon-anquan">
【 一 】事件绑定
- bind:这是微信小程序中默认的绑定方式。当使用
bind
方式绑定事件时,如果子元素触发了事件,这个事件会冒泡到父元素,如果父元素也绑定了该事件的处理函数,那么父元素的事件处理函数也会被调用。 - catch:这是另一种绑定方式,用于阻止事件冒泡。当使用
catch
方式绑定事件时,如果子元素触发了事件,这个事件将不会冒泡到父元素,即使父元素也绑定了该事件的处理函数,父元素的事件处理函数也不会被调用。
1.1 基本使用
v-on:事件名='hand'
v-on:click ='hand'
简写成(用的多)
@click='hand'
方法必须放在methods中
methods: {
hand: function () {
this.show = !this.show // ! 取反
}
}
# 1 方式一
<view bind:tab="js中写方法"></view>
# 2 方式二
<view bindtab="js中写方法"></view>
# 3 js中写方法
showLog(){
console.log("我被点了")
}
<!--pages/banner/banner.wxml-->
<image src="/images/31.jpg" mode=""/>
<view> ----事件基本使用------ </view>
<!-- -->
<button size="mini" type="warn" loading bind:tap="handShow"> 点击看控制台!!! </button>
是的,您提到的 <button>
标签和它的属性确实是微信小程序中的按钮组件的写法。在微信小程序中,<button>
组件有一些特定的属性和事件。
这里是您给出的 <button>
组件的解析:
size="mini"
:设置按钮的大小为迷你型。微信小程序中的按钮有三种尺寸:default
(默认大小)、mini
(迷你大小)和small
(小尺寸,但在某些版本或文档中可能不被支持,建议使用mini
)。type="warn"
:设置按钮的类型为警告样式。微信小程序的按钮类型有default
(默认样式)、primary
(主要样式)、warn
(警告样式)和success
/success_no_circle
(成功样式,不带/带圆形图标)。loading
:如果设置了该属性(无需赋值,属性名本身就是布尔值),按钮会显示为加载中状态。bindtap="handShow"
:当按钮被点击时,会触发handShow
方法。在微信小程序中,事件绑定的语法是bindxxx
或catchxxx
(其中xxx
是事件名),然后使用=
指定要调用的方法。
所以,这个 <button>
组件表示一个迷你的、警告样式的、加载中的按钮,当点击时,会触发 handShow
方法。
在您的 js 文件中,您应该有一个名为 handShow
的方法,例如:
Page({
// ... 其他页面数据和方法
handShow: function() {
console.log('按钮被点击了!');
// 在这里执行您希望在点击按钮时执行的操作
}
});
当您在微信开发者工具中预览或运行小程序,并点击这个按钮时,您应该在控制台中看到 “按钮被点击了!” 的输出。
1.2 阻止事件冒泡
如果一个父元素(或祖先元素)和它的子元素都绑定了相同类型的事件监听器(如click
事件),并且子元素被点击时,这两个事件监听器都有可能被触发。默认情况下,子元素的事件会首先被触发,然后这个事件会冒泡到父元素,并触发父元素的事件监听器(如果绑定的话)。这个过程就叫做事件冒泡。
1.阻止事件冒泡通常用于以下场景:
- 当你只想让子元素的事件监听器被触发,而不希望父元素或祖先元素的事件监听器也被触发时。
- 当你希望优化性能,避免不必要的事件处理时。
2. 如何阻止事件冒泡
在微信小程序中,阻止事件冒泡的主要方式就是将bind
替换为catch
。例如,如果你想阻止一个按钮的点击事件冒泡,你可以这样写:
<button catchtap="handleClick">点击我</button>
<!-- 阻止事件冒泡 -->
<view style="height:300rpx;display: flex;justify-content: center;align-items: center; background-color: orange;" bind:tap="handShow2">
<!-- catch:tap -->
<button type="primary" plain catch:tap="handleButton2">阻止事件冒泡</button>
</view>
Page({
handShow2: function() {
console.log('爹的按钮被点击了!');
// 在这里执行您希望在点击按钮时执行的操作
} ,
handleButton2: function() {
console.log('这个是儿子事件!!!');
// 在这里执行您希望在点击按钮时执行的操作
} ,
})
1.3 事件对象和传参
data-*方案
mark:自定义属性
target :事件触发者 :dataset data定义的属性
currentTarget:事件绑定者 :dataset data定义的属性
<view>-------------------</view>
<!-- 事件对象和传参 -->
<view style="height:300rpx;display: flex;justify-content: center;align-items: center; background-color: pink;" bind:tap="handShow3">
<button type="primary" plain bind:tap="handleButton3" data-name="JOINNN" data-xx="tian" mark:name="mao">事件传参</button>
</view>
Page({
handleButton3:(event) => {
console.log(event)
console.log('mark传入的参数:',event.mark.name)
console.log('=============currentTarget=====================')
console.log('data-字段名传入的参数:',event.currentTarget.dataset.xx)
console.log('data-字段名传入的参数:',event.currentTarget.dataset.name)
console.log('=============target=====================')
console.log('data-字段名传入的参数:',event.target.dataset.xx)
console.log('data-字段名传入的参数:',event.target.dataset.name)
},
handShow3:(event) => {
console.log(event)
},
})
【 二 】页面跳转
2.1 wxml-组件跳转–声明式导航
# 1 使用 navigator 组件实现跳转
-url :当前小程序内的跳转链接
-open-type :跳转方式
navigate:保留当前页面,跳转到应用内的某个页面。但是不能跳到 tabbar 页面
redirect: 关闭当前页面,跳转到应用内的某个页面。但不能跳转到 tabbar 页面
switchTab:跳转到 tabBar 页面,并关闭其他所有非 tabBar 页面
reLaunch:关闭所有页面,打开到应用内的某个页面
navigateBack:关闭当前页面,返回上一页面或多级页面
# 2 普通跳转 --注意带 /
<view><navigator url="/pages/login/login"><button type="primary">登录</button></navigator></view>
# 3 open-type 属性
## 3.1 navigate:保留当前页面,跳转到应用内的某个页面。但是不能跳到 tabbar 页面
<view>
<navigator url="/pages/my/my" open-type="navigate">不能跳转到我的</navigator>
</view>
<view>
<navigator url="/pages/login/login" open-type="navigate">跳转到登录</navigator>
</view>
## 3.2 redirect: 关闭当前页面,跳转到应用内的某个页面。但不能跳转到 tabbar 页面
<view>
<navigator url="/pages/login/login" open-type="redirect">跳转到登录关闭上一个页面</navigator>
</view>
## 3.3 switchTab:跳转到 tabBar 页面,并关闭其他所有非 tabBar 页面
<view>
<navigator url="/pages/my/my" open-type="switchTab">跳转到my-tab页</navigator>
</view>
## 3.4 reLaunch:关闭所有页面,打开到应用内的某个页面
<view>
<navigator url="/pages/my/my" open-type="reLaunch">跳转到my-tab页</navigator>
<navigator url="/pages/login/login" open-type="reLaunch">跳转到login页</navigator>
</view>
## 3.5 navigateBack:关闭当前页面,返回上一页面或多级页面
<view>
<navigator url="/pages/login/login" open-type="navigate">跳转到login页</navigator>
</view>
# 默认只能返回一页,通过delta 控制返回层级 delta="2"
<navigator open-type="navigateBack">跳转到login页</navigator>
# 4 携带参数
## 4.1 跳转
<view>
<navigator url="/pages/login/login?name=justin&age=19" open-type="navigate">跳转到login页</navigator>
</view>
## 4.2 在 onLoad的options中获取参数
onLoad(options) {
console.log(options)
},
## 4.3 注意跳转tabbar不能携带参数
2.2 js-跳转–编程式导航
# 1 5 个方法
wx.navigateTo({
url: 'url',
})
wx.redirectTo({
url: 'url',
})
wx.switchTab({
url: 'url',
})
wx.reLaunch({
url: 'url',
})
wx.navigateBack()
# 2 页面
<button type="default" bind:tap="handlenavigateTo">navigateTo</button>
<button type="warn" bind:tap="handleredirectTo">redirectTo</button>
<button type="primary" bind:tap="handleswitchTab">switchTab</button>
<button type="default" bind:tap="handlereLaunch">reLaunch</button>
<button type="warn" bind:tap="handlenavigateBack">navigateBack</button>
# 3 js
handlenavigateTo(){
wx.navigateTo({
url: '/pages/login/login',
})
},
handleredirectTo(){
wx.redirectTo({
url: '/pages/login/login',
})
},
handleswitchTab(){
wx.switchTab({
url: '/pages/my/my',
})
},
handlereLaunch(){
wx.reLaunch({
url: '/pages/login/login',
})
},
handlenavigateBack(){
// 关闭当前页面,返回上一页或上某一页,传入数字
wx.navigateBack()
wx.navigateBack({
delta:2
})
},
【 三 】wxml语法
3.1 模版语法
# 1 在页面 xx.js 的 Page() 方法的 data 对象中进行声明定义
# 2 在xx.wxml 中使用 {{}} 包裹,显示数据
# 3 可以显示如下,不能编写js语句或js方法
-变量
-算数运算
-三元运算
-逻辑判断
# 4 只是单纯通过赋值,js中变量会变化,但是wxml中的页面不会变化,没有联动效果,需要使用setData()方法修改
- 更新数据
- 页面更新
# 5 setData案例 修改数字
## 5.1 wxml
<view>
<view>姓名是:{{name}}</view>
<view>年龄是:{{age}}</view>
<button bind:tap="handleAddAge" plain="true" type="primary" size="mini">点击增加年龄</button>
</view>
##5.2 js
handleAddAge(){
//this.data.age++
console.log(this.data.age)
this.setData({
age:this.data.age+1
})
},
# 6 setData案例 修改对象
## 6.1 wxml<view>
<view>姓名是:{{userinfo.name}}</view>
<view>年龄是:{{userinfo.age}}</view>
<view>爱好是:{{userinfo.hobby}}</view>
<button bind:tap="handleChangeName" plain="true" type="primary" size="mini">点击修改对象-姓名</button>
</view>
## 6.2 js
data: {
name: 'justin',
age: 19,
userinfo: {
name: 'lqz',
age: 99
}
},
handleChangeName() {
// 增加数据
this.setData({
'userinfo.hobby': '篮球'
})
// 修改数据
this.setData({
'userinfo.name': '彭于晏'
})
// 修改多个数据--》简便方案--》展开运算符
// const userinfo = {
// ...this.data.userinfo,
// name: '新名字',
// hobby: '乒乓球'
// }
// this.setData({
// // userinfo:userinfo
// userinfo //简写形式
// })
// 修改多个数据--》简便方案-->assign
const userinfo = Object.assign(this.data.userinfo, {
name: 'xxzz',
hobby: '烫头'
})
this.setData({
// userinfo:userinfo
userinfo //简写形式
})
//删除数据-->单个
delete this.data.userinfo.name // 页面删除不了,需要用setData更新
this.setData({
userinfo:this.data.userinfo
})
//删除数据-->多个--解构赋值
const {name,age,...res}=this.data.userinfo
this.setData({
userinfo:res
})
},
# 7 setData 修改数组
## 7.1 js
data: {
names:['刘亦菲','迪丽热巴','古力娜扎','马尔扎哈']
},
handleChangeList(){
//1 增加数组
// 1.1 增加再设置值
this.data.names.push('亚瑟王')
this.setData({
names:this.data.names
})
// 1.2 通过数组拼接
// const newList=this.data.names.concat("甄姬")
// this.setData({
// names:newList
// })
// 1.3 通过解构赋值
const newList=[...this.data.names,"李白"]
this.setData({
names:newList
})
// 2 修改数组
this.setData({
'names[1]':'justin'
})
// 3 删除数组
this.data.names.slice(1)
this.setData({
names:this.data.names.slice(1)
})
},
## 7.2 wxml
<view wx:for="{{names}}" wx:key="index">
{{item}}
</view>
<button bind:tap="handleChangeList" plain="true" type="primary" size="mini">修改数组</button>
# 8 双向数据绑定:input checkbox
<view>
<!-- 不支持数组和对象 -->
<input type="text" model:value='{{name}}' style="border:orange solid 1rpx"/>
<checkbox model:checked="{{isCheck}}"/>
<text>{{isCheck}}</text>
</view>
3.2 列表渲染
# 1 基本使用
## 1.1 js
data: {
goodsList:[{id:1001,name:'钢笔',price:9},{id:1002,name:'铅笔',price:6},{id:1003,name:'脸盆',price:99}]
},
##1.2 wxml
<view>
<!-- wx:key 提升性能,不写会警告 可以用 index或 *this:代指item本身 要唯一-->
<view wx:for="{{goodsList}}" wx:key="*this">
<!-- 默认每个对象是item,默认每个下标是index -->
<!-- <text>商品id:{{item.id}}--商品名字:{{item.name}}--商品价格:{{item.price}}</text> -->
</view>
</view>
# 2 修改wx:for-index wx:for-item
<view>
<view wx:for="{{goodsList}}" wx:key="*this" wx:for-item="info">
<!-- 修改默认index和item--wx:for-index wx:for-item -->
<text>商品id:{{info.id}}--商品名字:{{info.name}}--商品价格:{{info.price}}</text>
</view>
</view>
# 3 block
<block>商品id:{{info.id}}--商品名字:{{info.name}}--商品价格:{{info.price}}</block>
3.3 条件渲染
# 1 wx:if wx:elif wx:else
<view>
<input type="text" model:value='{{score}}' style="border:orange solid 1rpx"/>
<view wx:if="{{score>=90&&score<=100}}">优秀</view>
<view wx:elif="{{score>=80&&score<90}}">良好</view>
<view wx:elif="{{score>=60&&score<80}}">及格</view>
<view wx:else>不及格</view>
</view>
# 2 wx:if 和 hidden
## 2.1 js
showPhoto:true,
showPhotoHidden:true
handleShowPhoto(){
this.setData({
showPhoto:!this.data.showPhoto
})
console.log(this.data.showPhoto)
},
handleShowPhotoHidden(){
this.setData({
showPhotoHidden:!this.data.showPhotoHidden
})
},
## 2.2 wxml
<view>
<image src="/images/b.jpg" mode="widthFix" wx:if="{{showPhoto}}"/>
<button bind:tap="handleShowPhoto" plain="true" type="primary" size="mini">显示隐藏图片(if)</button>
<view></view>
<image src="/images/b.jpg" mode="widthFix" hidden="{{showPhotoHidden}}"/>
<button bind:tap="handleShowPhotoHidden" plain="true" type="primary" size="mini">显示隐藏图片(hidden)</button>
</view>
【 四 】发送请求
前端
在项目上线的时候就要在小程序里面进行设置
[小程序 (qq.com)](https://mp.weixin.qq.com/]
如果只是本地测试只需要在
<!--pages/log/log.wxml-->
<!-- <image src="{{src}}" mode=""/>
<text>
{{name}}
</text> -->
<button size="mini" type="default" plain class="mybutton" bindtap="handLoad">点我加载数据</button>
<swiper
autoplay
interval="2000"
indicator-dots
indicator-color="#00FF00"
indicator-active-color="#70DB93"
circular
>
<!-- 解压赋值 -->
<swiper-item wx:for="{{bannerList}}" wx:key="*this">
<image src="{{item.image}}" mode="widthFix"/>
</swiper-item>
</swiper>
// pages/log/log.js
Page({
/**
* 页面的初始数据
*/
data: {
src : '/images/30.jpg',
name : 'maojingyi',
bannerList: []
},
handLoad(){
console.log('asd'),
wx.request({
url: 'http://127.0.0.1:8000/home/banner/',
method:'GET',
data:{},
header:{},
success:(res)=>{
console.log(res.data.results)
this.setData({
bannerList:res.data.results
})
},
fail:err=>{
console.log("失败")
},
complete:()=>{
console.log('成功或者失败,都会执行代码!!!')
}
})
}
})
后端
- models
from django.db import models
# Create your models here.
from lufy.utils.utils_model import BaseModel
class Banner(BaseModel):
title = models.CharField(max_length=16, unique=True, verbose_name='名称')
image = models.ImageField(upload_to='banner', verbose_name='图片')
link = models.CharField(max_length=64, verbose_name='跳转链接')
info = models.TextField(verbose_name='详情')
class Meta:
db_table = 'home_banner'
verbose_name_plural = '轮播图'
def __str__(self):
return self.title
- views.py
from django.core.cache import cache
# Create your views here.
from rest_framework.viewsets import GenericViewSet
# 引用公共文件夹的数据
from lufy.utils.utils_mixin import APIListModelMixin
# 导入轮播图表
from .models import Banner
from .serializer import Bannerserializer
# 这个就是导入自定义的common_setting的配置文件
from django.conf import settings
from utils.utils_response import APIResponse
from utils.logg import logger
from rest_framework.mixins import ListModelMixin
# 引用自定义的视图类
class BannerView(GenericViewSet, ListModelMixin):
# is_delete(否删除)、is_show(上架)和orders(优先级)
queryset = Banner.objects.all().filter(is_delete=False, is_show=True).order_by('orders')[0:settings.BANNER_COUNT]
serializer_class = Bannerserializer
def list(self, request, *args, **kwargs):
# 尝试从缓存中获取banner_list
banner_list = cache.get('banner_list')
if banner_list is None:
logger.info('调用缓存')
# 缓存中没有,调用mixin或父类的list方法获取数据并序列化
response = super().list(request, *args, **kwargs)
# 假设response.data是我们要缓存的数据
banner_list = response.data
# 将数据放入缓存 这个就是1缓存时间一个小时30秒
cache.set('banner_list', banner_list, timeout=1 * 30) # 例如,缓存1小时
# 构造并返回自定义的APIResponse(如果需要)
return APIResponse(results=banner_list)
- Bannerserializer
from rest_framework import serializers
from .models import Banner
class Bannerserializer(serializers.ModelSerializer):
class Meta:
model = Banner
fields = ['id','title', 'image', 'link']
- urls.py
from django.urls import path
from . import views
from .views import BannerView
# 自动生成路由
from rest_framework.routers import SimpleRouter, DefaultRouter
router = SimpleRouter()
# 轮播图
# http://127.0.0.1:8000/home/banner/
router.register('banner', BannerView, 'banner')
urlpatterns = [
# 轮播图
# path('banner/', BannerView.as_view()),
]
urlpatterns += router.urls
【 五 】对话框
5.1 模态对话框
##### wxml
<button type="default" size="mini" bind:tap="showModel">弹出模态框</button>
### js ###
showModel(){
wx.showModal({
title: '这是标题',
content: '这是内容部分~~',
complete: (res) => {
if (res.cancel) {
console.log('用户取消了')
}
if (res.confirm) {
console.log('用户确认了')
}
}
})
}
5.2 消息对话框
#### wxml
<button type="default" size="mini" bind:tap="showToast">弹出消息框</button>
### js
showToast(){
wx.showToast({
title: '恭喜您,秒杀成功',
icon:"success",
duration:2000
})
}
【 六 】存储
##### 在调试窗口中可以通过appdata看到当前页面中的变量,及变量变化
#### wxml####
<button type="default" plain bind:tap="handleSave">存储数据</button>
<button type="primary" plain bind:tap="handleGet">获取数据</button>
<button type="default" plain bind:tap="handleDelete">删除数据</button>
<button type="primary" plain bind:tap="handleClear">清空数据</button>
###js### 同步####
handleSave() {
wx.setStorageSync('name', "justin")
wx.setStorageSync('userinfo', {name:'lqz',age:19})
},
handleGet() {
const name=wx.getStorageSync('name')
const userinfo=wx.getStorageSync('userinfo')
console.log(name)
console.log(userinfo)
},
handleDelete() {
wx.removeStorageSync('name')
},
handleClear() {
wx.clearStorageSync()
}
###js### 异步####
handleSave() {
wx.setStorage({
key:'name',
data:"justin"
})
wx.setStorage({
key:'userinfo',
data:{name:'lqz',age:19}
})
},
async handleGet() {
const name= await wx.getStorage({key:'name'})
const userinfo= await wx.getStorage({key:'userinfo'})
console.log(name)
console.log(userinfo)
},
handleDelete() {
wx.removeStorage({key:'name'})
},
handleClear() {
wx.clearStorage()
}
ndleGet">获取数据
删除数据
清空数据
###js### 同步####
handleSave() {
wx.setStorageSync(‘name’, “justin”)
wx.setStorageSync(‘userinfo’, {name:‘lqz’,age:19})
},
handleGet() {
const name=wx.getStorageSync(‘name’)
const userinfo=wx.getStorageSync(‘userinfo’)
console.log(name)
console.log(userinfo)
},
handleDelete() {
wx.removeStorageSync(‘name’)
},
handleClear() {
wx.clearStorageSync()
}
###js### 异步####
handleSave() {
wx.setStorage({
key:‘name’,
data:“justin”
})
wx.setStorage({
key:‘userinfo’,
data:{name:‘lqz’,age:19}
})
},
async handleGet() {
const name= await wx.getStorage({key:‘name’})
const userinfo= await wx.getStorage({key:‘userinfo’})
console.log(name)
console.log(userinfo)
},
handleDelete() {
wx.removeStorage({key:‘name’})
},
handleClear() {
wx.clearStorage()
}