目录

​​一、Flex布局简介​​

​​什么是flex布局?​​

​​flex属性​​

​​二、视图层 View​​

​​WXML​​

​​三、会议OA项目-首页​​


一、Flex布局简介

布局的传统解决方案,基于​​盒状模型​​​,依赖 ​​display​​​属性 + ​​position​​​属性 + ​​float​​属性

什么是flex布局?

1) Flex是Flexible Box的缩写,意为”弹性布局”,用来为盒状模型提供最大的灵活性。

2) 任何一个容器都可以指定为Flex布局。

3) display: ‘flex’

三、Flex布局简介_微信小程序

  

容器默认存在两根轴:水平的主轴(main axis)和垂直的交叉轴(cross axis)。主轴的开始位置(与边框的交叉点)叫做main start,结束位置叫做main end;交叉轴的开始位置叫做cross start,结束位置叫做cross end。

项目默认沿主轴排列。单个项目占据的主轴空间叫做main size,占据的交叉轴空间叫做cross size。

flex属性

  • flex-direction 主轴的方向 默认为row
  • flex-wrap 如果一条轴线排不下,如何换行
  • flex-flow 是flex-direction属性和flex-wrap属性的简写形式
  • justify-content 定义了项目在主轴上的对齐方式
  • align-items 定义项目在交叉轴上如何对齐
  • align-content 属性定义了多根轴线的对齐方式

注意,设为Flex布局以后,子元素的float、clear和vertical-align属性将失效。

学习地址:

​Flex 布局语法教程 | 菜鸟教程​

二、视图层 View

框架的视图层由 WXML 与 WXSS 编写,由组件来进行展示。

将逻辑层的数据反映成视图,同时将视图层的事件发送给逻辑层。

WXML(WeiXin Markup language) 用于描述页面的结构。

WXS(WeiXin Script) 是小程序的一套脚本语言,结合 ​​WXML​​,可以构建出页面的结构。

WXSS(WeiXin Style Sheet) 用于描述页面的样式。

组件(Component)是视图的基本组成单元。

WXML

WXML(WeiXin Markup Language)是框架设计的一套标签语言,结合​​基础组件​​​、​​事件系统​​,可以构建出页面的结构。

要完整了解 WXML 语法,请参考​​WXML 语法参考​​。

用以下一些简单的例子来看看 WXML 具有什么能力:

数据绑定

<!--wxml-->
<view> {{message}} </view>
// page.js
Page({
data: {
message: 'Hello MINA!'
}
})

列表渲染

<!--wxml-->
<view wx:for="{{array}}"> {{item}} </view>
// page.js
Page({
data: {
array: [1, 2, 3, 4, 5]
}
})

条件渲染

<!--wxml-->
<view wx:if="{{view == 'WEBVIEW'}}"> WEBVIEW </view>
<view wx:elif="{{view == 'APP'}}"> APP </view>
<view wx:else="{{view == 'MINA'}}"> MINA </view>
// page.js
Page({
data: {
view: 'MINA'
}
})

模板

<!--wxml-->
<template name="staffName">
<view>
FirstName: {{firstName}}, LastName: {{lastName}}
</view>
</template>

<template is="staffName" data="{{...staffA}}"></template>
<template is="staffName" data="{{...staffB}}"></template>
<template is="staffName" data="{{...staffC}}"></template>
// page.js
Page({
data: {
staffA: {firstName: 'Hulk', lastName: 'Hu'},
staffB: {firstName: 'Shang', lastName: 'You'},
staffC: {firstName: 'Gideon', lastName: 'Lin'}
}
})

具体的能力以及使用方式在以下章节查看:

​数据绑定​​​、​​列表渲染​​​、​​条件渲染​​​、​​模板​​​、​​引用​

WXSS

WXSS (WeiXin Style Sheets)是一套样式语言,用于描述 WXML 的组件样式。

WXSS 用来决定 WXML 的组件应该怎么显示。

为了适应广大的前端开发者,WXSS 具有 CSS 大部分特性。同时为了更适合开发微信小程序,WXSS 对 CSS 进行了扩充以及修改。

与 CSS 相比,WXSS 扩展的特性有:

  • 尺寸单位
  • 样式导入

尺寸单位

rpx(responsive pixel): 可以根据屏幕宽度进行自适应。规定屏幕宽为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

建议: 开发微信小程序时设计师可以用 iPhone6 作为视觉稿的标准。

注意: 在较小的屏幕上不可避免的会有一些毛刺,请在开发时尽量避免这种情况。

样式导入

使用​​@import​​​语句可以导入外联样式表,​​@import​​​后跟需要导入的外联样式表的相对路径,用​​;​​表示语句结束。

示例代码:

/** common.wxss **/
.small-p {
padding:5px;
}
/** app.wxss **/
@import "common.wxss";
.middle-p {
padding:15px;
}

内联样式

框架组件上支持使用 style、class 属性来控制组件的样式。

style:静态的样式统一写到 class 中。style 接收动态的样式,在运行时会进行解析,请尽量避免将静态的样式写进 style 中,以免影响渲染速度。

<view style="color:{{color}};" />

class:用于指定样式规则,其属性值是样式规则中类选择器名(样式类名)的集合,样式类名不需要带上​​.​​,样式类名之间用空格分隔。

<view class="normal_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 组件前边插入内容

全局样式与局部样式

定义在 app.wxss 中的样式为全局样式,作用于每一个页面。在 page 的 wxss 文件中定义的样式为局部样式,只作用在对应的页面,并会覆盖 app.wxss 中相同的选择器。

WXS

WXS(WeiXin Script)是小程序的一套脚本语言,结合 ​​WXML​​,可以构建出页面的结构。

示例

  • 新建一个wxs文件
var toDecimal2 = function (x) {
var f = parseFloat(x);
if (isNaN(f)) {
return '0.00'
}
var f = Math.round(x * 100) / 100;
var s = f.toString();
var rs = s.indexOf('.');
if (rs < 0) {
rs = s.length;
s += '.';
}
while (s.length <= rs + 2) {
s += '0';
}
return s;
}
//module.exports = toDecimal2
module.exports = {
toDecimal2:toDecimal2
}
  • 在wxml中使用
<!--pages/c/c.wxml-->
<wxs src="../../wxs/PageUtils.wxs" module="PageUtils"></wxs>
<wxs module="m1">
var msg = "hello world";

module.exports.message = msg;
</wxs>
<view>
<text>pages/c/c.wxml,</text>
<text>{{m1.message}}</text>
<view>
<text>{{PageUtils.toDecimal2(123.453)}}</text>
</view>
<view>
<button type="primary" bindtap="jump">跳转到D页面</button>
</view>
</view>

注意事项

  1. WXS 不依赖于运行时的基础库版本,可以在所有版本的小程序中运行。
  2. WXS 与 JavaScript 是不同的语言,有自己的语法,并不和 JavaScript 一致。
  3. WXS 的运行环境和其他 JavaScript 代码是隔离的,WXS 中不能调用其他 JavaScript 文件中定义的函数,也不能调用小程序提供的API。
  4. WXS 函数不能作为组件的事件回调。
  5. 由于运行环境的差异,在 iOS 设备上小程序内的 WXS 会比 JavaScript 代码快 2 ~ 20 倍。在 android 设备上二者运行效率无差异。

以下是一些使用 WXS 的简单示例,要完整了解 WXS 语法,请参考​​WXS 语法参考​​。

页面渲染

<!--wxml-->
<wxs module="m1">
var msg = "hello world";

module.exports.message = msg;
</wxs>

<view> {{m1.message}} </view>

页面输出:

hello world

数据处理

// page.js
Page({
data: {
array: [1, 2, 3, 4, 5, 1, 2, 3, 4]
}
})
<!--wxml-->
<!-- 下面的 getMax 函数,接受一个数组,且返回数组中最大的元素的值 -->
<wxs module="m1">
var getMax = function(array) {
var max = undefined;
for (var i = 0; i < array.length; ++i) {
max = max === undefined ?
array[i] :
(max >= array[i] ? max : array[i]);
}
return max;
}

module.exports.getMax = getMax;
</wxs>

<!-- 调用 wxs 里面的 getMax 函数,参数为 page.js 里面的 array -->
<view> {{m1.getMax(array)}} </view>

页面输出:

5

三、会议OA项目-首页

前言叙述

1) 小程序没有DOM对象,一切基于组件化

  1. 储备知识
  1. 理解事件机制
  2. 理解组件化
  3. 理解数据绑定
  4. Flex布局
  5. 移动端适配方案
  1. 贴心小建议
    学习vue后开发小程序更简单

目标

三、Flex布局简介_css_02

配置

  • config/api.js
// 以下是业务服务器API地址
// 本机开发API地址
var WxApiRoot = 'http://localhost:8080/demo/wx/';
// 测试环境部署api地址
// var WxApiRoot = 'http://192.168.0.101:8070/demo/wx/';
// 线上平台api地址
//var WxApiRoot = 'https://www.oa-mini.com/demo/wx/';

module.exports = {
IndexUrl: WxApiRoot + 'home/index', //首页数据接口
SwiperImgs: WxApiRoot+'swiperImgs', //轮播图
MettingInfos: WxApiRoot+'meeting/list', //会议信息
};

tabbar

  • app.json
"list": [{
"pagePath": "pages/index/index",
"text": "首页",
"iconPath": "/static/tabBar/coding.png",
"selectedIconPath": "/static/tabBar/coding-active.png"
},
{
"pagePath": "pages/meeting/list/list",
"iconPath": "/static/tabBar/sdk.png",
"selectedIconPath": "/static/tabBar/sdk-active.png",
"text": "会议"
},
{
"pagePath": "pages/vote/list/list",
"iconPath": "/static/tabBar/template.png",
"selectedIconPath": "/static/tabBar/template-active.png",
"text": "投票"
},
{
"pagePath": "pages/ucenter/index/index",
"iconPath": "/static/tabBar/component.png",
"selectedIconPath": "/static/tabBar/component-active.png",
"text": "设置"
}]

mock工具

  • imageSrcs
{
"data": {
"images":[
{
"img": "https://cdn-we-retail.ym.tencent.com/tsr/home/v2/banner1.png",
"text": "1"
},
{
"img": "https://cdn-we-retail.ym.tencent.com/tsr/home/v2/banner2.png",
"text": "2"
},
{
"img": "https://cdn-we-retail.ym.tencent.com/tsr/home/v2/banner3.png",
"text": "3"
},
{
"img": "https://cdn-we-retail.ym.tencent.com/tsr/home/v2/banner4.png",
"text": "4"
},
{
"img": "https://cdn-we-retail.ym.tencent.com/tsr/home/v2/banner5.png",
"text": "5"
},
{
"img": "https://cdn-we-retail.ym.tencent.com/tsr/home/v2/banner6.png",
"text": "6"
}
]
},
"statusCode": "200",
"header": {
"content-type":"applicaiton/json;charset=utf-8"
}
}

三、Flex布局简介_css_03

page

  • index.css
page{
height: 100%;
background-color: #efeff4;
}

swiper

  • index.wxml
<swiper indicator-dots="true" autoplay="true" circular="true" indicator-color="#fff" indicator-active-color="blue">
<block wx:for="{{images}}" wx:key="text">
<swiper-item>
<view class="swiper-item">
<image src="{{item.img}}" mode="scaleToFill"></image>
</view>
</swiper-item>
</block>
</swiper>
  • index.css
swiper {
width: 100%;
height: calc(100vw*9/16);
}
.swiper-item>image {
width:100%;
}
  • index.js
loadSwiperImgs(){
//请注意this的指向问题
let that=this;
wx.request({
url: api.SwiperImgs,
success(rs){
console.log(rs);
that.setData({
images:rs.data.images
});
}
})
}

会议信息

  • mock数据
{
"data": {
"lists": [
{
"id": "1",
"image": "/static/persons/1.jpg",
"title": "对话产品总监 | 深圳·北京PM大会 【深度对话小米/京东/等产品总监】",
"num":"304",
"state":"进行中",
"starttime": "2022-03-13 00:00:00",
"location": "深圳市·南山区"
},
{
"id": "1",
"image": "/static/persons/2.jpg",
"title": "AI WORLD 2016世界人工智能大会",
"num":"380",
"state":"已结束",
"starttime": "2022-03-15 00:00:00",
"location": "北京市·朝阳区"
},
{
"id": "1",
"image": "/static/persons/3.jpg",
"title": "H100太空商业大会",
"num":"500",
"state":"进行中",
"starttime": "2022-03-13 00:00:00",
"location": "大连市"
},
{
"id": "1",
"image": "/static/persons/4.jpg",
"title": "报名年度盛事,大咖云集!2016凤凰国际论坛邀您“与世界对话”",
"num":"150",
"state":"已结束",
"starttime": "2022-03-13 00:00:00",
"location": "北京市·朝阳区"
},
{
"id": "1",
"image": "/static/persons/5.jpg",
"title": "新质生活 · 品质时代 2016消费升级创新大会",
"num":"217",
"state":"进行中",
"starttime": "2022-03-13 00:00:00",
"location": "北京市·朝阳区"
}
]
},
"statusCode": "200",
"header": {
"content-type":"applicaiton/json;charset=utf-8"
}
}
  • index.wxml
<view class="mobi-title">
<text class="mobi-icon"></text>
<text>会议信息</text>
</view>
<block wx:for-items="{{lists}}" wx:for-item="item" wx:key="item.id">
<view class="list" data-id="{{item.id}}">
<view class="list-img">
<image class="video-img" mode="scaleToFill" src="{{item.image}}"></image>
</view>
<view class="list-detail">
<view class="list-title"><text>{{item.title}}</text></view>
<view class="list-tag">
<view class="state">{{item.state}}</view>
<view class="join"><text class="list-num">{{item.num}}</text>人报名</view>
</view>
<view class="list-info"><text>{{item.address}}</text>|<text>{{item.time}}</text></view>
</view>
</view>
</block>
<view class="section bottom-line">
<text>到底啦</text>
</view>
  • index.js
loadMeetingInfos(){
let that=this;
wx.request({
url: api.MettingInfos,
dataType: 'json',
success(res) {
console.log(res)
that.setData({
lists:res.data.lists
})
}
})
}
  • index.wxss
.mobi-title {
font-size: 12pt;
color: #777;
line-height: 110%;
font-weight: bold;
width: 100%;
padding: 15rpx;
background-color: #f3f3f3;
}

.mobi-icon {
padding: 0rpx 3rpx;
border-radius: 3rpx;
background-color: #ff7777;
position: relative;
margin-right: 10rpx;
}

/*list*/
.list {
display: flex;
flex-direction: row;
width: 100%;
padding: 0 20rpx 0 0;
border-top: 1px solid #eeeeee;
background-color: #fff;
margin-bottom: 5rpx;
/* border-radius: 20rpx;
box-shadow: 0px 0px 10px 6px rgba(0,0,0,0.1); */
}

.list-img {
display: flex;
margin: 10rpx 10rpx;
width: 150rpx;
height: 220rpx;
justify-content: center;
align-items: center;
}

.list-img .video-img {
width: 120rpx;
height: 120rpx;

}

.list-detail {
margin: 10rpx 10rpx;
display: flex;
flex-direction: column;
width: 600rpx;
height: 220rpx;
}

.list-title text {
font-size: 11pt;
color: #333;
font-weight: bold;
}

.list-detail .list-tag {
display: flex;
height: 70rpx;
}

.list-tag .state {
font-size: 9pt;
color: #81aaf7;
width: 120rpx;
border: 1px solid #93b9ff;
border-radius: 2px;
margin: 10rpx 0rpx;
display: flex;
justify-content: center;
align-items: center;
}

.list-tag .join {
font-size: 11pt;
color: #bbb;
margin-left: 20rpx;
display: flex;
justify-content: center;
align-items: center;
}

.list-tag .list-num {
font-size: 11pt;
color: #ff6666;
}

.list-info {
font-size: 9pt;
color: #bbb;
margin-top: 20rpx;
}
.bottom-line{
display: flex;
height: 60rpx;
justify-content: center;
align-items: center;
background-color: #f3f3f3;
}
.bottom-line text{
font-size: 9pt;
color: #666;
}