整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:

一个月带你入门Flutter:UI篇(4)-一文搞定Flutter中的交互

Flutter系列的文章我会持续更新一个月左右,力求利用1个月带大家入门Flutter,抓住这波技术风口,欢迎大家关注。同时如果觉得这里代码排版不是很舒服的读者可以关注我的微信公众号“IT工匠”,我会同步更新,另外微信公众号上还有很多互联网必备资源(涉及算法、数据结构、java、深度学习、计算机网络、python、Android等互联网技术资料),欢迎大家关注、交流。

文的主要内容:

  • 如何响应点击事件
  • 如何自定义Widget
  • Stateless Widget和Stateful Widget的不同

Flutter中按照是否自身可直接响应用户交互可以将Widget分为两类:

  • 第一类:自身可直接响应用户交互,指的是Widget自身具有如onTap这类的属性,可以通过这类属性直接监听用户的点击等事件,典型的比如FlatButton等
  • 第二类:自身不能直接响应用户交互,指的是Widget自身没有入onTap这类属性,不能直接监听用户的点击等事件,典型的比如Icon等

由于第一类比较简单,本文重点介绍一下第二类,即如何为非交互性(不能直接响应用户交互)的Widget添加交互性, 具体来说,我们将通过创建一个自定义的Statful Widget来让Icon具有交互性。

在上一篇文章中我们介绍了如何构建一个下面这样的UI页面:

当这个app第一次运行的时候那个星星是红色的,代表这个屏幕中展示的那个图片被用户点击了喜欢,星星后面的数字47代表一共有47个用户点击了喜欢。本文将实现,点击星星后移除喜欢状态,用空心星星替换实心星星并减少星星后面的计数。 再次点击空心星星代表添加喜欢,会绘制一颗实心的星星并增加星星后的数字。

要实现此功能,您将创建一个包含星星和计数的自定义Widget, 点击星星会更改两个子Widget的状态,因此自定义的Widget应该同时管理这两个子Widget(星星和计数)。

首先我将会介绍一点前备知识,如果你只对最终的代码实现感兴趣,你可以直接跳到第2步:创建StatefulWidget的子类,如果你想尝试其他的管理状态的方法,可以直接跳到管理状态一节。

Stateful Widget和Stateless Widget

一个Widget要么是有状态(stateful)的,要么是无状态(stateless)的,如果一个Widget是可改变的,比如当用户与其交互的时候其会产生变化,这个Widget就是有状态的(stateful)。

一个无状态(stateless)的Widget是永远不会发生改变的,Icon、IconButton、Text都是典型的无状态的Widget,无状态(stateless)的Widget都是StatelessWidget的子类。

一个有状态(stateful)的Widget是动态的,比如它可以更改其外观以响应用户交互或接收数据时触发的事件。CheckBox、Radio、Slider、InkWell、Form、TextField都是典型的有状态的Widget,有状态(stateful)的Widget都是StatefulWidget的子类。

Widget的状态都是保存在State对象中的,从外观上分析小部件的状态。 状态由可以更改的值组成,例如滑块(slider)的当前值、是否选中复选框(CheckBox)。 当Widget的状态发生变化时,State对象调用会setState()方法来告诉框架重绘该Widget。

创建一个有状态的(stateful)Widget

明确几点概念:

  • 一个有状态的Widget一定实现了2个类:StatefulWidget、State
  • State类包含Widget的可变状态以及build()方法
  • 当Widget的状态(state)发生了改变,State对象将会调用setState()方法高速Flutter框架需要重绘当前Widget

本节将创建一个自定义的有状态(Stateful)的Widget,我们将用我们自定义的包含一个IconButton和一个Text的Widget来替代原有的红色星星Widget和计数Widget。

实现一个自定义的Widget需要创建2个类:

  • 一个StatefulWidget类的子类,用于定义Widget
  • 一个State类的子类,包含了State对象,并且定义build()方法

我们通过简单的几步来构建一个名为FavoriteWidget的自定义Widget:

第1步:决定由那个对象来管理Widget的状态(State)

Widget的状态(State)可以有多种管理方式,在此处由于切换星星的状态(实心还是空心)是一个独立的操作,不会影响父Widget或UI的其余部分,所以我们让Widget自己管理自己的状态(State)。

关于详细的状态管理的内容,我会在后面的管理状态一节介绍。

<span id="subclass-statefulWidget">第2步:创建StatefulWidget的子类</span>

由于第1步我们已经决定了FavoriteWidget自己管理自己的状态(State),所以我们应该重写createState()方法来创建一个State对象。Flutter框架会在构建Widget的时候调用对应Widget的createState()方法。在这个例子中,我们应该在createState()方法中返回一个我们将在下一步定义的_FavoriteWidgetState类的实例对象:

class FavoriteWidget extends StatefulWidget {
 @override
 _FavoriteWidgetState createState() => _FavoriteWidgetState();
}

注意:这里的_开头指的是定义的对应类是私有的。

第3步:创建State类的子类

我们定义一个_FavoriteWidgetState类来存储会在Widget不同生命周期变化的数据,当app第一次运行的时候,UI界面应该展示红色的实心星星,代表当前已经选择了”喜欢”状态,并且傍边展示的文字为”41”,我们本别使用bool _isFavorited和int _favoriteCount变量来存储这两个状态:

class _FavoriteWidgetState extends State<FavoriteWidget> {
 bool _isFavorited = true;
 int _favoriteCount = 41;
 // ···
}

_FavoriteWidgetState类同样也定义了一个build()方法,在该方法中创建一个Row(行),Row中包含有一个Iconbutton和一个Text,我们使用Iconbutton而不是Icon的原因是IconButton有onPressed属性,我们可以通过这个onPressed属性定义处理点击事件的回调函数(_toggleFavorite),我们将在后面具体定义这个_toggleFavorite函数:

class _FavoriteWidgetState extends State<FavoriteWidget> {
 // ···
 @override
 Widget build(BuildContext context) {
 return Row(
 mainAxisSize: MainAxisSize.min,
 children: [
 Container(
 padding: EdgeInsets.all(0),
 child: IconButton(
 icon: (_isFavorited ? Icon(Icons.star) : Icon(Icons.star_border)),
 color: Colors.red[500],
 onPressed: _toggleFavorite,
 ),
 ),
 SizedBox(
 width: 18,
 child: Container(
 child: Text('$_favoriteCount'),
 ),
 ),
 ],
 );
 }
}

注意:我们这里将Text作为子Widget放置在了SizedBox中,并且设置了SizedBox的宽度,这样做的作用是固定Text的宽度,设想一下,当Text中只显示1位数字的时候Text的宽度和显示2位数字的宽度一定是不一样的,如果不固定Text的宽度,当数字变化的时候就会出现Text宽度发生跳变的情况,导致视觉效果很不好。

当IconButton被点击的时候将会调用_toggleFavorite()方法,我们在_toggleFavorite()方法中调用setstate()方法并更新状态,这样Flutter框架就会知道需要重新绘制当前Widget了,从而达到更新界面的效果:

void _toggleFavorite() {
 setState(() {
 if (_isFavorited) {
 _favoriteCount -= 1;
 _isFavorited = false;
 } else {
 _favoriteCount += 1;
 _isFavorited = true;
 }
 });
}

setState()方法中的代码逻辑很简单,首先判断当前_isFavorited的状态,然后对_isFavorited和_isFavorited的值进行更新。

第4步:将我们自定义的Stateful Widget加入到Widget树中

我们应该在app的build()方法中将我们自定义的Stateful Widget加入到Widget 树中,首先找到原先Icon和Text的位置,然后删除原来的代码,加入新的我们创建的Stateful Widget:

 Widget titleSection = Container(
 padding: const EdgeInsets.all(32),
 child: Row(
 children: [
 Expanded(
 /*1*/
 child: Column(
 crossAxisAlignment: CrossAxisAlignment.start,
 children: [
 /*2*/
 Container(
 padding: const EdgeInsets.only(bottom: 8),
 child: Text(
 'Oeschinen Lake Campground',
 style: TextStyle(
 fontWeight: FontWeight.bold,
 ),
 ),
 ),
 Text(
 'Kandersteg, Switzerland',
 style: TextStyle(
 color: Colors.grey[500],
 ),
 ),
 ],
 ),
 ),
 FavoriteWidget(),
 ],
 ),
 );

然后运行代码(推荐使用热更新),可以看到效果图:

管理状态

在我们的设计中,到底应该由谁来管理Widget的状态(State)?是Widget本身?是Widget的父Widget?还是二者共同管理?还是另一个对象来管理? 事实上有不止一种有效的方法可以使你的Widget小部件具有交互性, 作为Widget的设计者,你可以根据预期的Widget的使用方式做出决策。 以下是几种最常用的管理状态的方法:

  • 第一种:Widget自己管理自己本身的State
  • 第二种:Widget的父级Widget管理其State
  • 第三种:混合使用前两种方法

你可能会有疑问,你应该如何决定具体使用哪一种状态管理方法?这里提供几个原则供你参考:

  • 如果状态代表的是用户数据,比如CheckBox是否被选中,或者Slider(进度条)的当前进度,这种情况下最好让Widget的父级Widget去管理其状态
  • 如果状态代表的是界面展示方面的,比如动画,这种情况最好由Widget自己来管理自己的状态

如果你不太确定自己的场景属于以上哪种,可以直接使用父级Widget管理的方法,因为这个方法是通用的。

接下来我将通过创建三个简单示例(TapboxA,TapboxB和TapboxC)来举例说明管理状态的不同方法。 这几个示例的工作方式类似: 每个都创建了一个Container,当点击时,可以在绿色或灰色框之间切换, _active布尔值确定颜色:true代表绿色,false代表灰色。

Widget自己管理自己本身的State

有时,由Widget自己管理自己的状态可以产生很强大的功能。例如,ListView在其内容的总尺寸超出其最大渲染框的尺寸时会自动进行滚动,这个滚动的状态是由ListView自己管理的,不需要我们开发人员去手动设置它什么时候应该开始滚动、什么时候应该停止滚动。

我们通过一个示例来进行说明,我们创建一个_TapboxAState类:

  • 管理TapboxA的状态
  • 定义布尔值_activity,代表当前Widget的颜色
  • 定义_handleTap()方法,当Widget被点击时在该方法中调用setState()并更新 _activity的值从而达到更新UI的目的
  • 实现Widget的所有交互行为

代码如下:

// TapboxA 自己管理自己的状态
//------------------------- TapboxA ----------------------------------
class TapboxA extends StatefulWidget {
 TapboxA({Key key}) : super(key: key);
 @override
 _TapboxAState createState() => _TapboxAState();
}
class _TapboxAState extends State<TapboxA> {
 bool _active = false;
 void _handleTap() {
 setState(() {
 _active = !_active;
 });
 }
 Widget build(BuildContext context) {
 return GestureDetector(
 onTap: _handleTap,
 child: Container(
 child: Center(
 child: Text(
 _active ? 'Active' : 'Inactive',
 style: TextStyle(fontSize: 32.0, color: Colors.white),
 ),
 ),
 width: 200.0,
 height: 200.0,
 decoration: BoxDecoration(
 color: _active ? Colors.lightGreen[700] : Colors.grey[600],
 ),
 ),
 );
 }
}
//------------------------- MyApp ----------------------------------
class MyApp extends StatelessWidget {
 @override
 Widget build(BuildContext context) {
 return MaterialApp(
 title: 'Flutter Demo',
 home: Scaffold(
 appBar: AppBar(
 title: Text('Flutter Demo'),
 ),
 body: Center(
 child: TapboxA(),
 ),
 ),
 );
 }
}

运行效果如下图所示:

Widget的父级Widget管理其State

父Widget管理子Widget状态的最大用处是在合适的时机通知子Widget进行UI更新。 例如,IconButton允许你将Icon视为可点击的按钮, IconButton是一个无状态的Widget,所以我们应该通过父Widget来确定Iconutton是否已被点击。

在以下例子中,TapboxB将其状态回调给父Widget,因为TapboxB不管理任何状态,所以它是StatelessWidget的子类。

在这个示例中我们应该实现2个类:ParentWidgetState(代表父Widget)、TapboxB(代表子Widget)

ParentWidgetState的主要功能:

  • 为TapboxB管理_activity状态
  • 实现 _handleTapboxChanged()方法,该方法会在TapboxB被点击时调用
  • 当状态发生改变时调用setState()来更新UI

TapboxB的主要功能:

  • 继承StatelessWidget类,因为TapboxB不用管理自己的状态
  • 当点击事件(tap)被触发的时候通知父Widget

代码实现如下:

// ParentWidget为TapboxB管理状态.
//------------------------ ParentWidget --------------------------------
class ParentWidget extends StatefulWidget {
 @override
 _ParentWidgetState createState() => _ParentWidgetState();
}
class _ParentWidgetState extends State<ParentWidget> {
 bool _active = false;
 void _handleTapboxChanged(bool newValue) {
 setState(() {
 _active = newValue;
 });
 }
 @override
 Widget build(BuildContext context) {
 return Container(
 child: TapboxB(
 active: _active,
 onChanged: _handleTapboxChanged,
 ),
 );
 }
}
//------------------------- TapboxB ----------------------------------
class TapboxB extends StatelessWidget {
 TapboxB({Key key, this.active: false, @required this.onChanged})
 : super(key: key);
 final bool active;
 final ValueChanged<bool> onChanged;
 void _handleTap() {
 onChanged(!active);
 }
 Widget build(BuildContext context) {
 return GestureDetector(
 onTap: _handleTap,
 child: Container(
 child: Center(
 child: Text(
 active ? 'Active' : 'Inactive',
 style: TextStyle(fontSize: 32.0, color: Colors.white),
 ),
 ),
 width: 200.0,
 height: 200.0,
 decoration: BoxDecoration(
 color: active ? Colors.lightGreen[700] : Colors.grey[600],
 ),
 ),
 );
 }
}

代码的运行效果如下:

混合使用前两种管理方法

对于某些Widget,使用混合的方法管理其状态很有有意义。 在这种情况下,有状态(stateful)的Widget和其父Widget分别管理其一部分状态(State)。

在TapboxC示例中,在点击时,框周围会出现深绿色边框,点击后,边框消失,框的颜色也会改变。 TapboxC将其 _active状态导出到其父Widget,在内部管理只其 _highlight状态,所以 此示例有两个State对象,_ParentWidgetState和_TapboxCState:

_ParentWidgetState的功能:

  • 管理_activity状态
  • 实现_handleTapboxChanged()方法,该方法会在方框被点击后调用
  • 当点击事件发生后调用setState()并改变_activity的值以更新UI

_TapboxCState的功能:

  • 管理_highlight状态
  • GestureDetector监听所有的点击事件,当用户手指点下的时候添加高亮边框,当用户手指抬起的时候取消高亮边框
  • 当点击事件发生时,根据父Widget传递的状态进行相应操作
//---------------------------- ParentWidget ----------------------------
class ParentWidget extends StatefulWidget {
 @override
 _ParentWidgetState createState() => _ParentWidgetState();
}
class _ParentWidgetState extends State<ParentWidget> {
 bool _active = false;
 void _handleTapboxChanged(bool newValue) {
 setState(() {
 _active = newValue;
 });
 }
 @override
 Widget build(BuildContext context) {
 return Container(
 child: TapboxC(
 active: _active,
 onChanged: _handleTapboxChanged,
 ),
 );
 }
}
//----------------------------- TapboxC ------------------------------
class TapboxC extends StatefulWidget {
 TapboxC({Key key, this.active: false, @required this.onChanged})
 : super(key: key);
 final bool active;
 final ValueChanged<bool> onChanged;
 _TapboxCState createState() => _TapboxCState();
}
class _TapboxCState extends State<TapboxC> {
 bool _highlight = false;
 void _handleTapDown(TapDownDetails details) {
 setState(() {
 _highlight = true;
 });
 }
 void _handleTapUp(TapUpDetails details) {
 setState(() {
 _highlight = false;
 });
 }
 void _handleTapCancel() {
 setState(() {
 _highlight = false;
 });
 }
 void _handleTap() {
 widget.onChanged(!widget.active);
 }
 Widget build(BuildContext context) {
 // This example adds a green border on tap down.
 // On tap up, the square changes to the opposite state.
 return GestureDetector(
 onTapDown: _handleTapDown, // Handle the tap events in the order that
 onTapUp: _handleTapUp, // they occur: down, up, tap, cancel
 onTap: _handleTap,
 onTapCancel: _handleTapCancel,
 child: Container(
 child: Center(
 child: Text(widget.active ? 'Active' : 'Inactive',
 style: TextStyle(fontSize: 32.0, color: Colors.white)),
 ),
 width: 200.0,
 height: 200.0,
 decoration: BoxDecoration(
 color:
 widget.active ? Colors.lightGreen[700] : Colors.grey[600],
 border: _highlight
 ? Border.all(
 color: Colors.teal[700],
 width: 10.0,
 )
 : null,
 ),
 ),
 );
 }
}

运行效果如下所示:

替代实现可能已将高亮状态导出到父级,同时保持活动状态为内部,但如果您要求某人使用该分接框,他们可能会抱怨它没有多大意义。 开发人员关心该框是否处于活动状态。 开发人员可能并不关心如何管理突出显示,并且更喜欢点按框处理这些细节。

其他的交互式Widget

Flutter提供了很多按钮和类似的交互式Widget。 这些Widget中的大多数都实现了Material Design准则,该准则定义了一组具有固定用户界面的组件。

如果您愿意,可以使用GestureDetector在任何自定义的Widget中构建交互性。 您可以在管理状态一节中找到GestureDetector的使用示例。

提示:Flutter还提供了一些IOS风格的Widget,称之为Cupertino,具体地址:https://api.flutter.dev/flutter/cupertino/cupertino-library.html

当您需要交互性时,最简单的方法是使用Flutter已经给我提供好的Widget,下面是一个部分列表:

标准库中的Widget

  • Form,地址:https://api.flutter.dev/flutter/widgets/Form-class.html
  • FormField,地址:https://api.flutter.dev/flutter/widgets/FormField-class.html

Material库中的Widget

  • Checkbox 地址:https://api.flutter.dev/flutter/material/Checkbox-class.html
  • DropdownButton ,地址:https://api.flutter.dev/flutter/material/DropdownButton-class.html
  • FlatButton , 地址:https://api.flutter.dev/flutter/material/FlatButton-class.html
  • FloatingActionButton , 地址:https://api.flutter.dev/flutter/material/FloatingActionButton-class.html
  • IconButton ,地址:https://api.flutter.dev/flutter/material/IconButton-class.html
  • Radio ,地址:https://api.flutter.dev/flutter/material/Radio-class.html
  • RaisedButton ,地址:https://api.flutter.dev/flutter/material/RaisedButton-class.html
  • Slider ,地址:https://api.flutter.dev/flutter/material/Slider-class.html
  • Switch ,地址:https://api.flutter.dev/flutter/material/Switch-class.html
  • TextField ,地址:https://api.flutter.dev/flutter/material/TextField-class.html

好了,本文的全部内容到这里就结束了,总结一下,本文我们主要介绍了如何给Flutter中的Widget添加交互性,下一篇文章我们将介绍如何油压地给Flutter项目中添加并引用资源和图片,欢迎大家关注。

单标签

网页(程序)如果要和用户产生互动,则必须借助一定的中介,这个中介一般是:文本输入框、按钮、多选框、单选框。而表单则是这些中介和放置这些中介的空间(<form action=”” methon=””></form>)。

在网页中,这些文本输入框、按钮等等必须放置在由<form></form>这个标签所定义的空间中,否则没有实际意义。所以,由<form></form>标签所定义的空间就是表单存在的空间。


【各种输入类型】

  1. 文字输入框:每个表单之所以会有不同的类型,原因就在于type="表单类型"设定的不同而已,我们就先来看看第一个类型:文字输入列。文字输入列的形态就是type="text,其使用方法如下:

呈现结果

姓名:

原始码

<form action=http://www.baidu.com/nameproject.aspmethon=”post”>

姓名:<input type="text" name="name" size="20">

</form>

它有下列可设定之属性:

  • name="名称",是设定此一栏位的名称,程式中常会用到。
  • size="数值",是设定此一栏位显现的宽度。
  • value="预设内容",是设定此一栏位的预设内容。
  • align="对齐方式",是设定此一栏位的对齐方式,其值有:top(向上对齐)、middle(向中对齐)、bottom(向下对齐)、right(向右对齐)、left(向左对齐)、texttop(向文字顶部对齐)、baseline(向文字底部对齐)、absmiddle(绝对置中)、absbottom(绝对置下)等。
  • maxlength="数值",是设定此一栏位可设定输入的最大长度。


  1. 单选框:利用type="radio"就会产生单选核取表单,单选核取表单通常是好几个选项一起摆出来供使用者点选,一次只能从中选一个,故为单选核取表单。

呈现结果

性别:男 女

原始码

<form>

性别:

男 <input type="radio" name="sex" value="boy">

女 <input type="radio" name="sex" value="girl">

</form>

它有下列可设定之属性:

  • name="名称",是设定此一栏位的名称,程式中常会用到。
  • value="内容",是设定此一栏位的内容、值或是意义。
  • align="对齐方式",是设定此一栏位的对齐方式,其值有:top(向上对齐)、middle(向中对齐)、bottom(向下对齐)、right(向右对齐)、left(向左对齐)、texttop(向文字顶部对齐)、baseline(向文字底部对齐)、absmiddle(绝对置中)、absbottom(绝对置下)等。
  • checked,是设定此一栏位为预设选取值。


  1. 复选框:利用type=" checkbox "就会产生复选核取表单,复选核取表单通常是好几个选项一起摆出来供使用者点选,一次可以同时选好几个,故为复选核取表单。

呈现结果

喜好: 电影 看书

原始码

<form>

喜好:

<input type="checkbox" name="sex" value="movie">电影

<input type="checkbox" name="sex" value="book">看书

</form>

它有下列可设定之属性:

  • name="名称",是设定此一栏位的名称,程式中常会用到。
  • value="内容",是设定此一栏位的内容、值或是意义。
  • align="对齐方式",是设定此一栏位的对齐方式,其值有:top(向上对齐)、middle(向中对齐)、bottom(向下对齐)、right(向右对齐)、left(向左对齐)、texttop(向文字顶部对齐)、baseline(向文字底部对齐)、absmiddle(绝对置中)、absbottom(绝对置下)等。
  • checked,是设定此一栏位为预设选取值。


  1. 密码表单:利用type=" password "就会产生一个密码表单,密码表单和文字输入表单长得几乎一样,差别就在于密码表单在输入时全部会以星号来取代输入的文字,以防他人偷窥。

呈现结果

请输入密码:

原始码

<form>

请输入密码:<input type="password" name="input">

</form>

它有下列可设定之属性:

  • name="名称",是设定此一栏位的名称,程式中常会用到。
  • size="数值",是设定此一栏位显现的宽度。
  • value="预设内容",是设定此一栏位的预设内容,不过呈现出来仍是星号。
  • align="对齐方式",是设定此一栏位的对齐方式,其值有:top(向上对齐)、middle(向中对齐)、bottom(向下对齐)、right(向右对齐)、left(向左对齐)、texttop(向文字顶部对齐)、baseline(向文字底部对齐)、absmiddle(绝对置中)、absbottom(绝对置下)等。
  • maxlength="数值",是设定此一栏位可设定输入的最大长度。


  1. 送出按钮:通常我们表单填完之后,都会有一个送出按钮以及清除重写的按钮,分别是利用type=" submit "及type=" reset "来产生,相当的简单易用。

呈现结果

原始码

<form>

<input type="submit" value="送出资料">

<input type="reset" value="重新填写">

</form>

它有下列可设定之属性:

  • name="名称",是设定此一按钮的名称。
  • value="文字",是设定此一按钮上要呈现的文字,若是没有设定,浏览器也会自动替您加上“送出查询”、“重设”等字样。
  • align="对齐方式",是设定此一栏位的对齐方式,其值有:top(向上对齐)、middle(向中对齐)、bottom(向下对齐)、right(向右对齐)、left(向左对齐)、texttop(向文字顶部对齐)、baseline(向文字底部对齐)、absmiddle(绝对置中)、absbottom(绝对置下)等。


  1. 按钮元件:表单中或是java script常会用到按钮来作一些效果,因此,我们可以利用type=" button "来产生一个按钮,相当简单。

呈现结果

请按下按钮:

原始码

<form>

请按下按钮:<input type="button" name="ok" value="我同意">

</form>

它有下列可设定之属性:

  • name="名称",是设定此一按钮的名称。
  • value="文字",是设定此一按钮上要呈现的文字。
  • align="对齐方式",是设定此一栏位的对齐方式,其值有:top(向上对齐)、middle(向中对齐)、bottom(向下对齐)、right(向右对齐)、left(向左对齐)、texttop(向文字顶部对齐)、baseline(向文字底部对齐)、absmiddle(绝对置中)、absbottom(绝对置下)等。


  1. 隐藏栏位:表单中有时有些东西因为某些因素,不想让使用者看到,但因程式需要却又不得不存在,此时,我们就可以利用type=" hidden "来产生一个隐藏的栏位。

呈现结果

隐藏栏位:

原始码

<form>

隐藏栏位:<input type="hidden" name="nosee" value="看不到">

</form>

它有下列可设定之属性:

  • name="名称",是设定此一栏位的名称。
  • value="文字",是设定此一栏位的值、文字或意义。

【大量文字输入元件】

  1. 有时候我们会希望让使用者输入比较大量的文字,此时,文字输入列就显得不敷使用,因此我们就可以利用<textarea></textarea>来产生一个可以输入大量文字的元件,夹在两个标签中的文字会出现在框框中,可作为预设文字。

呈现结果

请输入您的意见:

原始码

<form>

请输入您的意见:<br>

<textarea name="talk" cols="20" rows="3"></textarea>

</form>

它有下列可设定之属性:

  • name="名称",是设定此一栏位的名称。
  • wrap="设定值",是设定此一栏位的换行模式。设定值有三种:off(输入文字不会自动换行)、virtual(输入文字在萤幕上会自动换行,不过若是使用者没有自行按下enter换行,送出资料时,也视为没有换行)、physical(输入文字会自动换行,送出资料时,会将萤幕上的自动换行,视为换行效果送出)。
  • cols="数值",是设定此一栏位的行数(横向字数)。
  • rows="数值",是设定此一栏位的列数(垂直字数)。


【下拉式选单】

  1. 下拉式选单令整个网页看起来有很专业的感觉,我们只要利用<select name="名称">便可以产生一个下拉式选单,另外,还需要配合<option>标签来产生选项,这样才算完整喔!

呈现结果

您喜欢看书吗?:

非常喜欢

还算喜欢

不太喜欢

非常讨厌

原始码

<form>

您喜欢看书吗?:

<select name="like">

<option value="非常喜欢">非常喜欢

<option value="还算喜欢">还算喜欢

<option value="不太喜欢">不太喜欢

<option value="非常讨厌">非常讨厌

</select>

</form>

它有下列可设定之属性:

  1. size="数值",是设定此一栏位的大小,预设值为1,若是您的选项有四个,然后您将size设成4,那么,下拉式选单便会变成选项方块,将四个选项一起呈现在方块中。

multiple,是设定此一栏位为复选,可以一次选好几个选项。

....................................................................

我的微信公众号:UI严选 —越努力,越幸运

TMl 的标签可以分为单个标签和成对标签。

单个标签:html4 规定单个标签要有一个 / 表示结尾, html5 则不用

<!--单个标签-->
<meta>
<!--成对标签 -->
<div></div>

以下是HTMl中常用的一些标签


div 标签

div 标签 主要用来将相关的内容组合到一块,就像菜市场把各个蔬菜分成不同种类区分摆放是一个道理。

div 是最常见也是比较重要的标签,网页布局中经常使用的一类标签。通常布局被称为 DIV + CSS 布局

<div>
  div 就是一个分类的存储箱子
</div>


p标签

p标签表示段落, 在网页文字中应用的比较多

<!--段落和段落间会换行-->
<p>第一段</p>
<p>第二段</p>


H-标题标签

h标签分为六个

标签

语义

h1

一级标题

h2

二级标题

h3

三级标题

h4

四级标题

h5

五级标题

h6

六级标题

引用标题标签后,字体会加粗、字号一会变大


ul 无序标签

无序标签是没有显示顺序的列表,无序列表前面通常会有一个“小点”, 这个小点可以用type属性控制。其中有三个展示方式(不过这种方式比较固定,不够灵活和美观, 已经被CSS的效果代替),如下:

值(type属性)

描述

disc

默认值,实心圆

circle

空心圆

square

实心方框

举例:

<!--ul标签内部只能放置li标签-->
<!--li标签内部可以放其他的标签-->
<ul type=">
    <li>无序列表元素1</li> <!--列表项-->
    <li>无序列表元素2</li>
</ul>




实心圆
<ul type="disc">
  <li>西红柿</li>
  <li>黄瓜</li>
</ul>
空心圆
<ul type="circle">
  <li>西红柿</li>
  <li>黄瓜</li>
</ul>
实心方框
<ul type="square">
  <li>西红柿</li>
  <li>黄瓜</li>
</ul>


ol 有序标签

  • ol 前面的标签是有序的,可以是数字、字母、罗马数字等。同样控制这些样式使用的是type属性。

type属性值

意义

a

小写英文字母编号

A

大写英文字母编号

i

小写罗马数字编号

I

大写罗马数字编号

1

数字编号(默认)

  • 设置start属性,表示从哪个编号开始
  • 加 reversed 表示倒叙排列


有序列表, 从2开始
<ol start="2">
  <li>元素1</li>
  <li>元素2</li>
</ol>


小写字母表示
<ol type="a">
  <li>元素1</li>
  <li>元素2</li>
  <li>元素3</li>
</ol>


倒叙
<ol reversed>
  <li>元素1</li>
  <li>元素2</li>
  <li>元素3</li>
</ol>


dl 自定义列表

dl标签表示自定义列表

dt表示数据项,dd表示数据定义, dd是dt标签的解释


<dl>
    <dt>西红柿</dt>
    <dd>红、酸</dd>
    <dt>黄瓜</dt>
    <dd>绿、涩</dd>
  </dl>


img标签

img 用来插入图片,包括但不限于以下图片格式

图片格式

备注

.jpg、.jpeg

通常用于照片,是一种有损压缩格式

.png

通常用于logo、背景,支持透明和半透明。便携式网络图像

.svg

矢量图片


<!-- src(source)属性, 图片地址,可以为相对路径,也可以为绝对路径-->
<!-- alt 如果遇到图片无法加载的情况,网页上会展示 alt的 值 -->
<!-- width 和 height 表示 宽和高, 如果只设置一个, 那么另外一个就会跟着成比例缩放-->
<img src="./images/images.jpg" alt="星期一" width="120" height="20">


a 标签

用a标签来制作超级链接

<!-- href 属性 表示 其他页面的链接,支持相对路径和绝对路径,还可以链接到其它网站 -->
<!--target 属性表示 打开其他链接的方式-->
<!-- title 属性表示 链接的标题, 当鼠标移动到链接上,会展示出来-->
<a href="http://www.baidu.com" target="blank" title="文字标题">百度</a>






<!--也可以用a标签作为锚点 锚点可以是本页面的锚点,也可以是其他页面的锚点-->
<h1 id="title">头部标题</h1>
... 此处省略一些代码
<a href="#title">返回标题</a>




<!--下载链接,指向 doc, zip, zip等文件格式时,a标签将成为自动下载链接-->
<a href="./download/halou.zip">发邮件</a>
<!-- mailto:前缀的链接是邮件链接,系统将自动打开email相关软件-->
<a href="mailto:halouworld@126.com">发邮件</a>
<!-- tel: 前缀链接是电话链接,系统将自动打开拨号键-->
<a href="tel:11111111111">打开拨号键盘</a>


audio标签

audio标签用来插入音频标签

<!--添加 controls 后才会显示 播放控件-->
<!--常用音频格式 mp3 和 ogg格式-->
<!--autoplay 自动播放属性-->
<!--loop 属性表示循环播放-->
<audio controls src="./video/demo.mp3">
       您的浏览器不支持 audio标签,请升级
</audio>




<audio controls src="./video/demo.mp3" autoplay loop>
     您的浏览器不支持 audio标签,请升级
</audio>

video标签

video 标签用于插入一段视频

<!--有的视频不能播放 ,详见 https://blog.csdn.net/weixin_34272308/article/details/94614657 -->
<!-- controls 显示视频播放控件  -->
<!-- autoplay 自动播放 -->
<!-- loop 循环播放 -->
<!-- 常见的 视频格式 mp4 ogv webm 等-->
<video controls autoplay loop src="./video/5-4 RDB2.mp4" >
    您的浏览器不支持 video标签,请升级
</video>


其它区块标签

以前的区块标签只有div,现在为了更好的方便搜索引擎抓取网站,因此有了以下语义更加明确的区块标签

<section>

文档的区域,比div语义上还要大一点

<header>

页头

<main>

网页核心部分

<footer>

页脚


其他的语义标签

  • span 标记文本标记区域,没有特殊效果,结合CSS使用
  • b 标签 加粗文章(可以使用CSS实现同样效果)
  • u 加下换线文字
  • br 换行
  • i 倾斜文字(可以使用CSS实现同样效果)
  • strong 代表特别重要的文字
  • em 需要强调的文字,有一定的倾斜,也可以用其配置CSS做表情文字
  • mark 高亮文字
  • figure 和 figcaption 。figure - 一段独立的内容 figcaption- figure 内部元素的说明性内容


表单

表单用来收集信息并且可以完成和后端的数据传输

表单中大致可以分为三种标签

  • form标签,标识表单区域, 内部的元素都可能被表单提取信息
  • input 标签, 标识输入、点击等需要和用户交互的场景
  • datalist 下拉框,支持搜索,通常和input一块使用

一些表单的示例

<!--action 表示要提交到后端的网址-->
<!--method 表示表单提交的方式,通常有 get 、 post 、put、delete等-->


<form action="/save" meththo="post"></form>


<!--<form> 标签中 input 文本框 type="text" 表示文本框-->
<!-- value 表示文本框中的值 -->
<!--planceholder表示提示文字,在没任何输入值的情况下,作为提示信息-->
<!--disabled 表示禁用-->
<input type="text" value="123" planceholder="提示文字" disabled>


<!---单选按钮,name相等,表示选择了一个,另一个就不能选择了-->
<!--checked 表示默认被选中-->
<!-- value 属性表示要提交到后端服务器的值-->
<input type="radio" name="radio_group" checked>
<input type="radio"  name="radio_group">




<label>
    <input type="radio" name="sex"> 男
</label>
<label> 
    <input type="radio" name="sex"> 女
</label>




<!--html4 中的标签 通过for 属性 和 其他标签的id属性进行绑定-->


<input type="radio" name="sex" id="nan"> 
<label for="nan">男</label>


<input type="radio" name="sex"   id="nv">
<label for="nv">女</label>


<!--复选框 type="checkbox" 同一组的的复选框,name值应该相同 ,复选框也有value值, 用于向服务器提交数据-->
<input type="checkbox" name="hobby" value="soccer" > 足球
<input type="checkbox" name="hobby" value="basket" > 篮球


<!--密码框-->
<input type="password" placeholder="请输入密码">


<!-- 下拉菜单 -->
<select>
  <option value="alipay">支付宝</option>
  <option value="wxpay">微信支付</option>
</select>


<!--多文本框 rows 和  clos 分别用于设置 行数 和 列数-->
<textarea rows="3" cols="5"></textarea>


<!--三种按钮 submit 提交按钮  button 普通按钮 可以简写为  <button></button> reset 按钮 重置按钮-->
<input type="button" value="普通按钮">
    <input type="reset" value="重置按钮"> 
    <input type="submit" value="提交表单">




<!--像 email 和 url 等格式,如果点击提交按钮,不符合格式,会有提示-->
<form>
    日期空间: <input type="date">  <br/>
    时间空间: <input type="time">  <br/>
    日期时间空间 <input type="datetime-local">  <br/>


    文件:<input type="file"> <br/>  <br/>
    数字控件: <input type="number"> <br/>
    拖拽条: <input type="range"> <br/>
    搜索框: <input type="search"> <br/>
    网址控件: <input type="url"> <br/>
    邮箱控件: <input type="email" >
    <input type="submit" value="提交">
</form>




<!-- datalist 备选项示例 -->
<input type="text" list="province">
<datalist id="province">
  <option value="陕西"></option>
  <option value="山西"></option>
  <option value="河北"></option>
  <option value="山东"></option>
</datalist>


表格

可以用html渲染表格

  • table 标签表示表格
  • tr 表示行
  • td 表示单元格
  • caption 表格的标题,通常放在表格的第一行
  • th 表示列标题


<!--表格示例-->
<table border="1">
  <caption>我是标题</caption>
  <tr>
      <th>第一列标题</th>
      <th>第二列标题</th>
  </tr>
  <tr>
      <td>第一行第一列</td>
      <td>第一行第二列</td>
  </tr>
  <tr>
      <td>第二行第一列</td>
      <td>第二行第二列</td>
  </tr>
</table>


  • 单元格的合并, clospan 用来设置td 或者th的列跨度 , rowspan属性用来设置td或者th的行跨度
<!--跨列示例-->
<table border="1">
    <caption>我是标题</caption>
    <tr>
        <th>第一列标题</th>
        <th>第二列标题</th>
    </tr>
    <tr>
        <td colspan="2">跨两行</td>
    </tr>
    <tr>
        <td>第二行第一列</td>
        <td>第二行第二列</td>
    </tr>
</table>


<!--跨行示例-->
<table border="1">
        <caption>我是标题</caption>
        <tr>
            <th>第一列标题</th>
            <th>第二列标题</th>
        </tr>
        <tr>
            <td rowspan="2">第一行第一列</td>
            <td>第一行第二列</td>
        </tr>
        <tr>
            <td>第二行第二列</td>
        </tr>
        <tr>
            <td>第三行第一列</td>
            <td>第三行第二列</td>
        </tr>
  </table>


  • 表格的其他标签 , thead 定义表头, tbody 定义表格的主题内容, tfoot 标签定义表格底部,通常用来汇总等