Mysql4J是一款用于访问MySQL数据库的ORM组件。通过它可以方便地构建sql语句,并且可在编译期进行sql语法检查,还可以把得到的数据结果转换成List、Map、Set等形式。简单易用,独辟蹊径,是提高代码编写效率的好工具。
Mysql4J适用于中小型项目。
底层基于Spring的JdbcTemplate
Mysql4J底层通过Spring的JdbcTemplate对象访问数据库,该JdbcTemplate对象需要事先配置好并保证可用,然后设置到Mysql4J中。
编译期纠错
Mysql4J可在编译期检查出大部分的sql语法错误,相比于在运行时才发现sql错误,对于快速开发,有很大帮助。
由于用java模拟了sql语句,所以sql的语法,对应到了java语法,这样当sql拼写不正确时(逻辑错误除外),通常也是一个java语法错误,如果使用IDE的代码提示工具,则基本的匹配和代码构建是自动提示的。
数据结果,封装友好
Mysql4J对查询得到的数据,可进行相对灵活的后处理。可以是pojo对象的List集合,也可以是Map集合。同JdbcTemplate不同,JdbcTemplate的getMap方法,仅返回Map表示的一条数据记录,Mysql4J则把多行查询结果,放在Map中,Map的key值,可以由程序员指定,通常指定成表中某个不重复的字段。还可以方便的直接得到单个值,或者某一列值的List列表。
如果不想定义pojo对象,可以直接使用Row对象封装行记录,Row实现了Map接口,提供了getString、getInteger、getDate等方便的数据提取方法。
Api 简单易懂,上手迅速
Mysql4J的api非常简单,几乎不用阅读文档,仅根据java IDE的代码工具提示,就可以构建完整的程序代码。
SQL 即用即写,逻辑集中不分散
sql语句中,通常包含着关键的业务逻辑。Mysql4J可保证在一个java方法中,业务逻辑的完整性,sql语句不会被写到程序文件之外。打开一个类,逻辑全部在其内部展现,相对于把sql写到xml中,代码更清晰易读。
Mysql4J的使用非常简单,例如:
// 表(mapping类)
um_member m = new um_member();
// 查询对象
Query query = new Query();
query.from(m);
query.where(m.level.eq(1));
query.where(m.name.startsWith("urs"));
query.where(m.nick.contains("小熊"));
query.where(m.reg_time.le(new Date(), DATETIME));
query.order(m.reg_time.desc());
query.limit(0, 20);
// 获得结果集
List list = query.getList();
其中um_member为数据库表,类名直接对应表名,也是Mysql4J的mapping类,用来配置表结构。um_member m = new um_member(),变量m,可理解为表的别名,m.level,m.name,m.nick,m.reg_time是m对象的属性名,同时也是表um_member的字段名!
这样映射后,数据库中表名和字段名的改变,只需要修改mapping类um_member,然后分布在程序各处的Mysql4J数据库访问代码,会自动报出编译期错误,方便修改,保证了表名和字段名的一致。类似报出编译期错误警告的地方还有很多,比如把数字赋值给一个字符字段,等等。
Mysql4J不仅把表和字段直接映射成java的类和属性,而且把查询、插入、修改、删除数据的操作,也做了对象化处理。这些都采用java实现并且尽量遵循sql的语法习惯!
编写mapping类
使用Mysql4J,需要配置一个mapping类。在传统的ORM组件中,这个配置通常以xml格式写在文件里,用来指明java数据模型和数据库中的表以及字段的映射关系。在Mysql4J中,这个配置就是一个java类,它不仅说明了映射关系,还能被实例化成一个对象,在数据操作中使用。
具体使用方法如下:
首先假设数据库中存在如下的表:
// 会员表
CREATE TABLE `um_member` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`name` varchar(20) DEFAULT NULL,
`nick` varchar(30) DEFAULT NULL,
`level` smallint(6) DEFAULT NULL,
`tel` varchar(20) DEFAULT NULL,
`reg_time` datetime DEFAULT NULL,
`last_login_time` datetime DEFAULT NULL,
`login_times` int(11) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
它的配置类则按照如下方式书写:
// 类名 = 表名:类名需要同数据库表名保持完全一致,该类必须继承Table作为父类
public class um_member extends Table
{
// 构造方法的固定写法
public um_member()
{
// 数据映射对象的class,可以为Row.class或者pojo对象的class,这里采用pojo对象
super(Member.class);
// 初始化,固定写法,不可省略
super.init();
// 获得可用的JdbcTemplate对象
JdbcTemplate jdbcTemplate = (JdbcTemplate)YourSpring.get("jdbcTemplate");
// 设置jdbcTemplate
super.setJdbcTemplate(jdbcTemplate );
}
// 属性名 = 字段名:属性名需要同数据库字段名保持完全一致
public Num id = new Num().asPrimaryKey().asIncrement(); // 主键ID
public Chr name; // 姓名
public Chr nick; // 昵称
public Num level; // 会员等级
public Chr tel; // 电话
public Datetime reg_time = new Datetime().property("registerTime"); //注册时间
public Datetime last_login_time; // 最近登录时间
public Num login_times; // 登录次数
}
该类继承了cn.com.ursaminor.mysql4j.core.Table类,Table类是所有配置类的父类,配置类必须继承此类,继承该类不需要实现任何抽象方法。
配置类的类名,必须同表名相同,这可能违反了java的命名规范,但使得配置类在使用时,更像一个表,而不是一个对象。
配置类由两部分组成,一个是构造方法,一个是成员变量,不需要普通的方法。
构造方法对参数无要求,内部要求必须调用下列父类的方法:
一个是父类构造方法super(Class cls),用来指定数据查询结果的装载对象,即封装数据的pojo对象,如果没有pojo对象,可以直接使用Row,即super(Row.class)。
另一个是super.init(),该方法负责初始化工作,必须调用,不可省略。
第三个是super.setJdbcTemplate(jdbcTemplate),jdbcTemplate对象需要使用者自行获取,并保证可用。
后两个方法可以合并成super.init(jdbcTemplate)。
把jdbcTemplate绑定到配置类,可以自然地支持多数据库情况。并且在使用时,无须再设置jdbcTemplate,只需要简单实例化配置类即可:
um_member m = new um_member();
配置类中,需要配置同表字段一一对应的成员变量,成员变量的名称,必须同表的字段名保持一致,如:
public Num login_times;
这里也可能会违反java的命名规范,但这使配置类应用起来更像一个表。类名和属性名如果不同数据库的表名字段名保持一致,将导致sql拼写错误。
成员变量必须被声明为public的,并且只能是Chr、Num、Datetime三种类型之一。Chr代表该属性对应数据库的字符型字段,Num代表该属性对应数据库的数字型字段,Datetime目前只针对datetime类型字段,其它字段类型,会在后续版本扩展。
如果字段不需要其它的修饰,则不需要被赋值,仅保持声明即可,super.init()方法会自动给它们赋值一个对应的对象,不会出现属性为null的情况。如果需要其它修饰,比如设置为主键、设置为自增长、设置pojo类中的对应属性,则需要手动配置。如:
public Num id = new Num().asPrimaryKey().asIncrement();
public Datetime reg_time = new Datetime().property("registerTime");
这里,id属性被设置成主键,并且是自增长类型。reg_time属性被指定了pojo类中对应的属性为registerTime。如果pojo类中对应的属性为regTime,则不需要上述语句,super.init()会自动转化并为其赋值。
配置类可重复使用,虽然配置类是有状态的,但在使用过程中,其状态不会发生改变,可以构建一个配置类的工厂类,也可将配置类作为单例模式写到Spring中。最简单的使用方式,直接new一个就好:um_member m = new um_member();
编写pojo类
pojo类是一个普通的装载数据的对象,遵循JavaBean风格,不需要继承和实现任何父类和接口。
如果表的主键是自增长的,新增记录后的主键值,会自动设置到pojo类中,该pojo类需要有主键的setter方法。
一个表如果有对应的pojo类,则需要在配置类构造方法的super(Class cls)中设置,比如
super(Member.class);
Member类源码如下:
// 会员对象
public class Member
{
private Long id; // 主键ID
private String name; // 姓名
private String nick; // 昵称
private Integer level; // 会员等级
private String tel; // 电话
private Date registerTime; // 注册时间
private Date lastLoginTime; // 最近登录时间
private Integer loginTimes; // 登录次数
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
// 省略其它属性的getter/setter方法
}
使用Row
如果不使用自定义的pojo类装载数据,Mysql4j提供了Row类来装载数据。Row实现了Map接口,提供了getString、getInteger、getDate等方便的数据提取方法。可以作为Map的替代。
如果表的主键是自增长的,新增记录后的主键值,会自动设置到Row类中。
使用Query查询数据
Query类是Mysql4J的查询类,通过它可以方便的构建大多数的select语句。并且方便地得到想要的数据结果。
A:例1
// 值
int level = 2;
String name = "ur";
String nick = "小熊";
Date date = new Date(System.currentTimeMillis()-7*24*60*60*1000);
// 表
um_member m = new um_member();
// 构建sql
Query query = new Query();
query.from(m); // from um_member m
query.where(m.level.eq(level)); // m.level=2
query.where(m.name.startsWith(name)); // m.name like 'ur%'
query.where(m.nick.contains(nick)) // m.nick like '%小熊%'
.nullIgnore(); // 如果String变量nick为空,则忽略m.nick like...
query.where(m.reg_time.ge(date, DATETIME)); // m.reg_time>='2020-01-02 17:42:09'
query.order(m.reg_time.desc()); // order by m.reg_time desc
query.limit(0, 20); // limit 0,20
// 执行
List<Member> list = query.getList(Member.class);
上述语句生成sql为:
select t0.id,t0.name,t0.nick,t0.level,t0.tel,t0.reg_time,t0.last_login_time,t0.login_times
from um_member t0
where t0.level=2 and t0.name like 'ur%' and t0.nick like '%小熊%'
and t0.reg_time>='2020-01-02 17:42:09'
order by t0.reg_time desc limit 0,20
表别名实际为t0,同变量名m不一致,不会导致任何问题。下同。
B:例2
// 值
int level = 2;
Date date = new Date(System.currentTimeMillis()-7*24*60*60*1000);
// 表
um_member m = new um_member();
um_order_form of = new um_order_form();
// query支持链式方法调用
Query query = new Query()
query.from(m) // from um_member m
.from(of, m.id.eq(of.m_id)) // , um_order_form of where m.id=of.m_id
.select(m.name) // select m.name
.select(Fun.sum(of.count).as("count")) // sum(of.count) as count
.where(m.level.eq(level)) // m.level=2
.where(m.reg_time.ge(date, DATETIME)) // m.reg_time>='2020-01-02 17:42:09'
.having(Fun.sum(of.count).ge(5)) // having sum(of.count)>=5
.group(m.name); // group by m.name
// 执行
List<Member> list = query.getList(Member.class);
上述语句生成sql为:
select t2.name,sum(t3.count) as count
from um_member t2,um_order_form t3
where t2.id=t3.m_id and t2.level=2 and t2.reg_time>='2020-01-02 17:42:09'
group by t2.name having sum(t3.count)>=5
C:例3
// 表
um_member m = new um_member();
um_order_form of = new um_order_form();
// 子查询
Query sub = new Query()
.from(of) // from um_order_form of
.select(of.m_id) // select of.m_id
.having(Fun.sum(of.count).ge(5)) // having sum(of.count)>=5
.group(of.m_id); // group by of.m_id
// 构建sql
Query query = new Query();
query.from(m); // from um_member m
query.where(m.id.in(sub)); // where m.id in ( ... )
// 执行
List<Member> list = query.getList(Member.class);
上述语句生成sql为:
select t5.id,t5.name,t5.nick,t5.level,t5.tel,t5.reg_time,t5.last_login_time,t5.login_times
from um_member t5 where t5.id in
(select t6.m_id from um_order_form t6 group by t6.m_id having sum(t6.count)>=5)
得到特定结构的查询结果
Query对象返回的数据结果,可以有多种形式。
方法 | 说明 |
---|---|
List<R> getList() | 返回以List形式表示的结果集,元素类型<R>为配置类中指定的class,List的元素可以为pojo对象或者Row对象 |
Integer getCount() | 返回忽略分页后的结果行数,用于分页查询中 |
V getValue(Class<V> valueClass) | 返回一个值,值的类型由valueClass指定,比如String.class、Integer.class。当数据结果有多条记录时,仅返回第一条记录;当没有匹配结果时,返回null。该方法要求select关键字指定且仅指定一列。 |
List<V> getValues(Class<V> valueClass) | 返回值的List,元素类型由valueClass指定,比如String.class、Integer.class。当没有匹配结果时,返回空的List对象。该方法要求select关键字指定且仅指定一列。 |
Set<V> getSet(Class<V> valueClass) | 返回值的Set,元素类型由valueClass指定,比如String.class、Integer.class。当没有匹配结果时,返回空的Set对象。该方法要求select关键字指定且仅指定一列。 |
R getOne() | 返回一条记录,数据类型<R>为配置类中指定的class,List的元素可以为pojo对象或者Row对象。当没有匹配结果时,返回null。 |
Map<Object,R> getMap(String property) | 返回以Map形式表示的结果集,需要指定key,即pojo的property。Value的类型<R>为配置类中指定的class。value可以为pojo对象或者Row对象。当没有匹配结果时,返回空的Map对象。 |
Map<K,R> getMap(KeyCallback<K,R> keyCallback) |
返回以Map形式表示的结果集,通过回调获得属性值作为key。Value的类型<R>为配置类中指定的class。value可以为pojo对象或者Row对象。当没有匹配结果时,返回空的Map对象。 |
Map<K,V> getMap(KeyValueCallback<K,V,R> keyValueCallback) |
返回以Map形式表示的结果集。<R>指定了最初返回数据的类型,为配置类中指定的class。该方法通过回调获得属性值作为key和value。当没有匹配结果时,返回空的Map对象。 |
使用Inserter插入数据
如果要在表中插入新数据,可使用Inserter类,Inserter类用来构建insert语句并提交。
举例:
A:使用值创建一个insert语句
// 表
um_member m = new um_member();
// 值
String name = "ursaminor";
String nick = "小熊";
Integer level = 1;
String tel = "1234567890";
Date registerTime = new Date();
Date lastLoginTime = null;
Integer loginTimes = 0;
// 构建sql
Inserter inserter = new Inserter(m); // insert into um_member
inserter.set(m.name, name); // name, // 'ursaminor'
inserter.set(m.nick, nick); // nick, // '小熊'
inserter.set(m.level, level); // level, // 1
inserter.set(m.tel, tel); // tel, // '1234567890'
inserter.set(m.reg_time, registerTime); // reg_time, // '2020-01-02 17:42:09'
inserter.set(m.last_login_time, lastLoginTime); // last_login_time, // null
inserter.set(m.login_times, loginTimes); // login_times, // 0
// 提交
inserter.execute();
上述语句生成sql为:
insert into um_member (name,nick,level,tel,reg_time,last_login_time,login_times)
values ('ursaminor','小熊',1,'1234567890','2020-01-09 17:42:09',null,0)
B:使用pojo/Row对象创建一个insert语句
// 表
um_member m = new um_member();
// pojo对象
Member member = new Member();
member.setName("ursaminor");
member.setNick("小熊");
member.setLevel(1);
member.setTel("1234567890");
member.setRegisterTime(new Date());
// 提交
Inserter.insert(m, member);
上述语句生成sql为:
insert into um_member (name,nick,level,tel,reg_time,last_login_time,login_times)
values ('ursaminor','小熊',1,'1234567890','2020-01-09 17:42:09',null,null)
C:Inseter还可以生成 insert into...select...语句
// 表
um_member m = new um_member();
um_order_form of = new um_order_form();
// 值
int level = 2;
Date date = new Date(System.currentTimeMillis()-7*24*60*60*1000);
// Query对象,用来生成select语句
Query query = new Query();
query.from(m); // from um_member m
query.select(m.id.as(of.m_id)); // select m.id as m_id
query.select(Fun.eval("1").as(of.count)); // 1 as count
query.select(Fun.eval("8.00").as(of.price)); // 8.00 as price
query.where(m.level.ge(level)); // where m.level>=2
query.where(m.reg_time.ge(date, DATETIME)); // m.reg_time>='2020-01-02 17:42:09'
// 构建sql
Inserter inserter = new Inserter(of); // insert into um_order_form
inserter.columns(of.m_id, of.count, of.price); // (m_id, count, price)
inserter.with(query); // select ...
// 执行
inserter.execute();
上述语句生成sql为:
insert into um_order_form (m_id,count,price)
select t11.id as m_id,1 as count,8.00 as price from um_member t11
where t11.level>=2 and t11.reg_time>='2020-01-02 17:42:09'
如果表的主键是自增长的,新增记录后的主键值,会自动设置到pojo类中,该pojo类需要有主键的setter方法。
如果没有使用pojo类,而是使用Row类型,则主键值也会自动设置。
使用Updater修改数据
如果要修改表中的数据,可使用Updater类,Updater类用来构建update语句并提交。
举例:
A:使用值创建一个update语句
// 表
um_member m = new um_member();
// 要修改的值
Long id = 2020L;
String nick = "小熊";
Integer level = 1;
String tel = "1234567890";
Date lastLoginTime = new Date();
Integer loginTimes = 1;
// 构建sql
Updater updater = new Updater(m); // update um_member m
updater.set(m.nick, nick); // set m.nick='小熊'
updater.set(m.level, level); // m.level=1
updater.set(m.tel, tel); // m.tel='1234567890'
updater.set(m.last_login_time,lastLoginTime); // m.last_login_time='2020-01-09 17:42:09'
updater.set(m.login_times, loginTimes); // m.login_times=1
updater.where(m.id.eq(id)); // where m.id=2020
// 执行
updater.execute();
上述语句生成sql为:
update um_member t14
set t14.nick='小熊',t14.level=1,t14.tel='1234567890',
t14.last_login_time='2020-01-09 17:42:09',t14.login_times=1
where t14.id=2020
B:使用pojo/Row对象创建一个update语句
// 表
um_member m = new um_member();
// pojo类
Member member = new Member();
member.setId(2020L);
member.setName("ursaminor");
member.setNick("小熊");
member.setLevel(1);
// 执行
Updater.update(m, member);
上述语句生成sql为:
update um_member
set name='ursaminor',nick='小熊',level=1,tel=null,reg_time=null,last_login_time=null,login_times=null
where id=2020
C:Updater还可以生成带有select子句的update语句
// 表
um_member m = new um_member();
um_order_form of = new um_order_form();
// 临时表
class TempTable extends Query
{
public Num id;
}
// 临时表就是一个Query对象
TempTable tt = new TempTable();
tt.from(of); // from um_order_form of
tt.select(of.m_id.as(tt.id)); // select of.m_id as id
tt.group(of.m_id); // group by of.m_id
tt.having(Fun.count(of.id).ge(10)); // having count(of.id)>=10
// 构建sql
Updater updater = new Updater(m); // update um_member m
updater.with(tt, tt.id.eq(m.id)); // (select ... ) tt where tt.id=m.id
updater.set(m.level, 2); // set m.level=2
// 执行
updater.execute();
上述语句生成sql为:
update um_member t16,
(select t17.m_id as id from um_order_form t17 group by t17.m_id having count(t17.id)>=10) t18
set t16.level=2
where t18.id=t16.id
使用Deleter删除数据
如果要删除表中的数据,可使用Deteler类,Deleter类用来构建delete语句并提交。
举例:
A:使用值创建一个delete语句
// 表
um_member m = new um_member();
// 值
Integer level = 1;
// 构建sql
Deleter deleter = new Deleter(m); // delete m from um_member m
deleter.where(m.level.eq(level)); // where m.level=1
// 提交
deleter.execute();
上述语句生成sql为:
delete t19 from um_member t19 where t19.level=1
B:使用pojo/Row对象创建一个delete语句
// 表
um_member m = new um_member();
// pojo对象
Member member = new Member();
member.setId(2020L);
// 提交
Deleter.delete(m, member);
上述语句生成sql为:
delete from um_member where id=2020
C:Deleter还可以生成带有select子句的delete语句
// 表
um_member m = new um_member();
um_order_form of = new um_order_form();
// 临时表
class Tm extends Query
{
public Num id;
}
// 临时表就是一个Query对象
Tm s = new Tm();
s.from(of); // from um_order_form of
s.select(of.m_id.as(s.id)); // select of.m_id as id
s.group(of.m_id); // group by of.m_id
s.having(Fun.count(of.id).ge(10)); // having count(of.id)>=10
// 构建sql
Deleter deleter = new Deleter(m); // delete m from um_member m
deleter.with(s, s.id.eq(m.id)); // (select ... ) s where s.id=m.id
// 执行
deleter.execute();
上述语句生成sql为:
delete t21
from um_member t21,
(select t22.m_id as id from um_order_form t22 group by t22.m_id having count(t22.id)>=10) t23
where t23.id=t21.id
转载请注明出处:http://blog.csdn.net/l1028386804/article/details/75040821 log4j可以支持将log输出到文件,数据库,甚至远程服务器,这次给大家分享下如何输出到mysql中。 1、配置log4j.properties文件 log4j.properties的配置内容如下: log4j.rootLogger=ERROR,appender1,a
1、首先创建存储日志的数据表ibs_log 创建语句如下: DROP TABLE IF EXISTS `ibs_log`; CREATE TABLE `ibs_log` ( `log_id` int(10) NOT NULL AUTO_INCREMENT, `log_date` datetime NOT NULL COMMENT '日期', `log_file` varchar(255) D
今天我把自己的SpringBoot项目上传到了GitHub,于是murphysec安全扫描平台扫描到了我的代码安全问题,如下 漏洞标题:Oracle MySQL Connectors组件访问控制错误漏洞 漏洞编号:CVE-2018-3258 漏洞描述: Oracle MySQL是美国甲骨文(Oracle)公司的一套开源的关系数据库管理系统。该数据库系统具有性能高、成本低、可靠性好等特点。MySQL
官方Mysql手册链接 Notes For Connector/J 8.0.12 and earlier: In order to use the utf8mb4 character set for the connection, the server MUST be configured with character_set_server=utf8mb4; if that is not the
错误信息如下: 2016-09-08 17:11:45 [com.mchange.v2.c3p0.C3P0Registry]-[INFO] Initializing c3p0-0.9.1.2 [built 21-May-2007 15:04:56; debug? true; trace: 10] 2016-09-08 17:11:46 [org.springframework.scheduling
我现在用的是mysql5.7,操作系统centos 配置YUM源 下载mysql源安装包 [root@VM_0_9_centos software]# wget http://dev.mysql.com/get/mysql57-community-release-el7-8.noarch.rpm 安装mysql源 [root@VM_0_9_centos software]# yum locali
通过修改my.ini文件达到修改目的 MySQL 8.0.23的my.ini配置文件存储位置 注意事项: 1.下列方法选择其中一种即可完成配置,但在开始配置之前需要将MySQL80服务关闭,否者可能无法修改my.ini文件 2.在使用下面的的文件时请先备份原文件my.ini避免由于配置文件错误造成MySQL无法使用。 由于的版本更新迭代的原因MySQL 8.0.23的my.ini的配置文件被保存在
MySQL Connector/J实际上就是大家常用的Java的MySQL驱动Jar,除了简单的JDBC功能外还提供了连接切换功能,并且Fabric的功能也包含在MySQL Connector/J中。 Mysql Connector Jar支持FailOver主备模式,直接修改程序的MySQL连接字符串即可实现主备切换 jdbc:mysql://[primary host][:port],[sec
mysql5.7连接驱动 关于mysql5.7版本的连接驱动问题,分别使用8.0以上mysql-connector,及5.1.34版本以上,对于mysql的连接参数的配置。 1、使用5.1.35版本的连接驱动 使用5.1.34及以上版本的连接驱动,在mysql5.7的连接配置上,基本没有太大的出入。 具体配置如下: Class.forName("com.mysql.jdbc.Driver");
使用组件的目的就是通过构建模块化的组件,相互组合组件最后组装成一个复杂的应用。 在 React 组件中要包含其他组件作为子组件,只需要把组件当作一个 DOM 元素引入就可以了。 一个例子:一个显示用户头像的组件 Avatar 包含两个子组件 ProfilePic 显示用户头像和 ProfileLink 显示用户链接: import React from 'react'; import { rend
英文原文:http://emberjs.com/guides/components/defining-a-component/ 为了定义一个组件,需要先创建一个名字以components/开始的模板。例如:如果需要定义一个新组建{{blog-post}},需要创建components/blog-post模板。 注意: 组件名必须包含'-'。因此blog-post是一个合法的命名,而post则不是。
了解如何跨文档使用组件,以提高各工作流程的工作效率。 作为一名设计人员,您经常会创建一些在整个设计中重复出现的主要元素,如导航栏或按钮。但是,必须根据上下文或布局来自定义元素实例并非易事。在此情况下,您往往最终会创建同一基础元素的多个版本,这会使您的设计维护变得困难得多。 组件(以前称为符号)是具有无与伦比的灵活性的设计元素,可帮助您创建和维护重复元素(如按钮),同时针对不同的上下文和布局更改该按
结构 组件是对视图的一部分进行封装,以方便组织代码和重用。 任何具有 view 方法的 JavaScript 对象都是 Mithril 组件。组件可以用过 m() 函数调用: var Example = { view: function() { return m("div", "Hello") } } m(Example) // 等效 HTML // <div>Hello</d
底部动作条 按钮 按钮:浮动操作按钮 卡片 纸片 数据表格 提示框 分隔线 网格 列表 列表控制 菜单 选择器 进度和动态 选择控制 滑块 Snackbars 与 Toasts 副标题 开关 Tabs 文本框 工具提示
页面往往有不少重复的元素,这时可以将这些元素抽离为独立的、可复用的部件,我们将这些部件称为组件。组件在概念上类似于 JavaScript 函数,它接收任意的参数(组件的参数称为“props”),然后返回一个可以被渲染的 Rax 元素。下面简单介绍组件的基本使用。 定义组件 有两种方式来定义组件。最简单和推荐的做法是使用 JavaScript 函数来定义一个组件: function Welcome(
我们的页面一般都是由各种各样的组件构成的,组件就像一个一个积木一样,被用来搭建成页面。例如一个带有用户信息、logo的头部就是一个组件,而用户信息、logo也许也可以是独立组件。组件化可以让我们把一个庞大的页面切割成一个一个小块来分别进行管理,也就是分而治之的思想,同时组件化也能帮助我们更好地进行代码复用。 Nerv天生是支持组件化的,组件是Nerv中的核心概念。Nerv中的组件分为 Class
下面列表中的组件被用于构建 OpenResty。所有组件均可以方便的被激活或禁止。 绝大部分组件已内置在OpenResty安装包中,但也有一部分不包含在内。 Drizzle Nginx 模块、 Postgres Nginx 模块 以及 Iconv Nginx 模块 默认并未启用。 你需要分别加入--with-http_drizzle_module、--with-http_postgres_modu