目录
第一章微信小程序概述总结
如何认识小程序?
1.1 小程序简介
微信(WeChat)小程序是腾讯公司于2011年1月21日退出的一款智能终端提供即时通信(Instant Messaging,IM)服务的应用程序,小程序是一种不需要下载安装级可使用的应用。
1.2小程序的特征
(1)无需安装
(2)触手可及
(3)用完即走
(4)无需加载
1.3 小程序应用场景的特点
(1)简单的业务逻辑
简单是指应用本身的业务逻辑。例如:"小黄车"
(2)低频度的使用场景
低频度是小程序使用场景的另一个特点。例如:"猫眼"
1.4 微信小程序开发流程
第一步:在微信公众号平台上注册小程序账号
第二步:下载开发者工具进行编码
第三步:通过开发者工具提交代码,通过审核后便可发布
1.5 下载微信小程序开发中工具APP
学习这本课程中,首先,需要安装一个软件APP,之后注册一个微信小程序账号
微信开发者功能介绍
微信小程序界面划分于5大区域:工具栏、模拟区、目录文件区、编辑区和调试区。
(1)工具栏
实现多种功能,例如账号切换,小程序编译、清理存缓、预览等
(2)模拟区
在模拟区中选择手机类型、显示比例、网络类型,模拟器会显示运行效果
(3)目录文件区
用来显示当前的目录结构
(4)编辑区
用来实现对代码的编辑操作,编辑区中支持对.wxml、.wxss、.js及.json文件的操作
编辑区常用的组合键:
表1-1 微信小程序开发工具常用组合键
组合键 | 功能 | 组合键 | 功能 |
Ctrl+S | 保存文件 | Ctrl+Home | 移动到文件开头 |
Ctrl+【,Ctrl+】 | 代码行缩进 | Ctrl+End | 移动到文件结尾 |
Ctrl+Shift+【,Ctrl+Shift+】 | 折叠打开代码块 | Shift+Home | 选择从行首到光标处 |
Ctrl+Shift+Enter | 在当前上方插入一行 | Shift+End | 选择从光标到行尾 |
Ctrl+Shift+F | 全局搜索 | Ctrl+I | 选中当前行 |
Ctrl+Alt+F | 行码格式化 | Ctrl+D | 选中匹配 |
Alt+Up,Alt+Down | 上下移动一行 | Ctrl+Shift+L | 选择所有匹配 |
Shift+Alt+Up(Down) | 向上(向下)复制一行 | Ctrl+U | 光标退回 |
(5)调试区
调试区的功能是帮助开发者进行代码调试及排查有问题的区域,小程序系统为开发者提供了9个调试功能模块,分别是Console、Sources、Nekwork、Security、Storage、AppData、Wxml、Sensor和Trace。最右边的扩展菜单项:是控制开发工具按钮。
调试区功能介绍
(1)Console面板
Console面板是控制台,是调试小程序的控制面板,当代码执行错误时,错误信息将显示在控制Console面板中,便于开发者排查错误。
(2)Sources面板
Sources面板是源码,用于显示当前项目的脚本文件,例如:微信开放文档
(3)Network面板
Network面板是请求网络调试信息页,用于显示当前项目的脚本文件
(4)Security面板
Security面板是安全人证信息页,开发者可以通过该面板调试当前的网页的安全和认证等问题。如果安全设置安全论证,则会显示“The security of this page is unknown.”
(5)Storage面板
Storage面板是数据库存储信息页
(6)AppData面板
AppData面板是实时数据信息页,用于显示被激活的所有页面的数据情况
(7)Wxml面板
Wxml面板是布局信息页,主要用于调试Wxml组件和相关CSS样式,显示Wxml转化后的界面。
(8)Sensor面板
Sensor面板是重力传感器信息页,用于调试重力感应API
(9)Trace面板
Trace面板是路由跟踪信息页,开发者在这里可以追踪连接到电脑中的安装的路由信息
我的第一个微信小程序代码如下所示:
.wxml代码:
<!--index.wxml-->
<navigation-bar title="Weixin" back="{{false}}" color="black" background="#FFF"></navigation-bar>
<scroll-view class="scrollarea" scroll-y type="list">
<view class="container">
<view class="userinfo">
<block wx:if="{{canIUseNicknameComp && !hasUserInfo}}">
<button class="avatar-wrapper" open-type="chooseAvatar" bind:chooseavatar="onChooseAvatar">
<image class="avatar" src="{{userInfo.avatarUrl}}"></image>
</button>
<view class="nickname-wrapper">
<text class="nickname-label">昵称</text>
<input type="nickname" class="nickname-input" placeholder="请输入昵称" bind:change="onInputChange" />
</view>
</block>
<block wx:elif="{{!hasUserInfo}}">
<button wx:if="{{canIUseGetUserProfile}}" bindtap="getUserProfile"> 获取头像昵称 </button>
<view wx:else> 请使用2.10.4及以上版本基础库 </view>
</block>
<block wx:else>
<image bindtap="bindViewTap" class="userinfo-avatar" src="{{userInfo.avatarUrl}}" mode="cover"></image>
<text class="userinfo-nickname">{{userInfo.nickName}}</text>
</block>
</view>
<view class="usermotto">
<text class="user-motto">{{motto}}</text>
</view>
</view>
</scroll-view>
.scss代码:
/**index.scss**/
page {
height: 100vh;
display: flex;
flex-direction: column;
}
.scrollarea {
flex: 1;
overflow-y: hidden;
}
.userinfo {
display: flex;
flex-direction: column;
align-items: center;
color: #aaa;
width: 80%;
}
.userinfo-avatar {
overflow: hidden;
width: 128rpx;
height: 128rpx;
margin: 20rpx;
border-radius: 50%;
}
.usermotto {
margin-top: 200px;
}
.avatar-wrapper {
padding: 0;
width: 56px !important;
border-radius: 8px;
margin-top: 40px;
margin-bottom: 40px;
}
.avatar {
display: block;
width: 56px;
height: 56px;
}
.nickname-wrapper {
display: flex;
width: 100%;
padding: 16px;
box-sizing: border-box;
border-top: .5px solid rgba(0, 0, 0, 0.1);
border-bottom: .5px solid rgba(0, 0, 0, 0.1);
color: black;
}
.nickname-label {
width: 105px;
}
.nickname-input {
flex: 1;
}
.json代码:
{
"usingComponents": {
"navigation-bar": "/components/navigation-bar/navigation-bar"
}
}
.ts代码:
// index.ts
// 获取应用实例
const app = getApp<IAppOption>()
const defaultAvatarUrl = 'https://mmbiz.qpic.cn/mmbiz/icTdbqWNOwNRna42FI242Lcia07jQodd2FJGIYQfG0LAJGFxM4FbnQP6yfMxBgJ0F3YRqJCJ1aPAK2dQagdusBZg/0'
Component({
data: {
motto: 'Hello World',
userInfo: {
avatarUrl: defaultAvatarUrl,
nickName: '',
},
hasUserInfo: false,
canIUseGetUserProfile: wx.canIUse('getUserProfile'),
canIUseNicknameComp: wx.canIUse('input.type.nickname'),
},
methods: {
// 事件处理函数
bindViewTap() {
wx.navigateTo({
url: '../logs/logs',
})
},
onChooseAvatar(e: any) {
const { avatarUrl } = e.detail
const { nickName } = this.data.userInfo
this.setData({
"userInfo.avatarUrl": avatarUrl,
hasUserInfo: nickName && avatarUrl && avatarUrl !== defaultAvatarUrl,
})
},
onInputChange(e: any) {
const nickName = e.detail.value
const { avatarUrl } = this.data.userInfo
this.setData({
"userInfo.nickName": nickName,
hasUserInfo: nickName && avatarUrl && avatarUrl !== defaultAvatarUrl,
})
},
getUserProfile() {
// 推荐使用wx.getUserProfile获取用户信息,开发者每次通过该接口获取用户个人信息均需用户确认,开发者妥善保管用户快速填写的头像昵称,避免重复弹窗
wx.getUserProfile({
desc: '展示用户信息', // 声明获取用户个人信息后的用途,后续会展示在弹窗中,请谨慎填写
success: (res) => {
console.log(res)
this.setData({
userInfo: res.userInfo,
hasUserInfo: true
})
}
})
},
},
})
最后呈现的效果图为:
第二章 微信小程序开发基础总结
2.1 小程序的基本目录结构
图1-1:
2.1.1主页文件
微信小程序的主体部分由3 个文件组成, 这3 个文件必须放在项目的主目录中, 负责小程序的整体配置, 它们的名称是固定的。
(1)app.js:小程序逻辑页面,主要用来注册小程序全局实例。
(2)app.json:小程序公共配置文件,配置小程序全局设置。
(3)app.wxss:小程序主样式表文件,类似的HTML的.CSS文件。
图1-2:
2.1.2页面文件
小程序通常是由多个页面组成的, 每个页面包含4 个文件, 同一页面的这4 个文件必须具有相同的路径与文件名。 当小程序被启动或小程序内的页面进行跳转时, 小程序会根据app.json设置的路径找到相对应的资源进行数据绑定。
(1).js文件:页面逻辑文件,在该文件中编写JavaScript代码控制页面的逻辑。
(2).wxml:页面结构文件,用于设计页面的布局、数据绑定等。
(3).wxss:页面样式表文件,用于定义本页面中用到的各类样式表。
(4).json:页面配置文件,该文件在页面中不可缺少。
图 1-3:
2.2 小程序开发框架
图2-1
2.2.1视图层
MINA框架的视图层由WXML与WXSS 编写,由组件来进行展示,.wxml文件用于描述页面的结构; .wxss文件用于描述页面的样式。
2.2.2 逻辑层
逻辑层用于处理事务逻辑。
微信小程序开发框架的逻辑层是采用javaScrict编写的。 在javaScrict的基础上, 微信团队做了适当修改, 以便提高开发小程序的效率。 主要修改包括:
(1) 增加app()和Page()方法, 进行程序和页面的注册。
(2) 提供丰富的API, 如扫一扫、支付等微信特有的能力。
(3) 每个页面有独立的作用域, 并提供模块化能力。
2-2小程序默认的app.js文件,如图:
2.2.3数据层
数据层在逻辑上包括页面临时数据或缓存文件存储(本地存储)和网络存储与调用。
(1)页面临时数据或缓存
(2)文件存储(本地存储)
wx.getStorage:获取本地数据缓存
wx.setStorage:设置本地数据缓存
wx.clearStorage:清理本地数据缓存
(3)网络存储与调用
wx.request: 发起网络请求
wx.uploadFile: 上传文件
wx.downloadFile: 下载文件
调用URL的API接口,如下:
wx.navigateTo :新窗口打开页面
wx.redirectTo: 原窗口打开页面
2.3创建另一个页面
启动微信发开发工具,创建新项目,如图所示:
图2-3所示:
2.3.1创建另一个页面文件
在pages目录新建一个ti目录,并在ti目录中新建ti.js、ti.json、ti.wxss、ti.wxml空文件。之后把原来的index目录删掉。
图2-4
在app.json中删掉"pages/index/index"
{
"pages": [
"pages/ti/ti",
"pages/logs/logs"
],
"window": {
"navigationBarTextStyle": "black",
"navigationBarTitleText": "Weixin",
"navigationBarBackgroundColor": "#ffffff"
},
"style": "v2",
"componentFramework": "glass-easel",
"lazyCodeLoading": "requiredComponents"
}
图2-5
(1)首先,我们学习如何能在页面中显示“欢迎学习小程序,实现大梦想”,打开建的ti目录,找到ti.wxml文件中输入“欢迎学习小程序,实现大梦想”。如下所示 :
图2-6
(2)打开ti.json文件,输入代码:
图2-7
{
}
(3) 打开ti.js文件,引入Page()方法输入代码:
图2-8
Page({
})
将四个文件按Ctrl+S进行保存后,进行编译,运行结果如下所示:
运行效果图2-9
表2-10 各项文件的代码内容
2.4 配置文件
2.4.1 全局配置文件
小程序的全局配置保存在全局配置文件(app.json) 中, 使用全局配置文件来配置页面文件(pages) 的路径、设置窗口(window) 表现、设定网络请求API 的超时时间值(netwoekTimeout) 以及配置多个切换页(tabBar) 等。
图2-11 全局配置项
1.Pages配置项
设置Pages配置时要注意以下三点:
(1)数组的第一项用于设定小程序的初始页面
(2)在小程序新准则或减少页面时,都需要对数组进行修改
(3)文件名不需要写文件扩展名
app.json配置文件如下:
{
"pages": [
"pages/ti/ti",
"pages/logs/logs"
],
}
2.widow配置项
widow配置项负责设置小程序状态栏、导航栏、窗口背景等系统样式
图2-12 widow配置项及其描述
3.taBar配置项
当需要在程序顶部或底部设置菜单栏时,可以通过taBar配置项来实现
图2-13 taBar配置项及其描述
其中taBar配置项中list选项
图2-13taBar配置项中list选项
4.networkTimeout配置项
小程序中各种网络请求API的超时时间值只能通过networkTimeout配置项统一设置,不能单独在API中设置,显示颜色就近原则。
图2-14 networkTimeout配置项
5.debug配置项
用于开发者工具的调试模式,默认为false.
2.4.2页面配置文件
页面配置文件(*.json) 只能设置本页面的窗口表现, 而且只能设置window配置项的内容。 在配置页面配置文件后, 页面中的window配置值将覆盖全局配置文件(app.json) 中的配置值。
2.5逻辑文件
2.5.1.项目逻辑文件
项目逻辑文件app.js中可以通过App()函数注册小程序生命周期函数、全局属性和全局方法, 已注册的小程序实例可以在其他页面逻辑文件中通过getApp()获取。
图2-15 项目逻辑文件配置项
var app =getApp();
Console.log(app.data);
首先,我们可以在app.js文件中加入代码:
// app.js
App({
onLaunch() {
// 展示本地存储能力
console.log("小程序初始化");
},
onShow(){
console.log("小程序启动");
},
onHide(){
console.log("小程序隐藏");
},
globalData: {
userInfo: null
}
})
保存后运行控制台运行效果如下:
2.5.2页面逻辑文件
页面逻辑文件的主要功能有: 设置初始数据; 定义当前页面的生命周期函数; 定义事件处理函数等。 每个页面文件都有一个相应的逻辑文件, 逻辑文件是运行在纯javaScrict引擎中。 因此, 在逻辑文件中不能使用浏览器提供的特有对象(document、window) 及通过操作DOM改变页面, 只能采用数据绑定和事件响应来实现。
图2-16 页面逻辑文件配置项
(1)设置初始数据
设置初始数据是对页面的第一次数据绑定。
(2)定义当前页面的生命周期函数
在Page() 函数的参数中, 可以定义当前页面的生命周期函数。在Page() 函数的参数中, 可以定义当前页面的生命周期函数。 页面的生命周期函数主要有onload、onShow、onReady、onHide、onUnload。
■ onload 页面加载函数。 当页面加载完成后调用该函数。 一个页面只会调用一次。
■ onShow 页面显示函数。 当页面显示时调用该函数。 每次打开页面都会调用一次。
■ onReady页面数据绑定函数。 当页面初次数据绑定完成时调用该函数。 一个页面只会调用一次, 代表页面已经准备就绪, 可以和视图层进行交互。
■ onHide 页面隐藏函数。 当页面隐藏时及当navigateTo 或小程序底部进行tab 切换时,调用该函数。
■ onUnload页面卸载函数。 当页面卸载、进行navigateBack 或redirectTo 操作时, 调用该函数。
示例1:
首先,在ti.js文件中输入代码:
Page({
//页面的初始数据
data:{
name:'lwk',//字符串
age:30,//数字
birthday:[{year:1988},{month:11},{ date:18 }],//数组object:{hobby:'computer'}//对象
}
})
在ti.wxml中输入代码:
<view>姓名:{{name}}</view>
<view>年龄:{{age}}</view>
<view>出生日期:
{{birthday[0].year}}年
{{birthday[1].month}}月
{{birthday[2].date}}日
</view>
按Ctrl+S保存后,运行效果如下:
示例2:
在miniprogram目录文件下,新建一个images文件放入两张图片
在ti.js文件中输入代码:
// ti.js
Page({
data:{
name:'lwk',//字符串
age:30,//数字
birthday:[{year:1988},{month:11},{ date:18 }],//数组object:{hobby:'computer'}//对象
}
})
在logs.js文件中输入代码:
// logs.js
const util = require('../../utils/util.js')
Page({
data: {
logs: []
},
onLoad() {
console.log("logs onLoad ......"),
this.setData({
logs: (wx.getStorageSync('logs') || []).map(log => {
return {
date: util.formatTime(new Date(log)),
timeStamp: log
}
})
})
},
// 生命周期函数--监听页面加载
//生周期函数--监听页面初次渲染完成
onReady: function (){
console.log("logs onReady......")},
// 生命周期函数--监听页面显示
onShow: function () {
console.log("logs onShow ......")},
//*生命周期函数--监听页面隐藏
onHide: function () {
console.log("logs onHide ......")
},
//生命周期函数--监听页面卸载
onUnload: function (){
console.log("logs onUnload......")
}
})
在app.json中写入代码:
{
"pages": [
"pages/ti/ti",
"pages/logs/logs"
],
"window": {
"navigationBarTextStyle": "black",
"navigationBarTitleText": "Weixin",
"navigationBarBackgroundColor": "#ffffff"
},
"tabBar": {
"list": [{
"pagePath": "pages/logs/logs",
"text": "日志",
"iconPath": "images/logs.jpg",
"selectedIconPath": "images/logs.jpg"
},{
"pagePath": "pages/ti/ti",
"text": "ti页",
"iconPath": "images/ti.jpg",
"selectedIconPath": "images/ti.jpg"
}]
},
"style": "v2",
"componentFramework": "glass-easel",
"lazyCodeLoading": "requiredComponents"
}
保存编译,运行结果:
(3)定义事件处理函数
开发者在Page() 中自定义的函数称为事件处理函数。 视图层可以在组件中加入事件绑定, 当达到触发事件时, 小程序就会执行Page() 中定义的事件处理函数。
示例代码如下:
/index.wxml
<view bindtap="myclick">单击执行逻辑层事件<view>
//index.js
Page({
myclick:function(){
console.log("点击了view">}
}
});
(4)使用setData 更新数据
小程序在Page对象中封装了一个名为setData() 的函数, 用来更新data中的数据。
2.6页面文件
页面结构文件(WXML) 是框架设计的一套类似HTML的标签语言, 结合基础组件、事件系统, 可以构建出页面的结构, 即.wxml 文件。 在小程序中, 类似HTML的标签被称为组件, 是页面结构文件的基本组成单元。
2.6.1.数据绑定
1.简单绑定
简单绑定是指使用双大括号({{}})将变量包起来, 在页面中直接作为字符串输出使用。简单绑定可以作用于内容、组件属性、控制属性等的输出。
注意:简单绑定作用于组件属性、控制属性等,双大括号外应该添加双引号。
2.运算
在{{}} 内可以做一些简单的运算(主要有算术运算、逻辑运算、三元运算、字符串运算等), 这些运算均应符合JavaScript 运算规则。
示例代码如下:
目的算术运算、逻辑运算、三元运算运算代码
在ti.wxml写入代码:
<view>姓名:{{name}}</view>
<view>年龄:{{age}}</view>
<view>出生日期:
{{birthday[0].year}}年
{{birthday[1].month}}月
{{birthday[2].date}}日
</view>
<view>算术运算:{{age+num}}</view>
<view>逻辑运算:{{age==40}}</view>
<view>三元运算:{{age==1 ?3:4}}</view>
在ti.js文件中输入代码:
// ti.js
Page({
data:{
name:'lwk',//字符串
age:30,//数字
birthday:[{year:1988},{month:11},{ date:18 }],//数组object:{hobby:'computer'}//对象
}
})
运行结果:
2.6.2条件数据绑定
概念:条件数据绑定就是根据绑定表达式的逻辑值来判断是否数据绑定当前组件。
1.wx:if条件数据绑定wx:if条件数据绑定是指使用wx:if 这个属性来判断是否数据绑定当前组件。 当需要添加多个分支块时, 可以使用wx:elif、wx:else属性。 当控制表达式为true 时,数据绑定一个分支; 当控制表达式为false 时, 数据绑定另一个分支。
2.block:wx:if 条件数据绑定
例如:
目的:使用条件数据绑定运行字符串
在ti.js中继续加入代码:
// ti.js
Page({
data:{
name:'lwk',//字符串
age:30,//数字
birthday:[{year:1988},{month:11},{ date:18 }],//数组object:{hobby:'computer'}//对象
num:100,
students:[
{nickname:"Tom",height:150,weight:150},
{nickname:"Anne",height:160,weight:100}
]
}
})
在ti.wxml继续加入代码:
<view>姓名:{{name}}</view>
<view>年龄:{{age}}</view>
<view>出生日期:
{{birthday[0].year}}年
{{birthday[1].month}}月
{{birthday[2].date}}日
</view>
<view>算术运算:{{age+num}}</view>
<view>逻辑运算:{{age==40}}</view>
<view>三元运算:{{age==1 ?3:4}}</view>
<view wx:if="age>40">1</view>
<view wx:elif="age==40">2</view>
<view wx:else>3</view>
<template name="stu">
<view wx:for="{{students}}">
<text>姓名:{{item.nickname}}</text>
<text>身高:{{item.height}}</text>
<text>体重:{{item.weight}}</text>
</view>
</template>
<template is="stu" data="{{students}}"></template>
运行结果:
2.6.3列表数据绑定
概念:列表数据绑定用于将列表中的各项数据进行重复数据绑定。
1.wx:for 在组件上, 可以使用wx:for 控制属性绑定一个数组, 将数据中的各项数据循环进行数据绑定到该组件, 格式如下:
<view wx.for="{{items}}">
{{index}}:{{item}}
</view>
2.6.4 模板
概念:在小程序中, 如果要经常使用几个组件的组合(如“登录” 选项), 通常把这几个组件结合定义为一个模板, 以后在需要的文件中直接使用这个模板。
1.定义模板
模板代码由wxml组成, 因此其定义也是在wxml文件中, 定义模板的格式为:
< template = "模板名" >
相关组件代码为: </template> 其中, < template> 为模板标签, name 属性用于定义模板的名称。
2.调用模板
将模板定义后, 就可以对其进行调用了。 调用模板的格式为: < template is= "模板名称" data == "{{传入的数据}}" />
例如:
在原来的ti.js文件中加入代码:
<template name="stu">
<view wx:for="{{students}}">
<text>姓名:{{item.nickname}}</text>
<text>身高:{{item.height}}</text>
<text>体重:{{item.weight}}</text>
</view>
</template>
<template is="stu" data="{{students}}"></template>
在原来的ti.js加入代码:
<template name="stu">
<view wx:for="{{students}}">
<text>姓名:{{item.nickname}}</text>
<text>身高:{{item.height}}</text>
<text>体重:{{item.weight}}</text>
</view>
</template>
<template is="stu" data="{{students}}"></template>
运行结果:
2.6.5 引用页面文件
在WXML文件中, 不仅可以引用模板文件, 还可以引用普通的页面文件。 WXML 提供了两种方式来引用其他页面文件。
1.import方式
2.Include方式
2.6.6 页面事件
简单来说, 小程序中的事件是用户的一种行为或通信方式。 在页面文件中, 通过定义事件来完成页面与用户之间的交互, 同时通过事件来实现视图层与逻辑层的通信。 我们可以将事件绑定到组件上, 当达到触发条件时, 事件就会执行逻辑层中对应的事件处理函数。
(1)定义事件函数
概念:在.js文件中定义事件函数来实现相关功能, 当事件响应后就会执行事件处理代码。
(2)调用事件
概念:调用事件也称为注册事件。
(3)冒泡事件
概念:冒泡事件是指某个组件上的事件被触发后, 事件会向父级元素传递, 父级元素再向其父级元素传递, 一直到页面的顶级元素。
(4)非冒泡事件
概念: 非冒泡事件是指某个组件上的事件被触发后, 该事件不会向父节点传递。
2.7 页面样式文件
1.尺寸单位
由于CSS原有的尺寸单位在不同尺寸的屏幕中得不到很好的呈现,WXSS在此基础上增加了尺寸单位rps (respnesivepixel)。 WXSS规定屏幕宽度为750rps, 在系统数据绑定过程中rpx会按比例转化为px。
2.样式导入
为了便于管理WXSS文件, 我们可以将样式存放于不同的文件中。 如果需要在某个文件中引用另一个样式文件, 使用@import语句导入即可。
3.选择器
目前,WXSS 仅支持CSS中常用的选择器, 如.class、#id、element、beforee、aftert等。
4.WXSS常用属性
WXSS常用属性表
WXSS常用属性表
第三章页面布局总结
3.1 盒子模型
概念:微信小程序的视图层由WXML 和WXSS组成。 其中, WXSS (WeiXINStyleSheets) 是基于CSS 拓展的样式语言, 用于描述WXML 的组成样式, 决定WXML的组件如何显示。WXSS 具有CSS的大部分特性, 因此, 本章将重点讲解CSS 中的布局相关内容。、
在页面设计中, 只有掌握了盒子模型以及盒子模型的各个属性和应用方法, 才能轻松控制页面中的各个元素。 盒子模型就是我们在页面设计中经常用到的一种思维模型。 在CSS 中, 一个独立的盒子模型由内容(content)、内边距(padding)、边框(border)和外边距(margin) 4 个部分组成, 如图3-1所示。
图3-1盒子模型结构
此外, 对padding、border 和margin 可以进一步细化为上、下、左、右4 个部分, 在CSS可以分别进行设置, 如图3-2所示。
图中各元素的含义如下:
■ width 和height 内容的宽度和高度。
■ padding-top、padding-right、padding-bottom 和padding-left 上内边距、右内边距、底内边距和左内边距。
■ padding-top、padding-right、padding-bottom 和padding-left 上边框、右边框、底边框和左边框。
简单来说,一个盒子实际所占有的高度应该由"内容"+"内边距"+"边框"+"外边距",例如:
.box{
width:70px;
padding:5px;
marigin:10px;
}
3.2 块元素与行内元素
概念:块级元素默认占一行高度, 一行内通常只有一个块级元素(浮动后除外), 添加新的块级元素时, 会自动换行, 块级元素一般作为盒子出现。
3.2.1 块级元素
(1) 一个块级元素占一行。
(2) 块级元素的默认高度由内容决定, 除非自定义高度。
(3) 块级元素的默认宽度是父级元素的内容区宽度, 除非自定义宽度。
(4) 块级元素的宽度、高度、外边距及内边距都可以自定义设置。
(5) 块级元素可以容纳块级元素和行内元素。 < view/ > 组件默认为块级元素, 使用<view/ > 组件演示盒子模型及块级元素的示例代码如下:
在index.js中输入代码:
// pages/index/index.js
Page({
})
在index.json中输入代码:
{
}
在index.wmxl中输入代码:
<!--每个块级元素占一行-->
<view style = "border:1px solid #f00">块级元素1</view>
<!--块级元素的宽度等于父级元素的宽度减去内外边距的宽度-->
<view style = "border:1px solid #0f0;margin:15px;padding:20px">块级元素2</view >
<!--块级元素的宽度、高度自定义设置-->
<view style = "border:1px solid #00f;width:200px;height:80px">块级元素3</view >
<!--块级元素的高度随内容决定,内容为块级元素 -->
<view style= "border:1px solid #ccc;">
<view style = "height:60px">块级元素4</view >
</view>
<!--块级元素的高度随内容决定,内容为文本元素,块级元素的宽度为100px-->
<view style = "border: 1px solid #f00;width:100px;background-color:#ccc">父级元素高度随内容决定,内容为文本</view>
运行结果如下:
3.2.2 行内元素
概念:行内元素, 不必从新一行开始, 通常会与前后的其他行内元素显示在同一行中, 它们不占有独立的区域, 仅靠自身内容支撑结构, 一般不可以设置大小, 常用于控制页面中文本的样式。 将一个元素的display 属性设置为inline 后, 该元素即被设置为行内元素。
行内元素的特点
(1) 行内元素不能被设置高度和宽度, 其高度和宽度由内容决定。
(2) 行内元素内不能放置块级元素, 只级容纳文本或其他行内元素。
(3) 同一块内, 行内元素和其他行内元素显示在同一行。
< text/ > 组件默认为行内元素, 使用< view/ > 及< text/ > 组件演示盒子模型及行内元素的示例代码如下:
在index.json中输入代码:
{
}
在index.js中输入代码:
// pages/index/index.js
Page({
})
在index.wxml中输入代码:
<view style= "padding:20px">
<text style ="border:1px solid #f00">文本1</text >
<text style = " border:1px solid #0f0; margin:10px; padding:5px">文本2</text >
<view style ="border:1px solid #00f; display:inline">块级元
设置为行内元素</view>一行显示不全,自动换行显示
</view>
运行结果:
3.2.3 行内块元素
概念:当元素的display 属性被设置为inline-block时, 元素被设置为行内块元素。 行内块元素可以被设置高度、宽度、内边距和外边距。代码如下:
在index.wxml中输入代码:
<view>
<view style= "display: inline-block;border: 1px solid #f00;margin: 10px;width: 200px;">块级元素、行内元素和行内块元素
</view>三种类型
</view>
在index.js中输入代码:
// pages/index/index.js
Page({
})
在index.json中输入代码:
{
}
运行结果:
3.3 浮动与定位
3.3.1 元素浮动与清除
概念:元素浮动就是指设置了浮动属性的元素会脱离标准文档流的控制, 移到其父元素中指定位置的过程。 在CSS中, 通过float 属性来定义浮动, 其基本格式如下:
{float:none|left|right;}
none——默认值,表示元素不浮动;
left——元素向左浮动
right——元素向右浮动
例如:分别对box1、box2、box3元素左浮动
第一步,在index.wxml中输入代码:
<view>box1,box2,box3没浮动</view>
<view style="border: 1px solid #f00;padding:5px;">
<view style="border: 1px solid #0f0;padding:5px;">box2</view>
<view style="border: 1px solid #0f0;padding:5px;">box2</view>
<view style="border: 1px solid #0f0;padding:5px;">box3</view>
</view>
<view>box1左浮动</view>
<view style="border: 1px solid #f00;padding:5px;">
<view style="float: left; border: 1px solid #0f0;padding:5px;">box1</view>
<view style="border: 1px solid #0f0;padding:5px;">box2</view>
<view style="border: 1px solid #0f0;padding:5px;">box3</view>
</view>
<view>box2左浮动</view>
<view style=" border: 1px solid #f00;padding:5px;">
<view style="float: left; border: 1px solid #0f0;padding:5px;">box1</view>
<view style="float: left; border: 1px solid #0f0;padding:5px;">box2</view>
<view style="border: 1px solid #0f0;padding:5px;">box3</view>
</view>
<view> box1 box2 box3左浮动</view>
<view style=" border: 1px solid #f00;padding:5px;">
<view style="float: left; border: 1px solid #0f0;padding:5px;">box1</view>
<view style="float: left; border: 1px solid #0f0;padding:5px;">box2</view>
<view style="float: left; border: 1px solid #0f0;padding:5px;">box3</view>
</view>
第二步,在index.js中输入代码:
// pages/index/index.js
Page({
})
第三步,在index.json中输入代码:
{
}
运行结果:
例如:分别对box1、box2、box3元素右浮动
其他不变,在index.wxml中写入代码:
<view>box1,box2,box3没浮动</view>
<view style="border: 1px solid #f00;padding:5px;">
<view style="float: right; border: 1px solid #0f0;padding:5px;">box2</view>
<view style="float: right; border: 1px solid #0f0;padding:5px;">box2</view>
<view style="float: right; border: 1px solid #0f0;padding:5px;">box3</view>
</view>
<view>box1右浮动</view>
<view style="border: 1px solid #f00;padding:5px;">
<view style="float: right; border: 1px solid #0f0;padding:5px;">box1</view>
<view style=" float: right; border: 1px solid #0f0;padding:5px;">box2</view>
<view style="float: right; border: 1px solid #0f0;padding:5px;">box3</view>
</view>
<view>box2右浮动</view>
<view style=" border: 1px solid #f00;padding:5px;">
<view style="float: right; border: 1px solid #0f0;padding:5px;">box1</view>
<view style="float: right; border: 1px solid #0f0;padding:5px;">box2</view>
<view style="float: right; border: 1px solid #0f0;padding:5px;">box3</view>
</view>
<view> box1 box2 box3右浮动</view>
<view style=" border: 1px solid #f00;padding:5px;">
<view style="float: right; border: 1px solid #0f0;padding:5px;">box1</view>
<view style="float: right; border: 1px solid #0f0;padding:5px;">box2</view>
<view style="float: right; border: 1px solid #0f0;padding:5px;">box3</view>
</view>
运行结果:
例如:分别对box1、box2、box3元素none
其他不变,在index.wxml中写入代码:
<view>box1,box2,box3没浮动</view>
<view style="border: 1px solid #f00;padding:5px;">
<view style="float: none; border: 1px solid #0f0;padding:5px;">box2</view>
<view style="float: none; border: 1px solid #0f0;padding:5px;">box2</view>
<view style="float: none; border: 1px solid #0f0;padding:5px;">box3</view>
</view>
<view>box1</view>
<view style="border: 1px solid #f00;padding:5px;">
<view style="float: none; border: 1px solid #0f0;padding:5px;">box1</view>
<view style=" float: none; border: 1px solid #0f0;padding:5px;">box2</view>
<view style="float: none; border: 1px solid #0f0;padding:5px;">box3</view>
</view>
<view>box2</view>
<view style=" border: 1px solid #f00;padding:5px;">
<view style="float: none; border: 1px solid #0f0;padding:5px;">box1</view>
<view style="float: none;border: 1px solid #0f0;padding:5px;">box2</view>
<view style="float: none; border: 1px solid #0f0;padding:5px;">box3</view>
</view>
<view> box1 box2 box3</view>
<view style=" border: 1px solid #f00;padding:5px;">
<view style="float: none; border: 1px solid #0f0;padding:5px;">box1</view>
<view style="float: none; border: 1px solid #0f0;padding:5px;">box2</view>
<view style="float: none; border: 1px solid #0f0;padding:5px;">box3</view>
</view>
运行结果:
在CSS 中,clear 属性用于清除浮动元素对其他元素的影响, 其基本格式如下:
left———清除左边浮动的影响, 也就是不允许左侧有浮动元素;
right———清除右边浮动的影响, 也就是不允许右侧有浮动元素;
both———同时清除左右两侧浮动的影响;
none———不清除浮动。
例如: index.js和 index.json不变,在index.wxml中输入代码:
<view> box1 box2 左浮动 box3 清除左浮动</view>
<view style=" border: 1px solid #f00;padding:5px;">
<view style=" float: left;border: 1px solid #0f0;padding:5px;">box1</view>
<view style="float: left; border: 1px solid #0f0;padding:5px;">box2</view>
<view style=" clear: left;border: 1px solid #0f0;">box3</view>
</view>
运行结果:
除此之外,还可以在父元素外添加个空元素
例如:在父元素添加一个空元素,实现父元素包裹浮动元素
第一步,在index.wxml中输入代码:
<view> box1 box2 box3左浮动 在父元素后添加一个空元素</view>
<view style=" border: 1px solid #f00;padding:5px;"class="clearfloat">
<view style="float: left; border: 1px solid #0f0;padding:5px;">box1</view>
<view style="float: left; border: 1px solid #0f0;padding:5px;">box2</view>
<view style="float: left; border: 1px solid #0f0;padding:5px;">box3</view>
</view>
在index.wxss中输入代码:
.clearfloat::after{
display: block;clear: both;height: 0;content: ""
}
index.js和 index.json不变
运行结果:
3.3.2 元素定位
概念:浮动布局虽然灵活, 但无法对元素的位置进行精确的控制。 在CSS 中, 通过position属性可以实现对页面元素的精确定位。
基本格式如下:
{position:static|relative|absolute|fixed}
static———默认值, 该元素按照标准流进行布局;
relative———相对定位, 相对于它在原文档流的位置进行定位, 它后面的盒子仍以标准流方式对待它;
absoulute———绝对定位, 相对于其上一个已经定位的父元素进行定位, 绝对定位的盒子从标准流中脱离, 它对其后的兄弟盒子的定位没有影响;
fixed———固定定位, 相对于浏览器窗口进行定位。
(1)默认值 (static)
例如:
在index.wxml中写入代码:
<!-- 三个元素均为定位static -->
<view style=" border: 1px solid #0f0;width: 100px;height: 100px;">box1</view>
<view style=" border: 1px solid #0f0;width: 100px;height: 100px;">box2</view>
<view style=" border: 1px solid #0f0;width: 100px;height: 100px;">box3</view>
在index.js中写入代码:
// pages/index/index.js
Page({
})
在index.json中写入代码:
{
}
运行结果:
(2)相对定位 (relative)
代码如下:
在index.wxml中写入代码:
<!-- box2元素相对定位 -->
<view style=" border: 1px solid #0f0;width: 100px;height: 100px;">box1</view>
<view style=" border: 1px solid #0f0;width: 100px;height: 100px;position: relative;left: 30px;top: 30px;">box2</view>
<view style=" border: 1px solid #0f0;width: 100px;height: 100px;">box3</view>
在index.js中写入代码:
// pages/index/index.js
Page({
})
在index.json中写入代码:
{
}
运行结果:
(3)绝对定位 (absolute)
例如:
在index.wxml中写入代码:
<!-- box2元素绝对定位 -->
<view style=" border: 1px solid #0f0;width: 100px;height: 100px;">box1</view>
<view style=" border: 1px solid #0f0;width: 100px;height: 100px;position: absolute;left: 30px;top: 30px;">box2</view>
<view style=" border: 1px solid #0f0;width: 100px;height: 100px;">box3</view>
在index.json中写入代码:
{
}
在index.js中写入代码:
// pages/index/index.js
Page({
})
运行结果:
{
}
(4)固定定位 (fixed)
例如:
在index.wxml中写入代码:
<!-- box2元素固定定位 -->
<view style=" border: 1px solid #0f0;width: 100px;height: 100px;">box1</view>
<view style=" border: 1px solid #0f0;width: 100px;height: 100px;position: absolute;left: 30px;top: 30px;">box2</view>
<view style=" border: 1px solid #0f0;width: 100px;height: 100px;">box3</view>
在index.js中写入代码:
// pages/index/index.js
Page({
})
在index.json中写入代码:
{
}
运行结果:
3.4 flex布局
概念:flex 布局是万维网联盟(WoeldWideWebConsortium,W3C) 在2009 年提出的一种新布局方案, 该布局可以简单快速地完成各种可以伸缩的设计, 以便很好地支持响应式布局。flex 是flexiblebox 的缩写, 意为弹性盒子模型, 可以简便、完整、响应式地实现各种页面布局。
布局:
flex 布局主要由容器和项目组成, 采用flex 布局的元素称为flex容器(flexcontainer),flex 布局的所有直接子元素自动成为容器的成员, 称为flex项目(flexitem)。
容器默认存在两根轴: 水平的主轴和垂直的交叉轴。 主轴的开始位置(与边框的交叉点) 叫做mainstart, 结束位置叫做mained; 交叉轴的开始位置叫做crosstart, 结束位置叫做crossend。 项目默认沿主轴排列。 单个项目占据的主轴空间叫做mainsize, 占据的交叉轴空间叫做crossize。 flex 布局模型如图所示。
设置display 属性可以将一个元素指定为flex布局, 设置flex-direction属性可以指定主轴方向。 主轴既可以是水平方向, 也可以是垂直方向。
3.4.1 容器属性
flex容器支持的属性又七种,如图所示:
(1)display
display用来指定元素是否为flex 布局, 语法格式为:
.box{display:flex|inline-flex;}
flex———块级flex布局, 该元素变为弹性盒子;
inline-flex———行内flex 布局, 行内容器符合行内元素的特征, 同时在容器内又符合flex 布局规范。
设置了flex布局之后, 子元素的float、clear 和vertical-align属性将失效。
(2)flex-direction
用于设置主轴的方向, 即项目排列的方向, 语法格式为:
.box{flex-direction:row|row-reverse|column|column-reverse;}
row———主轴为水平方向, 起点在左端, 当元素设置为 flex布局时, 主轴默认为row;
row-reverse———主轴为水平方向, 起点在右端;
column———主轴为垂直方向, 起点在顶端;
column-reverse———主轴为垂直方向, 起点在底端
如图所示:
(3)flex-wrap
用来指定项目在一根轴线的排列位置不够时,项目是否换行,其语法格式为:
.box{flex-wrap:nowrap|wrap|wrap-reverse;}
flex-wrap不同值的显示效果:
(4) flex-flow
flex-flow是flex-direction 和flex-wrap 的简写形式, 默认值为row nowrap。 语法格式如下:
.box{flex-flow:<flex-direction>||<flex-wrap>;}
(5)justify-content
justify-content 用于定义项目在主轴上的对齐方式。 语法格式如下:
.box{justify-content:flex-start|flex-end|center|space-between|space-around;}
justify-content———与主轴方向有关, 默认主轴水平对齐, 方向从左到右;
flex-start———左对齐, 默认值;
flex-end———右对齐;
center———居中;
space-between———两端对齐, 项目之间的间隔都相等;
space-around———每个项目两侧的间隔相等。
如图所示为justify-content不同值的显示效果:
(6)align-items
align-items用于指定项目在交叉轴上的对齐方式, 语法格式如下:
.box{align-items:flex-start|flex-end|center|baseline|stretch;}
align-items———与交叉轴方向有关, 默认交叉由上到下;
flex-start———交叉轴起点对齐;
flex-end———交叉轴终点对齐;
center———交叉轴中线对齐;
baseline———项目根据它们第一行文字的基线对齐;
stretch———如果项目未设置高度或设置为auto, 项目将在交叉轴方向拉伸填充容器, 此为默认值。
示例代码如下:
在index.wxml写入代码:
<view class="cont1">
<view class="item">1</view>
<view class="item item2">2</view>
<view class="item item3">3</view>
<view class="item item4">4</view>
</view>
在index.wxss写入代码:
.cont1{
display: flex;
flex-direction: row;
align-items: baseline;
}
.item{
background-color: #ccc;
border: 1px solid#f00;
height: 100px;
width: 50px;
margin: 2px;
}
.item2{
height: 80px;
}
.item3{
display: flex;
height: 50px;
align-items:flex-end ;
}
.item4{
height: 120px;
}
在index.json写入代码:
{
"navigationBarBackgroundColor": "#000000",
"navigationBarTitleText": "趋势(苏冷)",
"navigationBarTextStyle": "white",
"backgroundTextStyle": "dark"
}
运行结果:
(7)align-content
align-content 用来定义项目有多根轴线(出现换行后) 在交叉轴上的对齐方式, 如果只有一根轴线, 该属性不起作用。 语法格式如下:
.box{align-content;flex-start|flex-end|center|space-between|space-around|stretch}
apace-between——与交叉轴两端对齐, 轴线之间的间隔平均分布;
space-around——每根轴线两侧的间隔都相等, 轴线之间的间隔比轴线与边框间隔大一倍。 其余各属性值的含义与align-items属性的含义相同。
如图所示为align-content 不同值的显示效果:
3.4.2 项目属性
容器内的项目支持六个属性,如图所示:
(1)order
order属性定义项目的排列顺序, 数值越小, 排列越靠前, 默认值为0。 语法格式如下:
.item{order:<number>;}
示例代码如下:
在index.wxml输入代码:
<view class="cont1">
<view class="item">1</view>
<view class="item item2">2</view>
<view class="item item3">3</view>
<view class="item item4">4</view>
</view>
<view class="cont1">
<view class="item" style="order: 1;">1</view>
<view class="item "style="order: 3;">2</view>
<view class="item "style="order: 2;">3</view>
<view class="item item4">4</view>
</view>
在index.wxss输入代码:
.cont1{
display: flex;
flex-direction: row;
align-items: baseline;
}
.item{
background-color: #ccc;
border: 1px solid#f00;
height: 100px;
width: 50px;
margin: 2px;
}
.item2{
height: 80px;
}
.item3{
display: flex;
height: 80px;
align-items:flex-start ;
}
.item4{
height: 120px;
}
在index.json输入代码:
{
"navigationBarBackgroundColor": "#000000",
"navigationBarTitleText": "趋势(苏冷)",
"navigationBarTextStyle": "white",
"backgroundTextStyle": "dark"
}
运行结果:
(2)flex-grow
定义项目的放大比例, 默认值为0, 即不放大。 语法格式如下:
.item{flex-grow:<number>;}
示例代码如下:
在index.wxml输入代码:
<view class="cont1">
<view class="item">1</view>
<view class="item item2">2</view>
<view class="item item3">3</view>
<view class="item item4">4</view>
</view>
<view class="cont1">
<view class="item">1</view>
<view class="item "style="flex-grow:1">2</view>
<view class="item "style="flex-grow:2">3</view>
<view class="item">4</view>
</view>
在index.wxss输入代码:
.cont1{
display: flex;
flex-direction: row;
align-items: baseline;
}
.item{
background-color: #ccc;
border: 1px solid#f00;
height: 100px;
width: 50px;
margin: 2px;
}
.item2{
height: 80px;
}
.item3{
display: flex;
height: 80px;
align-items:flex-start ;
}
.item4{
height: 120px;
}
在index.json输入代码:
{
"navigationBarBackgroundColor": "#000000",
"navigationBarTitleText": "趋势(苏冷)",
"navigationBarTextStyle": "white",
"backgroundTextStyle": "dark"
}
运行结果:
(3)flex-shink
用来定义项目的缩小比例, 默认值为1, 如果空间不足, 该项目将被缩小。语法格式如下:
.item{flex-shink:<number>;}
示例代码如下:
在index.wxml输入代码:
<view class="cont1">
<view class="item">1</view>
<view class="item item2">2</view>
<view class="item item3">3</view>
<view class="item item4">4</view>
</view>
<view class="cont1">
<view class="item">1</view>
<view class="item "style="flex-shrink:1">2</view>
<view class="item "style="flex-shrink:2">3</view>
<view class="item"style="flex-shrink:3">4</view>
</view>
在index.wxss输入代码:
.cont1{
display: flex;
flex-direction: row;
align-items: baseline;
}
.item{
background-color: #ccc;
border: 1px solid#f00;
height: 100px;
width: 50px;
margin: 2px;
}
.item2{
height: 80px;
}
.item3{
display: flex;
height: 80px;
align-items:flex-start ;
}
.item4{
height: 120px;
}
在index.json输入代码:
{
"navigationBarBackgroundColor": "#000000",
"navigationBarTitleText": "趋势(苏冷)",
"navigationBarTextStyle": "white",
"backgroundTextStyle": "dark"
}
运行结果:
(4)flex-basis
属性用来定义伸缩项目的基准值, 剩余的空间将按比例进行缩放, 它的默认值为auto (即项目的本来大小)。 语法格式如下:
.item{flex-basis:<numner>|auto;}
示例如下:
在index.wxml输入代码:
<view class="cont1">
<view class="item">1</view>
<view class="item item2">2</view>
<view class="item item3">3</view>
<view class="item item4">4</view>
</view>
<view class="cont1">
<view class="item">1</view>
<view class="item "style="flex-basis:1">2</view>
<view class="item "style="flex-basis:2">3</view>
<view class="item"style="flex-basis:3">4</view>
</view>
在index.wxss输入代码:
.cont1{
display: flex;
flex-direction: row;
align-items: baseline;
}
.item{
background-color: #ccc;
border: 1px solid#f00;
height: 100px;
width: 50px;
margin: 2px;
}
.item2{
height: 80px;
}
.item3{
display: flex;
height: 80px;
align-items:flex-start ;
}
.item4{
height: 120px;
}
在index.json输入代码:
{
"navigationBarBackgroundColor": "#000000",
"navigationBarTitleText": "趋势(苏冷)",
"navigationBarTextStyle": "white",
"backgroundTextStyle": "dark"
}
运行结果:
(5)flex
属性是flex-grow、flex-shrink 和flex-basis 的简写, 其默认值分别为0、1、auto。语法格式如下:
.item{<flex-grow>|<flex-shrink>|<flex-basis>;}
(6)align-self
属性用来指定单独的伸缩项目在交叉轴上的对齐方式。 该属性会重写默认的对齐方式。 语法格式如下:
.item{aligin-self:auto|flex-start|flex-end|center|baseline|stretch;}
在该属性值中, 除了auto以外, 其余属性值和容器align-items的属性值完全一致。 auto表示继承容器align-items的属性, 如果没有父元素, 则等于stretch (默认值)。
好啦~今天总结就分享到这里啦~感谢大家阅读我的博客,希望我的文章能够对你们有所帮助。如果你们有任何问题或建议,请随时联系我。