微信小程序开发

微信小程序开发

开发文档挺齐全的,也是借着微信这个平台.

开发模式也挺好.

不过缺点也是只能局限在这个平台,要开发手机软件还要看其他的而且现在web比较好.

开发文档

小程序简介 | 微信开放文档 (qq.com)

目录结构

image-20210831185320318

image-20210831185251774

项目配置文件

1
project.config.json

image-20210831185432310

当你重新安装工具或者换电脑工作时,你只要载入同一个项目的代码包,开发者工具就自动会帮你恢复到当时你开发项目时的个性化配置,其中会包括编辑器的颜色、代码上传时自动压缩等等一系列选项。

主体文件

1
2
3
4
5
app.json

app.js

app.wxss(可选文件)

app.json

小程序的全局配置文件.包含

  1. 小程序所有页面的路径地址
  2. 导航栏样式
  3. pages字段 —— 用于描述当前小程序所有页面路径,这是为了让微信客户端知道当前你的小程序页面定义在哪个目录。

  4. window字段 —— 定义小程序所有页面的顶部背景颜色,文字颜色定义等

还可以配置tabBar,networkTimeout,debug等属性

注意:pages记录小程序所有页面的路径地址.其中如果有多个页面地址,第一个默认为小程序初始页面

tabBar设置页面底部tab工具条表现

image-20210831192321856

window属性对应的值是对象形式

还有networkTimeout和debug

image-20210831192927512

app.js

全局逻辑文件

1
2
3
4
5
6
7
App(

{onLaunch(){},

globalData:{}

})

app.wxss

可以不写,类似于css.规定所有页面都可用的样式效果

页面配置文件

在根目录下的pages文件夹中保存所有页面文件

每一个独立的页面基本都由四种文件构成

wxml wxss js和json

由于页面的json只能写与window相关的配置无须像app.json那样复杂

sitemap.js

开发者可以通过 sitemap.json 配置,或者管理后台页面收录开关来配置其小程序页面是否允许微信索引。当开发者允许微信索引时,微信会通过爬虫的形式,为小程序的页面内容建立索引。当用户的搜索词条触发该索引时,小程序的页面将可能展示在搜索结果中。 爬虫访问小程序内页面时,会携带特定的 user-agent:mpcrawler场景值1129。需要注意的是,若小程序爬虫发现的页面数据和真实用户的呈现不一致,那么该页面将不会进入索引中。

具体配置说明

  1. 页面收录设置:可对整个小程序的索引进行关闭,小程序管理后台-功能-页面内容接入-页面收录开关;详情
  2. sitemap 配置:可对特定页面的索引进行关闭

在写网站时也会有sitemap相当于微信内对你的小程序的索引,可以设置哪些能索引到哪些不能

感觉不用改

其他文件

image-20210831193616831

utils文件夹用于存放公共js文件可以被其他文件引用

还可以自定义资源文件夹存放其他文件,如图片等

IDE使用

感觉跟vscode类似,功能还是挺多的

我就不多介绍了

图片

小程序框架

逻辑层

App Services

逻辑层主要作用是处理数据后发送给视图层渲染以及接受视图层的反馈.(一般解释)

个人认为就是后台的处理.MVVM结构

JavaScript 的基础上,增加了一些功能,以方便小程序的开发:

  • 增加 AppPage 方法,进行程序注册页面注册
  • 增加 getAppgetCurrentPages 方法,分别用来获取 App 实例和当前页面栈。
  • 提供丰富的 API,如微信用户数据,扫一扫,支付等微信特有能力。
  • 提供模块化能力,每个页面有独立的作用域

注意:小程序框架的逻辑层并非运行在浏览器中,因此 JavaScript 在 web 中一些能力都无法使用,如 windowdocument 等。

注册程序

App()

只能写在app.js内且只能注册一个

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
App({
onLaunch (options) {
// Do something initial when launch.
},
onShow (options) {
// Do something when show.
},
onHide () {
// Do something when hide.
},
onError (msg) {
console.log(msg)
},
globalData: 'I am global data'
})
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
App({

/**
* 当小程序初始化完成时,会触发 onLaunch(全局只触发一次)
*/
onLaunch: function () {

},

/**
* 当小程序启动,或从后台进入前台显示,会触发 onShow
*/
onShow: function (options) {

},

/**
* 当小程序从前台进入后台,会触发 onHide
*/
onHide: function () {

},

/**
* 当小程序发生脚本错误,或者 api 调用失败时,会触发 onError 并带上错误信息
*/
onError: function (msg) {

}

小程序后台就是按Home键或某些按钮将小程序退到后台

onLaunch()和onShow()方法在触发时会返回参数

globalData可以自由定义

onpageNotFound()

当需要打开的页面不催在时,微信客户端会有一个原生模板页面提示.如果想更改可以用这个方法

getApp()

获取小程序实例

整个小程序只有一个 App 实例,是全部页面共享的。开发者可以通过 getApp 方法获取到全局唯一的 App 实例,获取App上的数据或调用开发者注册在 App 上的函数。

1
2
3
// xxx.js
const appInstance = getApp()
console.log(appInstance.globalData) // I am global data

注册页面

对于小程序中的每个页面,都需要在页面对应的 js 文件中进行注册,指定页面的初始数据、生命周期回调、事件处理函数等。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
//index.js
Page({
data: {
text: "This is page data."
},
onLoad: function(options) {
// 页面创建时执行
},
onShow: function() {
// 页面出现在前台时执行
},
onReady: function() {
// 页面首次渲染完毕时执行
},
onHide: function() {
// 页面从前台变为后台时执行
},
onUnload: function() {
// 页面销毁时执行
},
onPullDownRefresh: function() {
// 触发下拉刷新时执行
},
onReachBottom: function() {
// 页面触底时执行
},
onShareAppMessage: function () {
// 页面被用户分享时执行
},
onPageScroll: function() {
// 页面滚动时执行
},
onResize: function() {
// 页面尺寸变化时执行
},
onTabItemTap(item) {
// tab 点击时执行
console.log(item.index)
console.log(item.pagePath)
console.log(item.text)
},
// 事件响应函数
viewTap: function() {
this.setData({
text: 'Set some data for updating view.'
}, function() {
// this is setData callback
})
},
// 自由数据
customData: {
hi: 'MINA'
}
})

初始数据

data属性 当页面加载时由逻辑层到渲染层因此data数据必须是可以转化成json的类型

wxml可以进行数据绑定

WXML 通过 { {变量名}} 来绑定 WXML 文件和对应的 JavaScript 文件中的 data 对象属性。

生命周期回调函数

Page()函数中会生成onLoad(),onShow()等

image-20210831204052874

image-20210831204116813

  • navigateTo, redirectTo 只能打开非 tabBar 页面。
  • switchTab 只能打开 tabBar 页面。
  • reLaunch 可以打开任意页面。
  • 页面底部的 tabBar 由页面决定,即只要是定义为 tabBar 的页面,底部都有 tabBar。
  • 调用页面路由带的参数可以在目标页面的onLoad中获取。

页面事件处理函数

Pages中的 onPullDownRefresh(),onReachBottom()等

组件事件处理函数

在wxml上定义事件绑定,事件触发时调用Page()中对应的事件处理函数

rout

利用this.route查看当前页面路径地址

setData()

在Pages()中同步更新data属性中的数据值也异步更新相关数据到wxml页面。

也可以在pages中利用this.data调用数据

生命周期

https://res.wx.qq.com/wxdoc/dist/assets/img/page-lifecycle.2e646c86.png

页面路由见路由

小程序应用打开时首先onLaunch()

页面打开时首先onLoad(),初次渲染onReady()

模块化

可以将一些公共的代码抽离成为一个单独的 js 文件,作为一个模块。模块只有通过 module.exports 或者 exports 才能对外暴露接口。

注意:

  • exportsmodule.exports 的一个引用,因此在模块里边随意更改 exports 的指向会造成未知的错误。所以更推荐开发者采用 module.exports 来暴露模块接口,除非你已经清晰知道这两者的关系。
  • 小程序目前不支持直接引入 node_modules , 开发者需要使用到 node_modules 时候建议拷贝出相关的代码到小程序的目录中,或者使用小程序支持的 npm 功能。

文件作用域

在小程序的任意js文件声明的变量和函数只在该文件有效

不同js文件声明相同名字的变量和函数不会相互影响

通过全局函数 getApp 可以获取全局的应用实例,如果需要全局的数据可以在 App() 中设置

模块调用

可以将公共的js放在一个文件中

只能通过module.exports或exports对外提供接口

API

为了让开发者可以很方便的调起微信提供的能力,例如获取用户信息、微信支付等等,小程序提供了很多 API 给开发者去使用。

需要注意的是:多数 API 的回调都是异步,你需要处理好代码逻辑的异步问题。

  • 网络
  • 媒体
  • 文件
  • 数据
  • 位置
  • 设备
  • 界面

视图层

WXML

类似HTML

1
2
3
<!-- 在此处写注释 -->

<标签名 属性名1="属性值1" 属性名2="属性值2" ...> ...</标签名>

1.数据绑定

1.简单绑定

利用{ {}}形式表示动态数据,这个数据在js文件data中定义

如果需要在用户输入的同时改变 this.data.value ,需要借助简易双向绑定机制。此时,可以在对应项目之前加入 model: 前缀:

1
<input model:value="{ {value}}" />

这样,如果输入框的值被改变了, this.data.value 也会同时改变。同时, WXML 中所有绑定了 value 的位置也会被一同更新, 数据监听器 也会被正常触发。

注意:只能单一字段绑定且不能data路径

2.组件属性

绑定属性值也可以动态的去改变,有所不同的是,属性值必须被包裹在双引号中

‘{ {}}’ 加个引号

1
<text data-test="{ {test}}"> hello world</text>

3.控制属性绑定

控制属性也可以使用动态数据

1
<view wx:if='{ {condition}}'>测试</view><------------>Page(    {    data:    {    condition:false;    }    })

4.关键字绑定

直接在引号内写布尔值也必须用双括号括起来

5.运算绑定

6.组合绑定

上面这几个挺好理解的

注意组合绑定不仅可以绑定数组也可以绑定其他对象

2.逻辑语法

可以在{ {}}中进行简单逻辑计算

1
<text>{ { a === 10? "变量 a 等于10": "变量 a 不等于10"}}</text>

{ { }}中还可以直接放置数字、字符串或者是数组

1
<text>{ {[1,2,3]}}</text><!-- 输出 1,2,3 --><text>{ {"hello world"}}</text><!-- 输出 hello world -->

条件逻辑

WXML 中,使用 wx:if=”{ {condition}}” 来判断是否需要渲染该代码块:

1
<view wx:if="{ {condition}}"> True </view>

使用 wx:elif 和 wx:else 来添加一个 else 块:

1
<view wx:if="{ {length > 5}}"> 1 </view><view wx:elif="{ {length > 2}}"> 2 </view><view wx:else> 3 </view>

因为 wx:if 是一个控制属性,需要将它添加到一个标签上。如果要一次性判断多个组件标签,可以使用一个 <block/> 标签将多个组件包装起来,并在上边使用 wx:if 控制属性。

1
<block wx:if="{ {true}}">  <view> view1 </view>  <view> view2 </view></block>

模板

WXML提供模板(template),可以在模板中定义代码片段,然后在不同的地方调用。使用 name 属性,作为模板的名字。然后在 <template/> 内定义代码片段

定义模板

1
<template name="msgItem">  <view>    <text> { {index}}: { {msg}} </text>    <text> Time: { {time}} </text>  </view></template>

使用 is 属性,声明需要的使用的模板,然后将模板所需要的 data 传入

模板使用示例

1
<!--item: {  index: 0,  msg: 'this is a template',  time: '2016-06-18'}--><template name="msgItem">  <view>    <text> { {index}}: { {msg}} </text>    <text> Time: { {time}} </text>  </view></template><template is="msgItem" data="{ {...item}}"/><!-- 输出0: this is a template Time: 2016-06-18-->

可以使用…符号将对象内容展开显示

如果对象中元素key和value相同可以省略表达

如果有相同的key则后者覆盖前者

列表渲染

1.简单渲染

在组件上使用 wx:for 控制属性绑定一个数组,即可使用数组中各项的数据重复渲染该组件。默认数组的当前项的下标变量名默认为 index,数组当前项的变量名默认为 item

1
<view wx:for='{ {array} }'>{ {index} }:{ {item} }</view>
1
Page(    data:{    array:['张三','李四']    })

使用 wx:for-item 指定数组当前元素的变量名,使用 wx:for-index 指定数组当前下标的变量名,即自定义当前元素和下表的变量名

注意,如果没有双括号,会直接将字符串当作数组拆开

2.嵌套列表

即使用

1
<view wx:for="{ {array}}" wx:for-item='i'>    <view wx:for='{ {arrray}}' wx:for-item='j'>        <view wx:if='{ {}}'>

3.多节点列表

类似 block wx:if ,也可以将 wx:for 用在 <block/> 标签上,以渲染一个包含多节点的结构块。例如:

1
<block wx:for="{ {[1, 2, 3]}}">  <view> { {index}}: </view>  <view> { {item}} </view></block>

4.wx:key属性

如果列表中项目的位置会动态改变或者有新的项目添加到列表中,并且希望列表中的项目保持自己的特征和状态(如 <input/> 中的输入内容, <switch/> 的选中状态),需要使用 wx:key 来指定列表中项目的唯一的标识符。

wx:key 的值以两种形式提供:

  1. 字符串,代表在 for 循环的 array 中 item 的某个 property,该 property 的值需要是列表中唯一的字符串或数字,且不能动态改变。
  2. 保留关键字 this 代表在 for 循环中的 item 本身,这种表示需要 item 本身是一个唯一的字符串或者数字,如:

当数据改变触发渲染层重新渲染的时候,会校正带有 key 的组件,框架会确保他们被重新排序,而不是重新创建,以确保使组件保持自身的状态,并且提高列表渲染时的效率。

条件渲染

1.简单条件

使用wx:if=”{ {condition}}”判断是否需要渲染

2.多节点条件

同理

在\中嵌入组件

3.wx:if hidden

如果是wx:if只有当真时才会开始渲染

hidden初始就会渲染,只是简单地控制显示和隐藏

事件

UI界面的程序需要和用户互动,例如用户可能会点击你界面上某个按钮,又或者长按某个区域,这类反馈应该通知给开发者的逻辑层,需要将对应的处理状态呈现给用户。
有些时候程序上的“行为反馈”不一定是用户主动触发的,例如我们在视频video播放的过程中,播放进度是会一直变化的,这种反馈也应该通知给开发者做相应的逻辑处理。

视图层到逻辑层的通信方式

  1. 将用户行为反馈到逻辑层进行处理
  2. 可以绑定在组件中,当触发事件时就会执行逻辑层中对应的事件处理函数
  3. 对象可以携带额外的信息

1.事件的使用

1
<button id="mybtn" bindtap="myTap" data-my="hello" data-i="fuck">按钮</button>

bind与catch

2.事件的分类

冒泡事件与非冒泡事件

冒泡事件被触发后会向父节点传递

3.事件绑定和冒泡

key=value

事件绑定的写法类似于组件的属性,如:

1
<view bindtap="handleTap">    Click here!</view>

如果用户点击这个 view ,则页面的 handleTap 会被调用。

事件绑定函数可以是一个数据绑定,如:

1
<view bindtap="{ { handlerName }}">    Click here!</view>

catch事件可以阻止冒泡事件向上冒泡

4.事件的捕获阶段

自基础库版本 1.5.0 起,触摸类事件支持捕获阶段。捕获阶段位于冒泡阶段之前,且在捕获阶段中,事件到达节点的顺序与冒泡阶段恰好相反。需要在捕获阶段监听事件时,可以采用capture-bindcapture-catch关键字,后者将中断捕获阶段和取消冒泡阶段

5.事件对象

image-20210901105757525

image-20210901105827504

type

代表事件的类型。

timeStamp

页面打开到触发事件所经过的毫秒数。

target

触发事件的源组件。

属性类型说明
idString事件源组件的id
datasetObject事件源组件上由data-开头的自定义属性组成的集合

currentTarget

事件绑定的当前组件。

属性类型说明
idString当前组件的id
datasetObject当前组件上由data-开头的自定义属性组成的集合
dataset

在组件节点中可以附加一些自定义数据。这样,在事件中可以获取这些自定义的节点数据,用于事件的逻辑处理。

在 WXML 中,这些自定义数据以 data- 开头,多个单词由连字符 - 连接。这种写法中,连字符写法会转换成驼峰写法,而大写字符会自动转成小写字符。如:

  • data-element-type ,最终会呈现为 event.currentTarget.dataset.elementType
  • data-elementType ,最终会呈现为 event.currentTarget.dataset.elementtype

6.引用

1.import

在 index.wxml 中引用了 item.wxml,就可以使用 item模板:

1
<import src="item.wxml"/><template is="item" data="{ {text: 'forbar'}}"/>

需要注意的是 import 有作用域的概念,即只会 import 目标文件中定义的 template,而不会 import 目标文件中 import 的 template,简言之就是 import 不具有递归的特性。

2.include

include 可以将目标文件中除了 <template/> <wxs/> 外的整个代码引入,相当于是拷贝到 include 位置

WXSS

1.尺寸单位

rpx 规定屏幕为750rpx

2.样式导入

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

3.内联样式

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

  • style:静态的样式统一写到 class 中。style 接收动态的样式,在运行时会进行解析,请尽量避免将静态的样式写进 style 中,以免影响渲染速度。
1
<view style="color:{ {color}};" />
  • class:用于指定样式规则,其属性值是样式规则中类选择器名(样式类名)的集合,样式类名不需要带上.,样式类名之间用空格分隔。
1
<view class="normal_view" />

4.选择器

选择器样例样例描述
.class.intro选择所有拥有 class=”intro” 的组件
#id#firstname选择拥有 id=”firstname” 的组件
elementview选择所有 view 组件
element, elementview, checkbox选择所有文档的 view 组件和所有的 checkbox 组件
::afterview::after在 view 组件后边插入内容
::beforeview::before在 view 组件前边插入内容

5.全局样式与局部样式

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

Flex布局

包含内容的组件称为容器,容器内部的组件成为项目

我们只需要在容器中设置以下两个属性即可实现内容不确定下的垂直居中。

1
.container{  display: flex;  flex-direction: column;  justify-content: center;}

flex不单是一个属性,它包含了一套新的属性集。属性集包括用于设置容器,和用于设置项目两部分。

设置容器的属性有:

1
display:flex;flex-direction:row(默认值) | row-reverse | column |column-reverseflex-wrap:nowrap(默认值) | wrap | wrap-reversejustify-content:flex-start(默认值) | flex-end | center |space-between | space-around | space-evenlyalign-items:stretch(默认值) | center  | flex-end | baseline | flex-startalign-content:stretch(默认值) | flex-start | center |flex-end | space-between | space-around | space-evenly

项目是在主轴上排列,排满后在交叉轴方向换行。需要注意的是,交叉轴垂直于主轴,它的方向取决于主轴方向。

flex-direction 属性

通过设置坐标轴,来设置项目排列方向。

1
.container{  flex-direction: row(默认值) | row-reverse | column | column-reverse}

row(默认值):主轴横向,方向为从左指向右。项目沿主轴排列,从左到右排列。

row-reverse:row的反方向。主轴横向,方向为从右指向左。项目沿主轴排列,从右到左排列。

column:主轴纵向,方向从上指向下。项目沿主轴排列,从上到下排列。

column-reverse:column的反方向。主轴纵向,方向从下指向上。项目沿主轴排列,从下到上排列。

flex-wrap 属性

设置是否允许项目多行排列,以及多行排列时换行的方向。

1
.container{  flex-wrap: nowrap(默认值) | wrap | wrap-reverse}

nowrap(默认值):不换行。如果单行内容过多,则溢出容器。
wrap:容器单行容不下所有项目时,换行排列。
wrap-reverse:容器单行容不下所有项目时,换行排列。换行方向为wrap时的反方向。

justify-content 属性

设置项目在主轴方向上对齐方式,以及分配项目之间及其周围多余的空间。

1
.container{  justify-content: flex-start(默认值) | flex-end | center | space-between | space-around| space-evenly}

flex-start(默认值):项目对齐主轴起点,项目间不留空隙。

center:项目在主轴上居中排列,项目间不留空隙。主轴上第一个项目离主轴起点距离等于最后一个项目离主轴终点距离。

flex-end:项目对齐主轴终点,项目间不留空隙。
space-between:项目间间距相等,第一个项目离主轴起点和最后一个项目离主轴终点距离为0。
space-around:与space-between相似。不同点为,第一个项目离主轴起点和最后一个项目离主轴终点距离为中间项目间间距的一半。

space-evenly:项目间间距、第一个项目离主轴起点和最后一个项目离主轴终点距离等于项目间间距。

align-items 属性

设置项目在行中的对齐方式。

1
.container{  align-items:stretch(默认值) | flex-start | center | flex-end | baseline}

stretch(默认值):项目拉伸至填满行高。
flex-start:项目顶部与行起点对齐。
center:项目在行中居中对齐。
flex-end:项目底部与行终点对齐。
baseline:项目的第一行文字的基线对齐。

align-content 属性

多行排列时,设置行在交叉轴方向上的对齐方式,以及分配行之间及其周围多余的空间。

1
.container{  align-content: stretch(默认值) | flex-start | center | flex-end | space-between |space-around | space-evenly}

stretch(默认值):当未设置项目尺寸,将各行中的项目拉伸至填满交叉轴。当设置了项目尺寸,项目尺寸不变,项目行拉伸至填满交叉轴。

flex-start:首行在交叉轴起点开始排列,行间不留间距。

center:行在交叉轴中点排列,行间不留间距,首行离交叉轴起点和尾行离交叉轴终点距离相等。

flex-end:尾行在交叉轴终点开始排列,行间不留间距。
space-between:行与行间距相等,首行离交叉轴起点和尾行离交叉轴终点距离为0。
space-around:行与行间距相等,首行离交叉轴起点和尾行离交叉轴终点距离为行与行间间距的一半。

space-evenly:行间间距、以及首行离交叉轴起点和尾行离交叉轴终点距离相等。

项目属性

设置项目,用于设置项目的尺寸、位置,以及对项目的对齐方式做特殊设置。

order 属性

设置项目沿主轴方向上的排列顺序,数值越小,排列越靠前。属性值为整数。

1
.item{  order: 0(默认值) | <integer>}

flex-shrink 属性

当项目在主轴方向上溢出时,通过设置项目收缩因子来压缩项目适应容器。属性值为项目的收缩因子,属性值取非负数。

1
.item{  flex-shrink: 1(默认值) | <number>}.item1{  width: 120px;  flex-shrink: 2;}.item2{  width: 150px;  flex-shrink: 3;}.item3{// 项目3未设置flex-shrink,默认flex-shrink值为1  width: 180px;}

flex-grow 属性

当项目在主轴方向上还有剩余空间时,通过设置项目扩张因子进行剩余空间的分配。属性值为项目的扩张因子,属性值取非负数。

1
.item{  flex-grow: 0(默认值) | <number>}

flex-basis 属性

当容器设置flex-direction为row或row-reverse时,flex-basis和width同时存在,flex-basis优先级高于width,也就是此时flex-basis代替项目的width属性。

当容器设置flex-direction为column或column-reverse时,flex-basis和height同时存在,flex-basis优先级高于height,也就是此时flex-basis代替项目的height属性。

需要注意的是,当flex-basis和width(或height),其中一个属性值为auto时,非auto的优先级更高。

1
2
3
4
5
.item{

flex-basis: auto(默认值) | <number>px

}

flex 属性

是flex-grow,flex-shrink,flex-basis的简写方式。值设置为none,等价于00 auto。值设置为auto,等价于1 1 auto。

1
2
3
4
5
.item{

flex: none | auto | @flex-grow @flex-shrink@flex-basis

}

align-self 属性

设置项目在行中交叉轴方向上的对齐方式,用于覆盖容器的align-items,这么做可以对项目的对齐方式做特殊处理。默认属性值为auto,继承容器的align-items值,当容器没有设置align-items时,属性值为stretch。

1
2
3
4
5
.item{

align-self: auto(默认值) | flex-start | center | flex-end | baseline |stretch

}
-------------本文结束感谢您的阅读-------------
感谢阅读.

欢迎关注我的其它发布渠道