前言
由于我自己是从Android原生转flutter,之前在Android Studio中写java代码时还没感受到模板的强大之处,在新建java的Class文件的时候,会自动生成"public class [文件名]"的样式模板,到了新建dart就没有自带的模板,每次都要手写class xxx,于是最近抽点时间研究了一下,果然是可以自定义模板的!而且远比之前强大,跟着我一起看看吧
实践
入口1
其实平时如果有好奇的同学喜欢观察就会发现,当我们新建文件时,有一个 Edit File Templates… 的选项,其实这就是修改模板的快捷入口了
入口2
除了快捷入口,当然也可以从工具栏进入,点击左上角的 File -> Settings -> Editor -> File and Code Templates
或者在Settings的搜索栏直接搜索 File and Code Templates,都可以
模仿
现在知道所有的模板文件是在这里定义了,那我们先去看看熟悉的Class文件的模板长什么样子吧!
打开一看,咦,怎么这个模板里还有代码,而且这个语法既陌生又熟悉呢?
这里介绍一下,这里模板使用的代码语法叫做 VTL(Velocity Templates Language) 点击右下角蓝色部分的Apache Velocity即可看到官方指南网页了,这里就不做详细介绍了。
简单说就是基于java的模板引擎,有点像jsp。
回过来看这个Class的模板代码,它干了什么事情呢,先看第一句
#if (${PACKAGE_NAME} && ${PACKAGE_NAME} != "")package ${PACKAGE_NAME};#end
意思其实就是,如果存在PACKAGE_NAME且不等于"",则在文件第一行加上package PACKAGE_NAME,理解起来很简单
第二行看到可能会有点懵逼,这个File Header.java是哪来的,为啥要解析它
#parse("File Header.java")
其实这是官方预定义好的一个文件,在Includes的tab里,是一个空的文件,让用户可以自己再文件头里写好预备的注释,比如说作者信息,创建时间等等,加完这个我们再去创建一个新的Class文件就会自带注释了
第三行就一个${NAME},其实就是文件名
超越
目前为止,已经看懂了Class模板文件里的代码了,我们可以来搞搞自己的了,首先去看看dart文件里有什么默认的模板代码——
嗯??啥都没有,好吧,我们自己来,我们已经学会用文件名传递到模板文件里的方法了,这个简单,来
挠头,好像哪里不对,但是又好像都对。
这个类名很明显不是我们想要的,java文件的文件名和类名是直接对应的,直接使用文件名是可以的。但是dart的文件名采用lowercase+下划线的方式,直接使用文件名肯定是不行的,别慌,既然是用java写的模板代码,那肯定可以对文件名做点操作。直接给大家贴上代码吧!
#set($words = $NAME.split("_"))
#set($result = "")
#foreach($word in $words)
#set($capitalizedWord = $word.substring(0,1).toUpperCase() + $word.substring(1))
#set($result = $result + $capitalizedWord)
#end
class $result {
}
我自己也没细看VTL的语法,但是这段代码也不复杂,可以简单理解下
第一行就是把文件名用下划线分隔成一个集合,用变量words存起来
第二行声明一个result的空字符串
第三行就是遍历words,把首字母变成大写,然后再拼接到result中
,最后把result设置为文件名就大功告成了
来试一下成果!
举一反三
除了dart文件,在写flutter新建widget也需要写很多模板代码,虽然官方自带live templates的也很好用,但是既然我们都学会了怎么直接从文件名做模板,那就一步到位。
live templates:
这里直接贴我自己喜欢用的StatelessWidget和StatefulWidget模板吧,需要的同学自己改一改
Stateless:
import 'package:flutter/material.dart';
#set($words = $NAME.split("_"))
#set($result = "")
#set($word = "")
#foreach($word in $words)
#set($capitalizedWord = $word.substring(0,1).toUpperCase() + $word.substring(1))
#set($result = $result + $capitalizedWord)
#end
class $result extends StatelessWidget{
@override
Widget build(BuildContext context) {
return Scaffold(
body: ,
);
}
}
StatefulWidget:
import 'package:flutter/material.dart';
#set($words = $NAME.split("_"))
#set($result = "")
#set($word = "")
#foreach($word in $words)
#set($capitalizedWord = $word.substring(0,1).toUpperCase() + $word.substring(1))
#set($result = $result + $capitalizedWord)
#end
class $result extends StatefulWidget {
const $result({super.key});
@override
State<$result> createState() => _${result}State();
}
class _${result}State extends State<${result}> {
@override
Widget build(BuildContext context) {
return Scaffold(
body: ,
);
}
}
生成模板如图: