https://mp.weixin.qq.com/
品牌,营销
app
和多个描述各自页面的 page
组成pages
:小程序的页面放在该目录,一般一个目录就是一个页面
utils
:放置的是项目模块化的公共代码(模块文件,可以做一些功能模块封装)common
:公共的样式,components
:公共的组件static
:公共的资源,图片,视屏,音频文件app.js
:放置的整个小程序的逻辑。(项目的入口js文件)app.json
: 放置的是整个小程序的配置(项目的配置文件)app.wxss
:放置的是小程序整体的样式结构(全局的css样式文件)project.config.json
:项目配置文件,不要手动修改里面的配置,记录用户配置的喜好,即使换了小程序的运行环境,不用重新配置了。sitemap.json
:配置微信能不能搜索到该小程序(栈点索引)app
和多个描述各自页面的 page
。文件 | 必需 | 作用 |
---|---|---|
app.js | 是 | 小程序逻辑 |
app.json | 是 | 小程序公共配置 |
app.wxss | 否 | 小程序公共样式表 |
文件类型 | 必需 | 作用 |
---|---|---|
js | 是 | 页面逻辑 |
wxml | 是 | 页面结构 |
json | 否 | 页面配置 |
wxss | 否 | 页面样式表 |
*.js、app.json、*.wxml、*.wxss
(其中 wxml 和 wxss 文件仅针对在 app.json 中配置了的页面)。除此之外,只有后缀名在白名单内的文件可以被上传,不在白名单列表内文件在开发工具能被访问到,但无法被上传。具体白名单列表如下:
app.json
文件用来对微信小程序进行全局配置,决定页面文件的路径(配置路由及)、窗口表现、设置网络超时时间、设置多 tab 等。
"pages": [
"pages/index/index",
"pages/cart/cart",
"pages/my/my",
"pages/cate/cate"
],
"entryPagePath": "pages/index/index",
{
"pages": [
"pages/index/index",
"pages/a/a",
"pages/logs/logs",
"pages/b/b"
],
"window": {
"navigationBarBackgroundColor": "#f00",
"navigationBarTitleText": "我的",
"navigationBarTextStyle": "black",
// 下拉刷新界面的背景颜色,需要开启enablePullDownRefresh,才能看见效果
"backgroundColor": "#ccc",
"enablePullDownRefresh": true,
"backgroundTextStyle": "light",
// 设置导航栏 如果设置custom 设置自定义导航栏 之前做的导航栏样式都不会再有效果
"navigationStyle": "custom"
},
"style": "v2",
"sitemapLocation": "sitemap.json"
}
"tabBar": {
"color":"#ccc",
"selectedColor": "#f00",
"backgroundColor": "#fff",
"borderStyle": "white",
"position": "top",
"custom": false,
"list": [
{
"pagePath": "pages/index/index",
"text":"首页",
"iconPath": "./images/index.png",
"selectedIconPath": "./images/indexFull.png"
},
{
"pagePath": "pages/car/car",
"text":"购物车",
"iconPath": "./images/cart.png",
"selectedIconPath": "./images/cartFull.png"
}
,
{
"pagePath": "pages/mine/mine",
"text":"个人中心",
"iconPath": "./images/my.png",
"selectedIconPath": "./images/myFull.png"
}
]
},
注意
.json
文件来对本页面的窗口表现进行配置,页面中配置项会覆盖 app.json
的 window
中相同的配置项。页面配置的作用范围只作用于该页面。 "navigationBarBackgroundColor": "#ff0000",
"navigationBarTextStyle": "white",
"navigationBarTitleText": "小u商城",
"backgroundColor": "#00ff00",
"backgroundTextStyle": "dark",
"enablePullDownRefresh": true
sitemap.json
配置,或者管理后台页面收录开关来配置其小程序页面是否允许微信索引。当开发者允许微信索引时,微信会通过爬虫的形式,为小程序的页面内容建立索引。当用户的搜索词条触发该索引时,小程序的页面将可能展示在搜索结果中sitemap.json
文件用于配置小程序及其页面是否允许被微信索引,文件内容为一个 JSON 对象,如果没有 sitemap.json
,则默认为所有页面都允许被索引;sitemap.json
有以下属性:属性 | 类型 | 必填 | 描述 |
---|---|---|---|
rules | Object[] | 是 | 索引规则列表 |
{
"rules": [{
"action": "disallow",
"page":"/pages/cart/cart"
},{
"action": "disallow",
"page":"/pages/my/my"
},{
"action": "allow",
"page":"/pages/detail/detail",
"params": ["price","info"],
"matching": "partial"
}]
}
属性 | 类型 | 必填 | 默认值 | 取值 | 取值说明 |
---|---|---|---|---|---|
action | string | 否 | “allow” | “allow”、“disallow” | 命中该规则的页面是否能被索引 |
page | string | 是 | “*”、页面的路径 | * 表示所有页面,不能作为通配符使用 |
|
params | string[] | 否 | [] | 当 page 字段指定的页面在被本规则匹配时可能使用的页面参数名称的列表(不含参数值) | |
matching | string | 否 | “inclusive” | 参考 matching 取值说明 | 当 page 字段指定的页面在被本规则匹配时,此参数说明 params 匹配方式 |
priority | Number | 否 | 优先级,值越大则规则越早被匹配,否则默认从上到下匹配 |
值 | 说明 |
---|---|
exact | 当小程序页面的参数列表等于 params 时,规则命中 |
inclusive | 当小程序页面的参数列表包含 params 时,规则命中 |
exclusive | 当小程序页面的参数列表与 params 交集为空时,规则命中 |
partial | 当小程序页面的参数列表与 params 交集不为空时,规则命中 |
onLaunch: function (option) {
if(option.scene==1035){
console.log("发放优惠券")
}
if(option.scene==1011){
console.log("点餐")
}
},
场景值
App
的 onLaunch
和 onShow
,或wx.getLaunchOptionsSync 中获取上述场景值。App({
// 小程序初始化完成走的生命周期
onLaunch(a){
// console.log("onlaunch",a)
// 同步
let b = wx.getLaunchOptionsSync();
console.log(b)
if(b.scene==1011){
console.log("活动详情")
}
},
onShow(e){
console.log("onshow",e)
}
})
JavaScript
引擎为小程序提供开发者 JavaScript
代码的运行环境以及微信小程序的特有功能。JavaScript
文件,并在小程序启动的时候运行,直到小程序销毁。这一行为类似 ServiceWorker,所以逻辑层也称之为 App Service。JavaScript
的基础上,我们增加了一些功能,以方便小程序的开发:
App
和 Page
方法,进行程序注册和页面注册。getApp
和 getCurrentPages
方法,分别用来获取 App
实例和当前页面栈。JavaScript
在 web 中一些能力都无法使用,如 window
,document
等。app.js
中调用 App
方法注册小程序实例,绑定生命周期回调函数、错误监听和页面不存在监听函数等。Object
参数,其指定小程序的生命周期回调等。app.js
中调用,必须调用且只能调用一次。不然会出现无法预期的后果。App({
/**
\* 当小程序初始化完成时,会触发 onLaunch(全局只触发一次)
*/
onLaunch: function () {
console.log("app launch")
},
/**
\* 当小程序启动,或从后台进入前台显示,会触发 onShow
*/
onShow: function (options) {
console.log("app show")
},
/**
\* 当小程序从前台进入后台,会触发 onHide
*/
onHide: function () {
console.log("app hide")
},
/**
\* 当小程序发生脚本错误,或者 api 调用失败时,会触发 onError 并带上错误信息(当小程序有报错信息,无论是页面文件还是全局文件,只要有报错信息,就会触发onerror函数)
*/
onError: function (msg) {
//调用记录日志接口
},
onPageNotFound:function(){
wx.navigateTo({
url: './pages/notfound/notfound',
})
}
})
App({
globalData:{
token:"",
userinfo:""
},
/**
\* 当小程序初始化完成时,会触发 onLaunch(全局只触发一次)
*/
onLaunch: function () {
this._login()
},
_login:function(){
//判断用户有没有登录过
//如果登录过
//调用登录的接口,返回对应的token
//将token存储到缓存中,再将token放到globalData中,这里globalData就是全局变量
console.log("login ok")
this.globalData.token="abcdefgh124343242"
this.globalData.userInfo={
name:"zhangsan"
}
console.log(this.globalData)
},
/**
\* 当小程序启动,或从后台进入前台显示,会触发 onShow
*/
onShow: function (options) {
console.log("app show")
},
/**
\* 当小程序从前台进入后台,会触发 onHide
*/
onHide: function () {
console.log("app hide")
},
/**
\* 当小程序发生脚本错误,或者 api 调用失败时,会触发 onError 并带上错误信息
*/
onError: function (msg) {
//调用记录日志接口
},
onPageNotFound:function(){
wx.navigateTo({
url: './pages/notfound/notfound',
})
}
})
//app.js
App({
// 小程序启动或者切前台
onShow(){
console.log("onshow")
},
// 小程序初始化完成 全局只触发一次
onLaunch(){
console.log("onlaunch")
console.log(this.userInfo.name)
console.log(this.userInfo.age)
console.log(this.say())
},
// 小程序切后台的时候触发
onHide(){
console.log("onhide")
},
// 当小程序有报错信息,无论是页面文件还是全局文件,只要有报错信息,就会触发onerror函数
onError(err){
console.log("错误信息",err)
},
onPageNotFound(){
console.log("页面不存在")
wx.navigateTo({
url: '/pages/logs/logs',
})
},
// 全局的变量
userInfo:{
name:"张三",
age:20
},
// say(){
// return "正在吃东西"
// }
// 全局的函数
say:function(){
// console.log(this.userInfo,"函数")
// 在函数内部访问全局变量
return this.userInfo.name + "正在吃东西"
}
})
// 获取app实例唯一的方法
let app = getApp();
console.log(app.userInfo.name)
// 注意事项:不要在页面中调用app的生命周期
Page({
})
getApp
方法获取到全局唯一的 App 实例,获取App上的数据或调用自定义函数开发者注册在 App
上的函数。// xxx.js
const appInstance = getApp()
console.log(appInstance.globalData) // I am global data
App()
内的函数中,或调用 App
前调用 getApp()
,使用 this
就可以拿到 app 实例。getApp()
获取实例之后,不要私自调用生命周期函数。js
文件中使用Page构造方法进行注册,指定页面的初始数据、生命周期回调、事件处理函数等。Page({
/**
\* 页面的初始数据
*/
data: {
},
/**
\* 生命周期函数--监听页面加载
*/
onLoad: function (options) {
console.log("index load")
},
/**
\* 生命周期函数--监听页面初次渲染完成
*/
onReady: function () {
console.log("index ready")
},
/**
\* 生命周期函数--监听页面显示
*/
onShow: function () {
console.log("index show")
},
/**
\* 生命周期函数--监听页面隐藏
*/
onHide: function () {
console.log("index hide")
},
/**
\* 生命周期函数--监听页面卸载
*/
onUnload: function () {
console.log("index unload")
},
/**
\* 页面相关事件处理函数--监听用户下拉动作
*/
onPullDownRefresh: function () {
console.log("下拉刷新")
},
/**
\* 页面上拉触底事件的处理函数
*/
onReachBottom: function () {
console.log("加载更多")
},
/**
\* 用户点击右上角分享
*/
onShareAppMessage: function () {
}
})
//修改数据
this.setData({
num:2
})
data: {
name:"zhangsan",
age:"18"
},
/**
\* 生命周期函数--监听页面加载
*/
onLoad: function (options) {
this._login()
},
_login:function(){
console.log("login ok")
},
_fn:function(){
this.setData({
age:2
})
},
// pages/demo1/demo1.js
Page({
/**
* 页面的初始数据
*/
data: {
num:1,
},
//页面的下拉刷新,必须先把enablePullDownRef开启才可以出发该事件函数
onPullDownRefresh(){
console.log("demo1的下拉刷新")
this.setData({
num:2
})
console.log(this)
},
//默认是距离底部有50px的时候,触发该函数,如果想改变距离,设置onReachBottomDistance就可以
onReachBottom(){
console.log("demo1的上拉刷新")
},
// 页面滑动事件
onPageScroll(e){
console.log("页面的滚动事件",e)
}
})
注意:请只在需要的时候才在 page 中定义此方法,不要定义空方法。以减少不必要的事件派发对渲染层-逻辑层通信的影响。 注意:请避免在 onPageScroll 中过于频繁的执行 setData
等引起逻辑层-渲染层通信的操作。尤其是每次传输大量数据,会影响通信耗时。
App.onLaunch
的时候调用 getCurrentPages()
,此时 page
还没有生成。
<view> {
{msg}} view>
<view id="{
{ID}}">view>
<view hidden="{
{ false }}">主人下马客在船view>
<view>{
{1+2+num}}view>
<view>{
{1+2+"3"}}view>
<view>{
{1+"2"+3}}view>
<view>{
{ store>=60?"及格":"不及格" }}view>
<view>{
{arr[0]}}view>
<view>{
{arr[1]}}view>
<view>{
{arr[2]}}view>
<view>
{
{obj.name}}------{
{obj.text}}
view>
<view>view>
<view wx:for="{
{[1,2,3,4]}}" wx:key="*this">
{
{index}}-------{
{item}}
view>
<view wx:for="{
{arr}}" wx:for-item="item1" wx:for-index="index1" wx:key="*this" >
{
{index1}}-------{
{item1}}
{
{index}}
view>
<view wx:for="{
{arr}}" wx:key="index">
{
{index}}-----{
{item}}
view>
<text>pages/demo2/demo2.wxmltext>
<view wx:for="{
{obj}}" wx:key="*this">
{
{index}}------ {
{item}}
view>
<view wx:for="{
{goods}}" wx:key="id">
{
{index}}-----{
{item.id}}-----{
{item.name}}------{
{item.price}}
view>
<view wx:for=" {
{[1,2,3]}}">
{
{item}}
view>
<view wx:for="[1,2,3]">
{
{item}}
view>
<view>
<block wx:for="{
{arr}}">
{
{item}}
block>
view>
<text>pages/demo3/demo3.wxmltext>
<view wx:if="{
{store>=60}}">及格view>
<view wx:if="{
{store>=80}}">优秀view>
<view wx:elif="{
{store>=60}}">中等view>
<view wx:else>不及格view>
<view hidden="{
{false}}">内容view>
<view wx:if="{
{false}}">内容一view>
<view>{
{
name}}</view>
<view>{
{
age}}</view>
<view data-title="{
{title}}">{
{
age}}</view>
{ {}}
<checkbox checked="{
{false}}"></checkbox>
<view data-title="{
{title}}">{
{
age+1}}</view>
<checkbox checked="{
{age<20}}"></checkbox>
<view>{
{
name+"三"}}</view>
<view>{
{
arr[0]}}</view>
<view>{
{
user.height}}</view>
<view class="{
{age>18?'red':'blue'}}">{
{
user.height}}</view>
data: {
name:"zhangsan",
age:17,
title:"我是标题",
arr:[1,2,3],
user:{
height:180,
weight:"150"
},
goods:[{
id:1,
name:"小米"
},{
id:2,
name:"华为"
}],
string:"abcdefg"
},
<view>--------遍历数组-----------</view>
<view wx:for="{
{arr}}" wx:key="*this">
{
{
index}}---{
{
item}}
</view>
<view wx:for="{
{arr}}" wx:key="*this" wx:for-item="vo" wx:for-index="key">
{
{
key}}---{
{
vo}}
</view>
<view>--------遍历对象-----------</view>
<view wx:for="{
{user}}" wx:key="*this">
{
{
index}}---{
{
item}}
</view>
<view wx:for="{
{user}}" wx:key="*this" wx:for-item="vo" wx:for-index="key">
{
{
key}}---{
{
vo}}
</view>
<view>--------遍历数组对象-----------</view>
<view wx:for="{
{goods}}" wx:key="*this">
{
{
index}}---{
{
item.id}}---{
{
item.name}}
</view>
<view>--------遍历字符串-----------</view>
<view wx:for="{
{string}}" wx:key="*this">
{
{
index}}---{
{
item}}
</view>
<view>--------遍历数字-----------</view>
<view wx:for="{
{10}}" wx:key="*this">
{
{
index}}---{
{
item}}
</view>
<block wx:for="{
{goods}}" wx:key="*this">
<view>{
{
item.id}}</view>
<view>{
{
item.name}}</view>
</block>
wx:key
来指定列表中项目的唯一的标识符。wx:key
的值以两种形式提供
*this
代表在 for 循环中的 item 本身,这种表示需要 item 本身是一个唯一的字符串或者数字。wx:key
,会报一个 warning
, 如果明确知道该列表是静态,或者不必关注其顺序,可以选择忽略。<view wx:if="{
{age>=18}}">成年</view>
<view wx:if="{
{age>=18}}">成年</view>
<view wx:else>未成年</view>
<view wx:if="{
{age>=18}}">成年</view>
<view wx:elif="{
{age>=15}}">青少年</view>
<view wx:else>少年</view>
wx:if
之中的模板也可能包含数据绑定,所以当 wx:if
的条件值切换时,框架有一个局部渲染的过程,因为它会确保条件块在切换时销毁或重新渲染。wx:if
也是惰性的,如果在初始渲染条件为 false
,框架什么也不做,在条件第一次变成真的时候才开始局部渲染。hidden
就简单的多,组件始终会被渲染,只是简单的控制显示与隐藏。wx:if
有更高的切换消耗而 hidden
有更高的初始渲染消耗。因此,如果需要频繁切换的情景下,用 hidden
更好,如果在运行时条件不大可能改变则 wx:if
较好。name="名字"
is="相对应的模板名字"
<import src="/pages/template/header.wxml">import>
<template is="myheader">template>
要在模板中定义
<text>pages/demo4/demo4.wxmltext>
<template name="mytem1">
<view>姓名:{
{name}}view>
<view>年龄:{
{age}}view>
template>
<template is="mytem1" data="{
{name:'张三',age:30}}">template>
<template is="mytem1" data="{
{name:'李四',age:60}}">template>
<template is="mytem1" data="{
{name:obj.name,age:obj.age}}">template>
<template is="mytem1" data="{
{ obj }}">template>
include 可以将目标文件除了 <template/> <wxs/> 外的整个代码引入,相当于是拷贝到 include 位置
import可以在该文件中使用目标文件定义的template
import引的是模板 inclue引入的是普通的组件
设计稿的元素宽度2px/设计稿的宽度750px = 设计布局的宽度2rpx/设备的宽度750rpx
设计稿的元素宽度2px/设计稿的宽度640px = 设计布局的宽度2rpx/设备的宽度750rpx
/* pages/demo6/demo6.wxss */
@import "/common/my.wxss";
.box{
width: 100rpx;
height: 100rpx;
background-color: red;
}
<template name="head">
<view>我是页面的头部</view>
</template>
<template name="foot">
<view>我是页面的底部</view>
</template>
<template is="head"></template>
<view>我是cate</view>
<template is="foot"></template>
data: {
style:"style1",
temp:{
nav:[{
id:1,
name:"男装"
},{
id:2,
name:"女装"
}],
name:"aaa"
}
},
<template name="style1">
<view class="nav1">
<view wx:for="{
{nav}}">{
{
item.name}}</view>
<view>{
{
name}}</view>
</view>
</template>
<template is="{
{style}}" data="{
{...temp}}"></template>
import
和include
。只引入目标文件中的template模板
,其余的一概不引入<import src="/template/template.wxml"/>
template
,在B中可以使用A定义的template
,但是C不能使用A定义的template
。include
可以将目标文件除了
外的整个代码引入,相当于是拷贝到 include
位置<include src="/template/template.wxml" />
规定屏幕宽为750rpx
。如在 iPhone6 上,屏幕宽度为375px,共有750个物理像素,则750rpx = 375px = 750物理像素,1rpx = 0.5px = 1物理像素。设备 | rpx换算px (屏幕宽度/750) | px换算rpx (750/屏幕宽度) |
---|---|---|
iPhone5 | 1rpx = 0.42px | 1px = 2.34rpx |
iPhone6 | 1rpx = 0.5px | 1px = 2rpx |
iPhone6 Plus | 1rpx = 0.552px | 1px = 1.81rpx |
@import
语句可以导入外联样式表,@import
后跟需要导入的外联样式表的相对路径,用;
表示语句结束。@import "../../common/cart.wxss";
<view style="color:{
{color}};font-weight:bold">nihao</view>
.
,样式类名之间用空格分隔。<view class="red {
{color}}">nihao</view>
选择器 | 样例 | 样例描述 |
---|---|---|
.class | .intro |
选择所有拥有 class=“intro” 的组件 |
#id | #firstname |
选择拥有 id=“firstname” 的组件 |
element | view |
选择所有 view 组件 |
element, element | view, checkbox |
选择所有文档的 view 组件和所有的 checkbox 组件 |
::after | view::after |
在 view 组件后边插入内容 |
::before | view::before |
在 view 组件前边插入内容 |
https://developers.weixin.qq.com/miniprogram/dev/framework/view/wxml/event.html
bind+事件类型 = "函数名"
或者使用catch+事件类型 = "函数名"
来绑定事件<view bindtap="_fn1">事件1</view>
<view catchtap="_fn2">事件1</view>
箭头函数拿不到this 建议在写事件函数的不要用箭头函数
_fn1:function(){
console.log("我被触发了fn1")
},
_fn2(){
console.log("我被触发了fn2")
},
//将this重新赋值
let money=[10,20,30]
let that=this
let new_money=money.map(function(item){
return item+that.data.add
})
console.log(new_money)
//使用箭头函数
let money=[10,20,30]
let new_money=money.map((item)=>{
return item+this.data.add
})
console.log(new_money)
冒泡事件,非冒泡事件
冒泡事件
类型 | 触发条件 | 最低版本 |
---|---|---|
touchstart | 手指触摸动作开始 | |
touchmove | 手指触摸后移动 | |
touchcancel | 手指触摸动作被打断,如来电提醒,弹窗 | |
touchend | 手指触摸动作结束 | |
tap | 手指触摸后马上离开 | |
longpress | 手指触摸后,超过350ms再离开,如果指定了事件回调函数并触发了这个事件,tap事件将不被触发 | 1.5.0 |
longtap | 手指触摸后,超过350ms再离开(推荐使用longpress事件代替) |
除上表之外的其他组件自定义事件如无特殊声明都是非冒泡事件,如 form 的submit
事件,input 的input
事件,scroll-view 的scroll
事件
<view class="father" catchtap="_fn1">
<view class="son" catchtap="_fn2"></view>
</view>
type
:什么事件触发的。touches
:事件发生的位置,detail
:子组件传递过来的数据就放在detail。currentTarget
:事件绑定的元素。target
:事件触发的元素。id
接参 e.target.id
e.currentTaget.id
data-*(自定义的参数名)
接参 e.target.dataset.id
e.currentTarget.dataset.id
<view class="father" data-user-sex="男" data-name="zhangsan" data-age="18" catchtap="_fn1">
<view class="son" catchtap="_fn2"></view>
</view>
//推荐使用的传参方式,参数名称比如data-user-sex====>userSex//传递的参数可以是对象/数组
https://developers.weixin.qq.com/miniprogram/dev/component/swiper.html
开始标签
和 结束标签
,属性
用来修饰这个组件,内容
在两个标签之内。<tagname property="value">
Content goes here ...
tagname>
-
连接类型 | 描述 | 注解 |
---|---|---|
Boolean | 布尔值 | 组件写上该属性,不管是什么值都被当作 true ;只有组件上没有该属性时,属性值才为false 。 如果属性值为变量,变量的值会被转换为Boolean类型 |
Number | 数字 | 1 , 2.5 |
String | 字符串 | "string" |
Array | 数组 | [ 1, "string" ] |
Object | 对象 | { key: value } |
EventHandler | 事件处理函数名 | "handlerName" 是 Page 中定义的事件处理函数名 |
Any | 任意属性 |
属性名 | 类型 | 描述 | 注解 |
---|---|---|---|
id | String | 组件的唯一标示 | 保持整个页面唯一 |
class | String | 组件的样式类 | 在对应的 WXSS 中定义的样式类 |
style | String | 组件的内联样式 | 可以动态设置的内联样式 |
hidden | Boolean | 组件是否显示 | 所有组件默认显示 |
data-* | Any | 自定义属性 | 组件上触发的事件时,会发送给事件处理函数 |
bind* / catch* | EventHandler | 组件的事件 | 详见事件 |
<icon type="success" size="50" color="#ff0000"></icon>
<icon type="success_no_circle" ></icon>
<icon type="info" ></icon>
<icon type="warn" ></icon>
<icon type="waiting" ></icon>
<icon type="download" ></icon>
<progress bindactiveend="_fn1" active="{
{true}}" percent="40" stroke-width="10" show-info="{
{true}}"></progress>
<view>
<text user-select="{
{true}}" space="ensp">文本 内容text>
view>
<view>
<text user-select="{
{true}}" space="nbsp">文本 内容text>
view>
<view>
<text user-select="{
{true}}" space="nbsp" decode="{
{true}}">文本>内容text>
view>
<text decode="{
{true}}" space="ensp" user-select="{
{true}}">{
{
goods_info}}</text>
nodes 节点列表string/array
string形式
<rich-text nodes="二级标题
">rich-text>
array形式
arr:[
{
// <h2 class="box1">二级标题数组h2>
// 标签名是节点node 标签内容是text
//节点类型
type:"node",
name:"h2", //标签名
attrs:{class:"box1"}, //标签身上的属性
children:[
{
type:"text",
text:"二级标题数组"
}
]
}
]
<rich-text nodes="{
{goods_info}}"></rich-text>
<view class="box" hover-class="active" hover-start-time="2000" hover-stay-time="5000">view>
<view class="out" hover-class="out-active">
<view class="inser" hover-class="inser-active" hover-stop-propagation="{
{true}}">view>
view>
<view id="father" hover-class="blue">
<view hover-stop-propagation="{
{true}}" id="son" hover-class="red">我是son</view>
</view>
<text>pages/demo04/demo04.wxmltext>
<swiper
indicator-dots="{
{true}}"
indicator-color="#ccc"
indicator-active-color="#f00"
autoplay="{
{true}}"
interval="1000"
circular="{
{true}}"
current="2"
vertical="{
{false}}"
previous-margin="50px"
next-margin="50px"
bindchange="_change"
>
<block wx:for="{
{arrImage}}">
<swiper-item>
<image src="{
{item}}">image>
swiper-item>
block>
swiper>
<swiper
indicator-dots="{
{true}}"
autoplay="{
{true}}"
current="2"
interval="2000"
circular="{
{true}}"
bindchange="_changeImg"
\>
<swiper-item><image src="/static/banners/1.jpg" /></swiper-item>
<swiper-item><image src="/static/banners/2.jpg" /></swiper-item>
<swiper-item><image src="/static/banners/3.jpg" /></swiper-item>
</swiper>
<text>pages/demo05/demo05.wxmltext>
<view class="banner">
<swiper
autoplay
interval="2000"
circular
bindchange="_change"
>
<swiper-item wx:for="{
{arr}}">
<image src="{
{item}}">image>
swiper-item>
swiper>
<view class="dots">
<text wx:for="{
{arr}}" class="{
{ index==_currentIndex?'active':'' }}" >text>
view>
view>
/* pages/demo05/demo05.wxss */
image{
width: 100%;
height: 100%;
}
.banner{
position: relative;
}
.dots{
position: absolute;
left: 0;
bottom: 0;
width: 100%;
text-align: center;
}
.dots text{
width: 40rpx;
height: 20rpx;
display: inline-block;
background: #ccc;
margin-left: 10rpx;
}
.dots .active{
background-color: red;
}
// pages/demo05/demo05.js
Page({
/**
* 页面的初始数据
*/
data: {
arr:[
"/logo/1.jpg",
"/logo/2.jpg",
"/logo/3.jpg",
],
_currentIndex:0,
num:1
},
_change(e){
// console.log(e.detail.current)
// 异步
this.setData({
_currentIndex:e.detail.current,
},function(){
// console.log(this.data.num++)
})
// 如果变量经过赋值改变之后,要渲染在视图层,建议写setdata进行改变值
// 如果变量只在js文件中使用,可以直接进行赋值,不需要再setdata里面改变
console.log( this.data.num++)
}
})
<view class="container">
<swiper autoplay="{
{true}}" bindchange="_changeImg">
<swiper-item wx:for="{
{banner}}" wx:key="*this">
<image class="img" src="/static/banners/{
{item}}" />
</swiper-item>
</swiper>
<view class="dots">
<text class="{
{index==currentIndex?'active':''}}" wx:for="{
{banner}}" wx:key="*this"></text>
</view>
</view>
/* pages/swiper/swiper.wxss */
.container{
position: relative;
}
.container .dots{
width: 100%;
position: absolute;
bottom: 20rpx;
text-align: center;
}
.dots text{
display: inline-block;
width:20rpx;
height:8rpx;
margin-left:10rpx;
background-color:#333;
}
text.active{
background-color: blue;
}
.img{
width: 100%;
}
/**
\* 页面的初始数据
*/
data: {
banner:["1.jpg","2.jpg","3.jpg"],
currentIndex:0
},
_changeImg:function(e){
this.setData({
currentIndex:e.detail.current
})
},
<text>pages/demo06/demo06.wxmltext>
<view class="classify">
<scroll-view class="classify_l" scroll-y="{
{true}}" >
<view wx:for="{
{arr}}" class="title" bindtap="_change" data-index="{
{index}}">{
{item.title}}view>
scroll-view>
<scroll-view class="classify_r" scroll-y="{
{true}}" scroll-into-view="carid{
{_currentIndex}}">
<view wx:for="{
{arr}}" id="carid{
{index}}" >
<view class="secTitle" >{
{item.title}}view>
<view wx:for="{
{item.goods}}" wx:for-item="item1" >{
{item1.text}}view>
view>
scroll-view>
view>
_change(e){
console.log(e.target.dataset.index)
this.setData({
_currentIndex:e.target.dataset.index
})
},
<!--横向滚动-->
<scroll-view class="scroll-x" scroll-x="{
{true}}">
<view>分类1</view>
<view>分类1</view>
<view>分类1</view>
<view>分类1</view>
<view>分类1</view>
<view>分类1</view>
<view>分类1</view>
<view>分类1</view>
<view>分类1</view>
<view>分类1</view>
<view>分类1</view>
</scroll-view>
<!--纵向滚动-->
<scroll-view class="scroll-y" scroll-y="{
{true}}">
<view>分类1</view>
<view>分类1</view>
<view>分类1</view>
<view>分类1</view>
<view>分类1</view>
<view>分类1</view>
<view>分类1</view>
<view>分类1</view>
<view>分类1</view>
<view>分类1</view>
<view>分类1</view>
</scroll-view>
/* pages/scroll/scroll.wxss */
.scroll-x{
white-space: nowrap;
}
.scroll-x view {
display: inline-block;
padding:10rpx;
background-color: #ccc;
margin:0rpx 10rpx;
}
.scroll-y{
height:600rpx;
width:400rpx;
border:1rpx solid #ccc
}
.scroll-y view {
width: 400rpx;
height:270rpx;
background-color: #ccc;
margin-bottom: 10rpx;
}
<view class="container">
<scroll-view class="left" scroll-y="{
{true}}">
<view bindtap="_scrollview" data-cate="cate1">分类1</view>
<view bindtap="_scrollview" data-cate="cate2">分类2</view>
<view bindtap="_scrollview" data-cate="cate3">分类3</view>
<view bindtap="_scrollview" data-cate="cate4">分类4</view>
<view bindtap="_scrollview" data-cate="cate5">分类5</view>
<view bindtap="_scrollview" data-cate="cate6">分类6</view>
<view bindtap="_scrollview" data-cate="cate7">分类7</view>
<view bindtap="_scrollview" data-cate="cate8">分类8</view>
</scroll-view>
<scroll-view class="right" scroll-y="{
{true}}" scroll-into-view="{
{view}}">
<view id="cate1">
<text>分类1子分类</text>
<text>分类1子分类</text>
<text>分类1子分类</text>
<text>分类1子分类</text>
</view>
<view id="cate2">
<text>分类2子分类</text>
<text>分类2子分类</text>
<text>分类2子分类</text>
<text>分类2子分类</text>
</view>
<view id="cate3">
<text>分类3子分类</text>
<text>分类3子分类</text>
<text>分类3子分类</text>
<text>分类3子分类</text>
</view>
<view id="cate4">
<text>分类4子分类</text>
<text>分类4子分类</text>
<text>分类4子分类</text>
<text>分类4子分类</text>
</view>
<view id="cate5">
<text>分类5子分类</text>
<text>分类5子分类</text>
<text>分类5子分类</text>
<text>分类5子分类</text>
</view>
<view id="cate6">
<text>分类6子分类</text>
<text>分类6子分类</text>
<text>分类6子分类</text>
<text>分类6子分类</text>
</view>
<view id="cate7">
<text>分类7子分类</text>
<text>分类7子分类</text>
<text>分类7子分类</text>
<text>分类7子分类</text>
</view>
<view id="cate8">
<text>分类8子分类</text>
<text>分类8子分类</text>
<text>分类8子分类</text>
<text>分类8子分类</text>
</view>
</scroll-view>
</view>
data: {
view:"cate1"
},
_scrollview:function(e){
let {
cate}=e.currentTarget.dataset
this.setData({
view:cate
})
},
/* pages/scroll-view/scroll-view.wxss */
.container{
display: flex;
height:800rpx;
}
.left{
width:200rpx;
height:800rpx;
}
.left view{
height:120rpx;
line-height: 120rpx;
text-align: center;
margin-bottom:20rpx;
background-color: #ccc;
}
.right{
width:550rpx;
height:800rpx;
}
.right view{
width: 550rpx;
height:400rpx;
background-color: #ccc;
margin-bottom:20rpx;
}
.right view text{
display: inline-block;
padding: 20rpx;
margin:10rpx;
background-color: #fff;
}
<image src="/static/erha1.jpg" lazy-load="{
{true}}" bindload="_load" />
<!--
binderror 图片资源加载不成功
bindload 图片资源加载成功
lazy-load 懒加载
show-menu-by-longpress 只识别小程序二维码
-->
<image src="/logo/1.jpg" binderror="_error" bindload="_load" lazy-load="{
{true}}"></image>
<form bindsubmit="_submit">
<view class="box">
<view class="title">请填写以下信息view>
<view>
<view>姓名view>
<input type="idcard" placeholder="请输入姓名" name="name1" />
view>
<view>
<view>联系方式view>
<input type="idcard" placeholder="请输入姓名" name="tel"/>
view>
<radio-group bindchange="_change1" name="sex">
<view>
<radio value="0">男radio>view>
<view>
<radio value="1">女radio>
view>
<view>
<radio value="2">保密radio>
view>
radio-group>
<view>
<view>您的爱好是view>
<checkbox-group bindchange="_changeHobby" name="hobby">
<view>
<checkbox value="吃饭">吃饭checkbox>
view>
<view>
<checkbox value="睡觉">睡觉checkbox>
view>
<view>
<checkbox value="打豆豆">打豆豆checkbox>
view>
checkbox-group>
view>
<view>
<view>是否同意view>
<switch type="checkbox" name="isArr">switch>
view>
<view>
<button size="mini" type="primary" form-type="submit">提交button>
<button size="mini" form-type="reset">重置button>
view>
view>
form>
注意
<!--pages/form/form.wxml-->
<view class="page">
<form bindsubmit="_submit" bindreset="_reset">
<view class="title">请填写问卷调查</view>
<view>
<label>姓名</label>
<input class="input" type="text" placeholder="请填写姓名" name="name" bindinput="_inputName"></input>
</view>
<view>
<label>联系方式</label>
<input class="input" type="number" placeholder="请填写手机号码" name="tel" maxlength="11" bindinput="_inputPhone"></input>
</view>
<view>
<label>性别</label>
<radio-group name="sex" bindchange="_inputSex">
<view>
<radio checked="{
{true}}" value="男">男</radio>
</view>
<view>
<radio color="#ff0000" value="女">女</radio>
</view>
<view>
<radio disabled="{
{true}}" value="保密">保密</radio>
</view>
</radio-group>
</view>
<view>
<label>你的爱好</label>
<checkbox-group name="hobby" bindchange="_inputHobby">
<view>
<checkbox checked="{
{true}}" value="抽烟">抽烟</checkbox>
</view>
<view>
<checkbox color="#00ff00" value="喝酒">喝酒</checkbox>
</view>
<view>
<checkbox disabled="{
{true}}" value="烫头">烫头</checkbox>
</view>
</checkbox-group>
</view>
<view>
<label>您是否同意我们联系你</label>
<view>
<switch name="agree" type="checkbox" bindchange="_inputAgree">同意</switch>
</view>
</view>
<view>
<label>请给我们的服务打分</label>
<view>
<slider name="score" show-value="{
{true}}" value="60" min="0" max="100" bindchange="_inputScore"></slider>
</view>
</view>
<view>
<label>你喜欢的运动</label>
<picker range="{
{arr}}" name="sport" value="{
{index}}" range-key="name" bindchange="_inputSport">
<view>你的选择是:{
{
arr[index].name}}</view>
</picker>
</view>
<view>
<label>你喜欢的时间</label>
<picker mode="region">
<view>开始时间:</view>
</picker>
</view>
<view class="btn">
<button type="primary" form-type="submit" size="mini" >提交</button>
<button type="warn" form-type="reset" size="mini">重置</button>
</view>
</form>
</view>
/* pages/form/form.wxss */
.page{
padding: 10rpx;
}
.page view{
margin:15rpx;
}
.title{
height:80rpx;
line-height: 80rpx;
padding-left: 10rpx;
font-weight: bold;
color:#fff;
background-color: orangered;
}
view label{
font-size: 36rpx;
font-weight: bold;
}
.input{
height:80rpx;
border:1rpx solid #ccc;
margin-top:10rpx;
border-radius: 10rpx;
padding-left: 10rpx;
}
data: {
name:"",
tel:"",
sex:"男",
hobby:[],
agree:false,
score:60,
arr:[{
id:1,
name:"有氧运动"
},{
id:2,
name:"无氧运动"
}],
index:0
},
_submit:function(e){
console.log(e)
},
_inputSport:function(e){
this.setData({
index:e.detail.value
})
},
_inputName:function(e){
this.setData({
name:e.detail.value
})
},
_inputPhone:function(e){
this.setData({
tel:e.detail.value
})
},
_inputSex:function(e){
this.setData({
sex:e.detail.value
})
},
_inputHobby:function(e){
this.setData({
hobby:e.detail.value
})
},
_inputAgree:function(e){
this.setData({
agree:e.detail.value
})
},
_inputScore:function(e){
this.setData({
score:e.detail.value
})
},
值 | 说明 | 最低版本 |
---|---|---|
self | 当前小程序 | |
miniProgram | 其它小程序 |
<text>pages/demo1/demo1.wxmltext>
<navigator url="/pages/homework/homework?id=121344&name='作业'" target="self">
<button>组件跳转----indexbutton>
navigator>
<navigator target="self" url="../detail/detail" open-type="navigate" >跳转到商品详情</navigator>
场景:电子商城 首页—分类—商品列表–详情(还可以返回)
redirect临时重定向)不保留当前的页面栈,新的页面会入栈。
<navigator target="self" url="../detail/detail" open-type="redirect" >跳转到商品详情</navigator>
<navigator target="self" url="../cart/cart" open-type="switchTab">跳转cart</navigator>
应用场景:只能用于跳转tabbar页面
reLaunch永久重定向),所有的页面会出栈,新页面入栈
<navigator target="self" url="../goodslist/goodslist" open-type="reLaunch">跳转列表</navigator>
应用场景:支付完成后跳转。
navigateBack:返回的页面,返回一次,页面就出栈一次。
<navigator target="self" open-type="navigateBack" delta="2">返回</navigator>
<button bindtap="_goHome">跳转页面----APIbutton>
_goHome(){
wx.navigateTo({
url: '/pages/homework/homework',
success:(res)=>{
console.log(res)
// 逻辑
},
fail:(err)=>{
console.log(err)
},
// 无论成功或者失败,都会执行的回调函数
complete:(res)=>{
console.log(res)
}
})
},
<navigator target="self" url="../detail/detail?id=1&name=小米&price=100" open-type="navigate" >小米手机</navigator>
_goDetail:function(){
wx.navigateTo({
url: '../detail/detail?id=2&name=华为&price=80000',
})
},
onLoad: function (options) {
console.log(options)
},
<navigator target="miniProgram" app-id="wx6acf0caf71cb5860">星座和运势</navigator>
const name='swk'
const say=()=>{
console.log("say")
}
export {
name,
say
}
import {
name,say} from '../../utils/tool'
const name='swk'
const say=()=>{
console.log("saying")
}
export default {
name,
say
}
import tool from '../../utils/tool'
console.log(tool.name)
const name='swk'
const say=()=>{
console.log("saying")
}
module.exports={
name,
say
}
const tool=require("../../utils/tool")
console.log(tool.name)
tool.say()
// components/test/test.js
Component({
/**
\* 组件的属性列表,外部传递的值
*/
properties: {
},
/**
\* 组件的初始数据,组件的内部的值
*/
data: {
},
/**
\* 组件的方法列表,组件的方法
*/
methods: {
}
})
{
"component": true, //说明这是一个组件
"usingComponents": {
} //注册组件用的
}
"usingComponents": {
"my-test":"/components/test/test"
},
<my-test />
<my-test></my-test>
properties: {
name:{
type:'String',
value:""
},
age:{
type:'Number',
value:18
}
},
<view>
我是{
{
name}}我的年龄:{
{
age}}
</view>
<my-test name="zhangsan" age="18" />
<my-test name="lisi"></my-test>
<my-test name="zhangsan" age="18" bindget="_getUser" />
<my-test name="lisi"></my-test>
methods: {
_hander:function()
this.triggerEvent("get",{
name:"hello"+this.properties.name,age:this.properties.age+1})
}
}
<my-test name="zhangsan" age="18" bindget="_getUser" />
_getUser:function(e){
console.log(e)
},
<view bindtap="_hander">
我是{
{
name}}我的年龄:{
{
age}}
<slot></slot>
</view>
<my-test name="lisi">
<view>我是默认的插槽</view>
</my-test>
Component({
options: {
multipleSlots: true // 在组件定义时的选项中启用多slot支持
},
properties: {
/* ... */ },
methods: {
/* ... */ }
})
<view>
<slot name="header"></slot>
<view>我是{
{
name}}</view>
<slot></slot>
<view>我的年龄:{
{
age}}</view>
<slot name="footer"></slot>
</view>
<my-test name="lisi">
<view slot="header">我是头部的插槽</view>
<view>我是默认的插槽</view>
<view slot="footer">我是底部的插槽</view>
</my-test>
Component({
lifetimes: {
attached: function() {
// 在组件实例进入页面节点树时执行
},
detached: function() {
// 在组件实例被从页面节点树移除时执行
},
},
// 以下是旧式的定义方式,可以保持对 <2.2.3 版本基础库的兼容
attached: function() {
// 在组件实例进入页面节点树时执行
},
detached: function() {
// 在组件实例被从页面节点树移除时执行
},
// ...
})
app.wxss
或页面的 wxss
中使用了标签名选择器(或一些其他特殊选择器)来直接指定样式,这些选择器会影响到页面和全部组件。通常情况下这是不推荐的做法。尽量使用class选择器styleIsolation
默认就使用样式隔离。https://developers.weixin.qq.com/miniprogram/dev/framework/app-service/api.html
on
开头的 API 用来监听某个事件是否触发,如:wx.onSocketOpen,wx.onCompassChange 等。wx.onCompassChange(function (res) {
console.log(res.direction)
})
Sync
结尾的 API 都是同步 API, 如 wx.setStorageSync,wx.getSystemInfoSync 等。此外,也有一些其他的同步 API,如 wx.createWorker,wx.getBackgroundAudioManager 等,详情参见 API 文档中的说明。try {
wx.setStorageSync('key', 'value')
} catch (e) {
console.error(e)
}
Object
类型的参数,这个参数都支持按需指定以下字段来接收接口调用结果:参数名 | 类型 | 必填 | 说明 |
---|---|---|---|
success | function | 否 | 接口调用成功的回调函数 |
fail | function | 否 | 接口调用失败的回调函数 |
complete | function | 否 | 接口调用结束的回调函数(调用成功、失败都会执行) |
其他 | Any | - | 接口定义的其他参数 |
let info=wx.getSystemInfoSync()
console.log(info)
wx.getSystemInfo({
success:res=>{
console.log(res)
},
fail:err=>{
}
})
_show:function(){
wx.showToast({
title: '显示成功',
icon:"none",
duration:5000
})
},
_hide:function(){
wx.hideToast()
},
wx.showLoading({
title:"加载中"
})
wx.hideLoading()
wx.showModal({
title:"系统提示",
content:"请先完善个人信息",
confirmText:"前往",
cancelText:"放弃",
success:res=>{
console.log(res)
}
})
wx.showActionSheet({
alertText:"请选择",
itemList:["订单查询","联系客服","联系商家"],
success:res=>{
if(res.tapIndex==0){
}
if(res.tapIndex==1){
}
}
})
wx.setNavigationBarTitle({
title: '首页',
})
wx.setNavigationBarColor({
backgroundColor: '#00ff00',
frontColor: '#ffffff',
animation: {
duration: 400,
timingFunc: 'easeIn'
}
})
wx.showTabBarRedDot({
index: 2,
})
wx.setTabBarBadge({
index: 1,
text: '5',
})
wx.setBackgroundColor({
backgroundColor: '#0000ff',
})
wx.setStorageSync('name', "zhangsan")
wx.setStorageSync('userinfo',{
age:18,
sex:1
})
wx.setStorage({
data:{
id:1,
goods_name:"小米"
},
key: 'goods',
})
wx.clearStorage()
wx.clearStorageSync()
wx.getStorage({
key: 'userinfo',
success:res=>{
console.log(res)
}
})
let goods= wx.getStorageSync('goods')
console.log(goods)
wx.getStorage({
key: 'userinfo',
success:res=>{
console.log(res)
}
})
let goods= wx.getStorageSync('goods')
console.log(goods)
_getProduct:function(){
wx.request({
url: 'http://localhost:3000/product',
method:"get",
data:{
id:1,
name:"zhansan"
},
header:{
"content-type":"application/x-www-form-urlencoded",
},
success:res=>{
console.log(res)
},
})
wx.request({
url: 'http://localhost:3000/login',
method:"post",
header:{
"content-type":"application/x-www-form-urlencoded",
},
data:{
tel:"12345",
pwd:"123"
},
success:res=>{
console.log(res)
}
})
},
GET
方法的数据,会将数据转换成 query string(encodeURIComponent(k)=encodeURIComponent(v)&encodeURIComponent(k)=encodeURIComponent(v)...
)POST
方法且 header['content-type']
为 application/json
的数据,会对数据进行 JSON 序列化POST
方法且 header['content-type']
为 application/x-www-form-urlencoded
的数据,会将数据转换成 query string (encodeURIComponent(k)=encodeURIComponent(v)&encodeURIComponent(k)=encodeURIComponent(v)...)
const baseUrl="http://localhost:3000"
const http=(option)=>{
return new Promise((resolve,reject)=>{
wx.request({
url:baseUrl+option.url,
method:option.method||"get",
data:option.data||{
},
header:option.header||{
"content-type":"application/x-www-form-urlencoded",
},
success:resolve,
fail:reject
})
})
}
export {
http
}
https://developers.weixin.qq.com/community/develop/article/doc/000ecc775a86807f7ba9b7dc956c13
"useExtendedLib": {
"weui": true
},
npm install weui-miniprogram
@import '/miniprogram_npm/weui-miniprogram/weui-wxss/dist/style/weui.wxss';
<!--pages/order/order.wxml-->
<mp-navigation-bar background="#ff0000" ext-class="nav" color="#ffffff" back="{
{false}}">
<view slot="center">
<mp-icon color="#ffffff" icon="search"></mp-icon>
订单查询
</view>
<view slot="left" class="back">
<text bindtap="_goIndex">首页</text>|<text>返回</text>
</view>
</mp-navigation-bar>
<mp-searchbar></mp-searchbar>
<mp-tabbar bindchange="_switchTab" list="{
{tab}}"></mp-tabbar>
<mp-cells title="订单的基本信息" footer="请仔细核对">
<mp-cell title="代付款" link="{
{true}}" footer="查看">
<image src="/static/icon/kf.png" slot="icon" />
</mp-cell>
<mp-cell title="更多" link="{
{true}}" footer="查看" bindtap="_showAction">
<image src="/static/icon/kf.png" slot="icon" />
</mp-cell>
</mp-cells>
<mp-actionSheet show="{
{show}}" actions="{
{groups}}"></mp-actionSheet>
data: {
tab:[{
text:"物流查询",
iconPath:"/static/icon/dd.png",
selectedIconPath:"/static/icon/ddFull.png"
},{
text:"物流查询",
iconPath:"/static/icon/dd.png",
selectedIconPath:"/static/icon/ddFull.png",
badge:"3"
},{
text:"物流查询",
iconPath:"/static/icon/dd.png",
selectedIconPath:"/static/icon/ddFull.png",
},{
text:"物流查询",
iconPath:"/static/icon/dd.png",
selectedIconPath:"/static/icon/ddFull.png",
}],
groups:[
{
text: '示例菜单', value: 1 },
{
text: '示例菜单', value: 2 },
{
text: '负向菜单', type: 'warn', value: 3 }
],
show:false
},
_goIndex:function(){
wx.switchTab({
url: '../index/index',
})
},
_switchTab:function(e){
if(e.detail.index==1){
}
},
_showAction:function(){
this.setData({
show:true
})
},
/* pages/order/order.wxss */
.back{
padding: 10rpx;
border:1rpx solid #ccc;
border-radius: 25rpx;
}
image{
width: 40rpx;
height: 40rpx;
}
{
"usingComponents": {
"mp-navigation-bar": "/miniprogram_npm/weui-miniprogram/navigation-bar/navigation-bar",
"mp-icon": "/miniprogram_npm/weui-miniprogram/icon/icon",
"mp-searchbar": "/miniprogram_npm/weui-miniprogram/searchbar/searchbar",
"mp-tabbar": "/miniprogram_npm/weui-miniprogram/tabbar/tabbar",
"mp-cells": "/miniprogram_npm/weui-miniprogram/cells/cells",
"mp-cell": "/miniprogram_npm/weui-miniprogram/cell/cell",
"mp-actionSheet": "/miniprogram_npm/weui-miniprogram/actionsheet/actionsheet"
},
"navigationStyle":"custom"
}
https://developers.weixin.qq.com/miniprogram/dev/framework/subpackages.html
subpackages
字段声明项目分包结构:"subPackages": [{
"root":"animate",
"pages":[
"pages/cat/cat",
"pages/dog/dog"
]
},{
"root":"firut",
"pages":[
"pages/orange/orange",
"pages/pear/pear"
]
}],
subpackages
后,将按 subpackages
配置路径进行打包,subpackages
配置路径外的目录将被打包到 app(主包) 中subpackage
的根目录不能是另外一个 subpackage
内的子目录tabBar
页面必须在 app(主包)内packageA
无法 require packageB
JS 文件,但可以 require app
、自己 package 内的 JS 文件packageA
无法 import packageB
的 template,但可以 require app
、自己 package 内的 templatepackageA
无法使用 packageB
的资源,但可以使用 app
、自己 package 内的资源subpackage
里面的路径放到 pages 中。"subPackages": [{
"root":"animate",
"pages":[
"pages/cat/cat",
"pages/dog/dog"
],
"independent": true
},{
"root":"firut",
"pages":[
"pages/orange/orange",
"pages/pear/pear"
]
}],
app.wxss
对独立分包无效,应避免在独立分包页面中使用 app.wxss
中的样式;App
只能在主包内定义,独立分包中不能定义 App
,会造成无法预期的行为;App
并不一定被注册,因此 getApp()
也不一定可以获得 App
对象:
App
也不存在,此时调用 getApp()
获取到的是 undefined
。 当用户进入普通分包或主包内页面时,主包才会被下载,App
才会被注册。getApp()
可以获取到真正的 App
。https://developers.weixin.qq.com/miniprogram/dev/framework/runtime/operating-mechanism.html
https://developers.weixin.qq.com/miniprogram/dev/framework/runtime/update-mechanism.html
user
id account pwd phone email
1 zhangsan 123 15155525032
user_grant
id type(接入第三方平台的类型) header_url openid user_id
1 qq 1234ab
2 weibo sdfgh
3 微信 sdsakdfsakd
4 微信小程序 hdhdhdhdhd 1
if(查到){
if(user_id为空){
//重新绑定跳转到绑定界面----输入原来账号密码----进行绑定----修改user_grant下面的数据---生成token
}else{
//直接使用user_id-----token
}
}else{
//第一次使用qq登录,进行插入操作--成功后跳转到绑定界面----输入原来账号密码----进行绑定----修改下面的数据---生成token
}
_login:function(){
wx.login({
success:res=>{
let code=res.code
wx.request({
url: 'http://localhost:3000/login',
method:"get",
data:{
code:code
},
success:res=>{
console.log(res)
wx.setStorageSync("token",res.data.token)
this.setData({
isLogin:true
})
}
})
}
})
},
scope
,用户选择对 scope
来进行授权,当授权给一个 scope
之后,其对应的所有接口都可以直接使用。<button wx:if="{
{!userInfo}}" type="primary" open-type="getUserInfo" bindgetuserinfo="_getUserInfo">一键授权登录</button>
_getUserInfo:function(e){
if(e.detail.userInfo){
this.setData({
userInfo:e.detail.userInfo
})
}
},
wx.getSetting({
//获取用授权的scope
withSubscriptions: true,
success:res=>{
if(res.authSetting["scope.userInfo"]){
wx.getUserInfo({
success:res=>{
this.setData({
userInfo:res.userInfo
})
}
})
}
}
})
能力 | 作用 | 说明 |
---|---|---|
云函数 | 无需自建服务器 | 在云端运行的代码,微信私有协议天然鉴权,开发者只需编写自身业务逻辑代码 |
数据库 | 无需自建数据库 | 一个既可在小程序前端操作,也能在云函数中读写的 JSON 数据库 |
存储 | 无需自建存储和 CDN | 在小程序前端直接上传/下载云端文件,在云开发控制台可视化管理 |
云调用 | 原生微信服务集成 | 基于云函数免鉴权使用小程序开放接口的能力,包括服务端调用、获取开放数据等能力 |
"miniprogramRoot": "miniprogram/", //小程序的目录
"cloudfunctionRoot": "cloudfunctions/", //云函数的目录
https://developers.weixin.qq.com/miniprogram/dev/wxcloud/billing/quota.html
关系型 | 文档型 |
---|---|
数据库 database | 数据库 database |
表 table | 集合 collection |
行 row | 记录 record / doc |
列 column | 字段 field |
onLaunch: function () {
if (!wx.cloud) {
console.error('请使用 2.2.3 或以上的基础库以使用云能力')
} else {
wx.cloud.init({
env: 'music-dev-wi2lv',
traceUser: true,
})
}
}
const db=wx.cloud.database()
db.collection(表名).add(data:{ 字段名:字段值,....},success:res=>{ })
db.collection(表名).add(data:{ 字段名:字段值,....}).then(res=>{ })
db.collection("test").add({
data:{
book_name:"西游记",
book_pirce:120,
book_author:"吴承恩",
book_tag:["神话","古装"]
},
success:res=>{
console.log(res)
}
})
db.collection("test").add({
data:{
book_name:"西游记",
book_pirce:1200,
book_author:"吴承恩",
book_tag:["神话","古装"]
}
}).then(res=>{
console.log(res)
})
db.collection(表名).where({ 匹配的字段名:字段值 }).remove().then(res=>{ })
_delete:function(){
db.collection("test").where({
book_pirce:1200
}).remove().then(res=>{
console.log(res)
})
},
API | 说明 |
---|---|
update | 局部更新一个或多个记录 |
set | 替换更新一个记录 |
db.collection(表名).doc("id值").update/set({data:{要更新的字段名:更新后的字段值}}).then(res=>{ })
db.collection("test")
.doc("21ded5cb5fe59586000dbef439a762df").update({
data:{
"book_name":"大话西游"
}
}).then(res=>{
console.log(res)
})
db.collection("test")
.doc("21ded5cb5fe59586000dbef439a762df").set({
data:{
"book_name":"大话西游"
}
}).then(res=>{
console.log(res)
})
db.collection(表名).doc("id值").get().then(res=>{ })
db.collection(表名).where({ 匹配的字段名:字段值,......}).get().then(res=>{ })
//使用doc通过主键查询获取单条数据,doc只能放置主键id
db.collection("test")
.doc("023ce9555fe590a6000c372d714bcc02")
.get().then(res=>{
console.log(res)
})
db.collection("test")
.where({
book_author:"吴承恩",
book_pirce:120
})
.get().then(res=>{
console.log(res)
})
get
方法获取,但通常不建议这么使用,在小程序中我们需要尽量避免一次性获取过量的数据,只应获取必要的数据。为了防止误操作以及保护小程序体验,小程序端在获取集合数据时服务器一次默认并且最多返回 20 条记录,云函数端这个数字则是 100。开发者可以通过 limit
方法指定需要获取的记录数量,但小程序端不能超过 20 条,云函数端不能超过 100 条。_selectImg:function(){
wx.chooseImage({
count: 9,
success:res=>{
this.setData({
fileList:res.tempFilePaths
})
}
})
},
_upload:function(){
this.data.fileList.forEach((item,index)=>{
let ext=item.split(".").pop()
let file=(new Date).getTime()+index+"."+ext
wx.cloud.uploadFile({
cloudPath:file,
filePath:item
}).then(res=>{
console.log(res)
})
})
},
wx.cloud.downloadFile({
fileID:"cloud://music-dev-wi2lv.6d75-music-dev-wi2lv-1302673657/1.jpg"
}).then(res=>{
wx.saveFile({
tempFilePath:res.tempFilePath,
success:res=>{
console.log(res)
wx.showToast({
title: '下载成功',
})
}
})
})
_deleteImg:function(){
wx.cloud.deleteFile({
fileList:[" cloud://music-dev-wi2lv.6d75-music-dev-wi2lv-1302673657/1608885426389.jpg","cloud://music-dev-wi2lv.6d75-music-dev-wi2lv-1302673657/1608885426387.jpg"]
}).then(res=>{
console.log(res)
})
},
const cloud = require('wx-server-sdk')
//初始化云能力
cloud.init()
// 云函数入口函数
exports.main = async (event, context) => {
const wxContext = cloud.getWXContext()
let sum=event.a+event.b
return {
sum,
openid: wxContext.OPENID
}
}
wx.cloud.callFunction({
name:"g_sum",
data:{
a:1003,
b:3849
}
}).then(res=>{
console.log(res)
})
// 云函数入口文件
const cloud = require('wx-server-sdk')
cloud.init()
// 云函数入口函数
const db=cloud.database()
exports.main = async (event, context) => {
const wxContext = cloud.getWXContext()
let res=await db.collection(event.table).where(event.where).remove()
return {
openid: wxContext.OPENID,
res
}
}