当前位置: 首页 > 工具软件 > Alice UI > 使用案例 >

前端工程构建及推荐UI组件库 Thyleamf

关飞翼
2023-12-01

技术栈

1.前端 项目架构 Vue+Nodejs react + TS 两大体系
2.前端框架 MUI Flutter PhonrGap ReactNatice
3.小程序体系 京东 美团
4.vue 项目常规插件 webpack 打包 vue-routr 路由 编译 babel 数据流vuex 语法 es6 eslint 公司代码规范 代码检测工具 mock数据
5.Electron 跨平台桌面应用
6.Nodejs 的增删改查 api 微服务

7.vue + proxy 代理

NVM nodejs 版本控制

可在点此在github上下载最新版本,本次下载安装的是windows版本。

https://github.com/coreybutler/nvm-windows/releases
选择下载
1.1.7 目前使用
  nvm-setup.zip:安装版,推荐使用,下一步式傻瓜安装
选择文件夹 配置nodejs 的运行目录 带上 /nodejs
  nvm-noinstall.zip:绿色免安装版,但使用时需进行配置环境变量。

双击nvm-setup.exe文件安装

注意的是安装路径最好不要出现中文和空格

nvm -v

1.列出所有已经安装的Node版本
nvm ls
2.安装最新版 Node
nvm install node
3.列出所有可以安装的Node版本号
nvm list available
4.安装指定版本号的Node
nvm install 11.13.0
5.使用特定版本的Node
nvm use 11.13.0
6.卸载版本号的Node
nvm uninstall 11.13.0

nvm arch :显示node是运行在32位还是64位。
nvm install [arch] :安装node, version是特定版本也可以是最新稳定版本latest。可选参数arch指定安装32位还是64位版本,默认是系统位数。可以添加–insecure绕过远程服务器的SSL。
nvm list [available] :显示已安装的列表。可选参数available,显示可安装的所有版本。list可简化为ls。
nvm on :开启node.js版本管理。
nvm off :关闭node.js版本管理。
nvm proxy [url] :设置下载代理。不加可选参数url,显示当前代理。将url设置为none则移除代理。
nvm node_mirror [url] :设置node镜像。默认是https://nodejs.org/dist/。如果不写url,则使用默认url。设置后可至安装目录settings.txt文件查看,也可直接在该文件操作。
nvm npm_mirror [url] :设置npm镜像。https://github.com/npm/cli/archive/。如果不写url,则使用默认url。设置后可至安装目录settings.txt文件查看,也可直接在该文件操作。
nvm uninstall :卸载指定版本node。
nvm use [version] [arch] :使用制定版本node。可指定32/64位。
nvm root [path] :设置存储不同版本node的目录。如果未设置,默认使用当前目录。
nvm version :显示nvm版本。version可简化为v。

nvm list available

nodejs

taobao npm

设置setting 文件

root: E:\environment\NodeJS\nvm
path: E:\environment\NodeJS\nodejs
arch: 64 
proxy: none 
node_mirror: https://npm.taobao.org/mirrors/node/
npm_mirror: https://npm.taobao.org/mirrors/npm/


环境变量 如果为  nvm-setup 会自动配置上
NVM_SYMLINK    配置 启动nodejs的路径
E:\environment\NodeJS\nodejs
NVM_HOME		 配置 nvmhome
E:\environment\NodeJS\nvm

发现没用  npm 还是存在下不下来问题
	所以偏方来了 现在方案是
	https://nodejs.org/download/release 从这里下载 解压到 nvm 文件下 修改文件为 v版本号  
	然后nvm list 就能获取到列表了  哈哈哈哈哈哈 虽然很笨 但是多把几个版本的管理起来就香了。


启用指定版本

nvm use 10.23.0
验证npm node
npm -v
node -v
npm install -g cnpm --registry=https://registry.npm.taobao.org

Vue工程

主要配置文件
package.json
main.js
app.vue

1 本地支持nodejs开发环境
.抛出方法 即构造方法 export function login () { }
service.js

			import Mock from 'mockjs'
			export function login () {
					  return {
					    // isOpen: false,
					    url: '/sys/login',
					    type: 'post',
					    data: {
					      'msg': 'success',
					      'code': 0,
					      'expire': Mock.Random.natural(60 * 60 * 1, 60 * 60 * 12),
					      'token': Mock.Random.string('abcdefghijklmnopqrstuvwxyz0123456789', 32)
					    }
					  }
					}

抛出对象
module.exports = { }
vue组件

webpack 前端项目

  1. 查看node和npm 或者安装 node和npm
  2. npm install -g cnpm –registry=https://registry.npm.taobao.org
  3. cnpm -v 查看版本,安装vue cnpm install vue
  4. 安装vue-cli cnpm stall -g vue-cli
  5. 创建项目 vue init webpack myvue
  6. 进入创建的工程 cd myvue
  7. npm install 进行工程初始化
  8. npm run dev 运行和 执行命令查看 packge.json 的 scripts配置
  9. 打包命令 npm run build --prod
    |__
    |__ build
    |build.js
    |webpack.base.conf.js
    |
    src
    |_mock //mock 拦截
    |_assert
    |_iconfont
    |_imgs
    |_scss
    |_store //vuex 组件间通讯
    |route
    |i18n
    |utils
    |views
    |App.vue
    |main.js
    |
    static //入口可以直接引用的资源
    |
    node_modules
    |
    package.json
    |_index.html

vue-cli 创建项目

npm install --global vue-cli

1.创建基于 webpack 模板的项目

Vue init webpack my-project
是否安装路由 yes
等。。。

npm uninstall -g vue-cli – 卸载
npm install -g @vue/cli

  1. 创建基于 cli的项目
    vue create my-project — vue-cli建的工程 cli3.0支持
    |_
    |_public
    |_index.html
    |_static 静态资源导包到工程内不经过vue编译
    |_src
    |_router
    |_store
    |_utils
    |_mock
    |_views
    |_i18n
    |_assets
    |_iconfont
    |_imgs
    |_scss
    |_app.vue
    |_main.js
    |_package.json
    |_vue.config.js //全局配置信息

常用配置 插件

1.vue-cookie插件,localStorage和sessionStorage的本地存储

2.qs 数据序列化插件

3.对象合并插件lodash

	import merge from 'lodash/merge' 
		或
	const merge = require('webpack-merge')
	
	objA = merge(objB,objC)

4.监听事件 和 绑定事件

	main.js 配置
		Vue.prototype.$bus = new Vue()
		1触发事件
		this.$bus.$emit('eventName',{paramKey:vule})  //  触发事件

2.监听事件

      mounted () {   //指定页面的 mounted内绑定该事件 和就收参数
					      this.$bus.$on('eventName', ({paramKey}) => {
		
					      })
			    },

3.销毁事件

			 beforDestroy(){//在当前组件销毁的时候 注销
     			    this.$bus.$off("vaPage");  //当这个组件销毁的时候bus也跟着一起销毁
		     }
	
				父组件 监听子组件的触发 要先
				this.$bus.$off(event).$on(event, () => {
						this.status = 'reserve'
				})

5.import require 说明

 require 是赋值过程并且是运行时才执行,require可以理解为一个全局方法   带index.js 入口的 文件夹    
 import 是解构过程并且是编译时执行,import必须写在文件的顶部       import   是 js文件 export function login () { } 或 module.exports = { }

6 mock 数据拦截

index.js

	service.js
	
		// 获取上级菜单
		export function select () {
		  return {
		    // isOpen: false,
		    url: '/sys/menu/select',
		    type: 'get',
		    data: {
		      'msg': 'success',
		      'code': 0,
		      'menuList': dataList
		    }
		  }
		}
		
		// 获取菜单信息
		export function info () {
		  return {
		    // isOpen: false,
		    url: '/sys/menu/info',
		    type: 'get',
		    data: {
		      'msg': 'success',
		      'code': 0,
		      'menu': dataList[0]
		    }
		  }
		}
		
	1.引入mock插件
	import Mock from 'mockjs'
	import * as service from './service'    //导入 js文件
	// tips
	// 1. 开启/关闭[业务模块]拦截, 通过调用fnCreate方法[isOpen参数]设置.
	// 2. 开启/关闭[业务模块中某个请求]拦截, 通过函数返回对象中的[isOpen属性]设置.
	fnCreate(service , false)

	/**
	 * 创建mock模拟数据
	 * @param {*} mod 模块
	 * @param {*} isOpen 是否开启?
	 */
	function fnCreate (mod, isOpen = true) {
	  if (isOpen) {
	    for (var key in mod) {  //处理服务抛出的方法
	      ((res) => {
	        if (res.isOpen !== false) {
	          Mock.mock(new RegExp(res.url), res.type, (opts) => {
	            opts['data'] = opts.body ? JSON.parse(opts.body) : null
	            delete opts.body
	            console.log('\n')
	            console.log('%cmock拦截, 请求: ', 'color:blue', opts)
	            console.log('%cmock拦截, 响应: ', 'color:blue', res.data)
	            return res.data
	          })
	        }
	      })(mod[key]() || {})
	    }
	  }
	}

配置
在main.js require("@/mock");

7 store 组件间通讯

import common from './common'
import cloneDeep from 'lodash/cloneDeep'
Vue.use(Vuex)
export default new Vuex.Store({
  modules: {
    common
  },
  state: {
  	  plantList: [], //base_plant 工厂列表
  	  basePlantList: [], //基地工厂列表
  	},
  getters: {
	   getPlantListByBase: (state) => (base) => {
	      let plantList = []
	      let basePlantList = state.basePlantList
	      for(let index in basePlantList) {
	        if(basePlantList[index].base === base) {
	          plantList.push(basePlantList[index].plant)
	        }
	      }
	      return plantList
	    },
		getPlantList(state){
		      return state.plantList
		 },
	
	},
  mutations: {
  	setPlantList( state, val){
	      state.plantList = val
	    },
	setBasePlantList( state, val){
	      state.basePlantList = val
	}
    // 重置vuex本地储存状态
    resetStore (state) {
      Object.keys(state).forEach((key) => {
        state[key] = cloneDeep(window.SITE_CONFIG['storeState'][key])
      })
    }
  },
   // 异步操作的方法
  actions: {
  }
  
  strict: process.env.NODE_ENV !== 'production'
})

使用方法
1. main.js
import store from ‘./store’

	全局变量注入数据
	 this.$store.commit("plantList", list);   或者指定到 那个 路径下的变量
	 使用全局变量
		  computed: {  
		      plantList: {
		        get () {
		          return this.$store.state.plantList  // 具体到那个模块的变量
		        }
		      }
  		  },

8 子组件调用父组件方法

1.父组件 在子组件上绑定方法 
	@fatherMethod="getTodayReports"
2 子组件内部 
	  this.$emit('fatherMethod',params);

9 ES6 -> ES5

配置
	babel-polyfill
	main.js  import 'babel-polyfill'
	
	webpack.base.config
	entry: {
	    app: ['babel-polyfill', './src/main.js']
	  },

10 scss css预处理语言
node-sass sass-loader style 配置 l CSS预处理语言 有特定语法 编译后生成css 简化样式

tsx-loader:处理 ts 文件

less-loader:处理 less 文件,并将其编译为 css

sass-loader:处理 sass、scss 文件,并将其编译为 css

postcss-loader:
// postcss.config.js
module.exports = { // 解析CSS文件并且添加浏览器前缀到 CSS 内容里
plugins: [require(‘autoprefixer’)],
};
复制代码

css-loader:处理 css 文件

style-loader:将 css 注入到 DOM

file-loader:将文件上的import / require 解析为 url,并将该文件输出到输出目录中

url-loader:用于将文件转换成 base64 uri 的 webpack 加载程序

10 vue ui 管理 vue3.0的项目

vue ui 可视化管理工具

11 功能代码

1. 循环生成 el-table
 
 <template>
    <div>
        <el-table
                ref="tab"
                stripe
                :header-cell-style="dealHeadStyle"
                :data="tabData">
            <el-table-column
                v-for ="(item,index) in colArr"
                :key="index"
                :prop="item.colName"
                :label="item.colName"
                width="180">
               <!-- <template slot-scope="scope">
                    <span>
                        {{scope.row[index]}},{{scope.row.sage}}
                    </span>
                </template>-->
                <slot :row="item" :$index="index"></slot>
            </el-table-column>
        </el-table>
        <hr>
        <el-table
                :data="tableData"
                style="width: 100%">
            <el-table-column
                    prop="date"
                    label="日期"
                    width="180">
            </el-table-column>
            <el-table-column
                    prop="name"
                    label="姓名"
                    width="180">
            </el-table-column>
            <el-table-column
                    prop="address"
                    label="地址"
                    width="280"
                    :formatter="formatter">
            </el-table-column>
            <el-table-column
                    prop="tag"
                    label="标签"
                    width="100"
                    :filters="[{ text: '家', value: '家' }, { text: '公司', value: '公司' }]"
                    :filter-method="filterTag"
                    filter-placement="bottom-end">
                <template slot-scope="scope">
                    <el-tag
                            :type="scope.row.tag === '家' ? 'primary' : 'success'"
                            close-transition>{{scope.row.tag}}</el-tag>
                </template>
            </el-table-column>
        </el-table>
    </div>
</template>

<script>
    export default {
        name: "tableTest",
        data(){
            return{
                tabData:[
                    {sid:'tefd989786',tNames:"TOM",sage:'20'},
                    {sid:'tefd989743',tNames:"LINDA",sage:'21'},
                    {sid:'tefd989754',tNames:"Jack",sage:'19'},
                    {sid:'tefd989752',tNames:"Alge",sage:'22'}
                ],
                colArr:[
                    {colName:'sid'},
                    {colName:'tNames'},
                    {colName:'sage'},
                ],
                
                tableData: [{
                    date: '2020-05-02',
                    name: '王小虎',
                    address: '旧金山普陀区金沙江路 1518 弄',
                    tag: '家'
                }, {
                    date: '2020-05-04',
                    name: '王大虎',
                    address: '普陀区金沙江路 1517 弄',
                    tag: '学校'
                }, {
                    date: '2020-05-01',
                    name: '王小名',
                    address: '上海市普陀区金沙江路 1519 弄',
                    tag: '家'
                },]
            }
        },
        methods:{
            //给表头添加背景色
            dealHeadStyle(){
                return{
                    background:'#2b2b2b'
                }
            },
            formatter(row, column) {
                return row.address;
            },
            filterTag(value, row) {
                return row.tag === value;
            }
        }
    }
</script>

<style scoped>
</style>

2. Vue slot
 vue slot
	1. 绑定模板
	  <slot name="title"></slot>
	  
	  及父组件  
	  
	  <div slot="title">这是页脚</div>
	  
	2. 作用域插槽
使用时候子组件标签中要有标签,再通过scopeName.childProp就可以调用子组件模板中的childProp绑定的数据,所以作用域插槽是一种子传父传参的方式 
	  <div id="app">
		<Child>
			<template slot="content" slot-scope="msg"><div>{{msg.data}}</div></template>
		</Child>
	</div>

	<template id="child" >
		<div>
			<div class="panel">
				<div class="title">这是标题</div>
				<div class="content">
					<slot name="content" :data="msg"></slot>			
				</div>
				<div class="footer">这是页脚</div>
			</div>
		</div>
	</template>
3. Promise (E)

XMLhttpRequest

var  xmlHttp = null;
    if(window.ActiveXObject)//IE
    {
      try {
        //IE6以及以后版本中可以使用
        xmlHttp = new ActiveXObject("Msxml2.XMLHTTP");
      }
      catch (e) {
        //IE5.5以及以后版本可以使用
        xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
      }
    }
    else if(window.XMLHttpRequest)//Firefox,Opera 8.0+,Safari,Chrome
    {
      xmlHttp = new XMLHttpRequest();
    }
    
//jquary 的ajax 封装的 xmlhttpRequest 
 
function sendAjax() {
  //构造表单数据
  var formData = new FormData();
  formData.append('username', 'johndoe');
  formData.append('id', 123456);
  //创建xhr对象 
  var xhr = xmlHttp ;
  //设置xhr请求的超时时间
  xhr.timeout = 3000;
  //设置响应返回的数据格式
  xhr.responseType = "text";
  //创建一个 post 请求,采用异步
  xhr.open('POST', '/server', true); //同步还是异步
  //注册相关事件回调处理函数
  xhr.onload = function(e) { 
    if(this.status == 200||this.status == 304){
        alert(this.responseText);
    }
  };
  xhr.ontimeout = function(e) { ... };
  xhr.onerror = function(e) { ... };
  xhr.upload.onprogress = function(e) { ... };
  
  //发送数据
  xhr.send(formData);  //发送请求是配置 同步还异步
	    //4代表数据发送完毕
    if ( xhr.readyState == 4 )
    {
      //0为访问的本地,200到300代表访问服务器成功,304代表没做修改访问的是缓存
      if((xhr.status >= 200 && xhr.status <300) || xhr.status == 0 || xhr.status == 304)
      {
        return true;
      }else{
        return false;
      }
    }
    else
    {
      return false;
    }
}

JS 文件流

file -> fileReader -> DataURL -> blob ->FormData

 	//传输文件 请求设置为
   'Content-Type': 'multipart/form-data'

   //axios 请求
    var oMyForm = new FormData();
      oMyForm.append("baseInfo", JSON.stringify(baseInfo))
     //存储文件blob对象
      oMyForm.append(imgeInfoList[x].key, imgeInfoList[x].blob, fileName);
      oMyForm.append("fileType", 'image');

   axios.post('onlineDataReport/upload', oMyForm, {
          'Content-Type': 'multipart/form-data'
        }).then(res => { })

 //jquary 发送 ajax
 
 
        

js方法

----------------js  正则匹配-------------
	var arr = str.match(/(iid=?)(\S*)(?=ffr)/);
	
	var pattern = /^\d+(\.\d{1,2})?$/;
		
   bol  pattern.test(str)
----------------js map -------------------		

(function(arr){ arr.forEach(item => { console.log(item)})})(["1","2"])
		
var data = [["2000-06-05",116],["2000-06-06",129],["2000-06-07",135],["2000-06-08",86],["2000-06-09",73],["2000-06-10",85],["2000-06-11",73],["2000-06-12",68],["2000-06-13",92],["2000-06-14",130],["2000-06-15",245],["2000-06-16",139],["2000-06-17",115],["2000-06-18",111],["2000-06-19",309],["2000-06-20",206],["2000-06-21",137],["2000-06-22",128],["2000-06-23",85],["2000-06-24",94],["2000-06-25",71],["2000-06-26",106],["2000-06-27",84],["2000-06-28",93],["2000-06-29",85],["2000-06-30",73],["2000-07-01",83],["2000-07-02",125],["2000-07-03",107],["2000-07-04",82],["2000-07-05",44],["2000-07-06",72],["2000-07-07",106],["2000-07-08",107],["2000-07-09",66],["2000-07-10",91],["2000-07-11",92],["2000-07-12",113],["2000-07-13",107],["2000-07-14",131],["2000-07-15",111],["2000-07-16",64],["2000-07-17",69],["2000-07-18",88],["2000-07-19",77],["2000-07-20",83],["2000-07-21",111],["2000-07-22",57],["2000-07-23",55],["2000-07-24",60]];

var dateList = data.map(function (item) {
    return item[0];
});
var valueList = data.map(function (item) {
    return item[1];
});

----------------js reduce-------------------

var arrayObj = [
	{
	name: 'Tonks',
    house: 'Hufflepuff'
	}


var hufflepuff = arrayObj.reduce(function (newArr, wizard) {
  if (wizard.house === 'Hufflepuff') {
    newArr.push(wizard.name);
  }
  return newArr;
}, []);

var arr = [1, 2, 3, 4];
var sum = arr.reduce(function(prev, cur, index, arr) {
    console.log(prev, cur, index);
    return prev + cur;
})

let names = ['Alice', 'Bob', 'Tiff', 'Bruce', 'Alice'];

let nameNum = names.reduce((pre,cur)=>{
  if(cur in pre){
    pre[cur]++
  }else{
    pre[cur] = 1 
  }
  return pre
},{})
console.log(nameNum); //{Alice: 2, Bob: 1, Tiff: 1, Bruce: 1}




----------类型定义------------------------

  {...to}   //深拷贝 将to的参数全部整合到
	var socketMaps = {
	    "keya": {
	        "1": "abc",
	        "a": "123"
	    },
	    "keyb": {
	        "2": "abc1",
	        "aa": "123123"
	    }
	};
	 
	function getAllUsers() {
	    let allUsers = [];
	    for(let [key, value] of Object.entries(socketMaps)){
	        allUsers.push({
	            id: key,
	            ...value
	        });
	    }
	    return allUsers;
	}
	 
	console.log("\n getAllUsers =", getAllUsers());
 
/**
 getAllUsers = [ { '1': 'abc', id: 'keya', a: '123' },
 { '2': 'abc1', id: 'keyb', aa: '123123' } ]
**/



// ~~和 | 
~~它代表双非按位取反运算符,如果你想使用比Math.floor()更快的方法,那就是它了。需要注意,对于正数,它向下取整;对于负数,向上取整;非数字取值为0,它具体的表现形式为:
	~~null;      // => 0
	~~undefined; // => 0
	~~Infinity;  // => 0
	~~NaN;       // => 0
	~~0;         // => 0
	~~{};        // => 0
	~~[];        // => 0
	~~(1/0);     // => 0
	~~false;     // => 0
	~~true;      // => 1
	~~1.9;       // => 1
	~~-1.9;      // => -1
// | 的用法,通常用来取整
	1.2 | 0  // 1
	1.8 | 0  // 1
	-1.2 | 0  // -1
  
 let year2, month2, day2, hour2;
      [year2, month2, day2, hour2] = [d.getFullYear(), d.getMonth(), d.getDate(), d.getHours()]
	  
	   
 var statusMap ={
		a:1,
		b:2
	  }
	  
	   function findKey(value, compare = (a, b) => a === b) {
        return Object.keys(statusMap).find(k => compare(statusMap[k], value))
      },
	  
	  findKey(1);
	  
----------------Object.keys()--------------------  
	  
	  let person = {name:"张三",age:25,address:"深圳",getName:function(){}}

		Object.keys(person).map((key)=>{
		  person[key] // 获取到属性对应的值,做一些处理
   }) 
		
-------------------------Array 内置函数-----

1、Array.prototype.some  数组对象内置方法
2、Array.prototype.every  数组对象内置方法



3、Array.prototype.indexOf  数组对象内置方法
4、Array.prototype.lastIndexOf 数组对象内置方法
5、for...in循环语句

array.merge()  
array.concat()
array.push()   //正序插入
array.unshift()  //倒叙插入
var a = [1,2,3];
a.forEachCopy(function(value,key,arr){
    console.log(value)    // 结果依次为1,2,3
    console.log(key)      // 结尾依次为0,1,2
    console.log(arr)      // 三次结果都为[1,2,3]
})




//-------------类型转换-------------
parseFloat
parseInt


H5

<!-- JOSN 格式标签-->
<pre></pre>
<!--画布-->
<canvas></canvas>


<!DOCTYPE HTML>
<html>

<body>

<form>
  <fieldset>
    <legend>健康信息</legend>
    身高:<input type="text" />
    体重:<input type="text" />
  </fieldset>
</form>

<p>如果表单周围没有边框,说明您的浏览器太老了。</p>

</body>
</html>

原型链

在这里插入代码片

React

react的生态圈非常庞大,第三方的构建工具也有很多种,比如圈内常用的generator-react-webpack,它是需要yeoman的支持的,当然你可以手打webpack都是一样的

1.安装
npm install -g yo 缩写
npm install -g generator-react-webpack
yo ‘projectName’

方式2
npm install -g create-react-app
create-react-app my-app my-app为自己的demo名称

结构

Electron

cript
	
1.npm init  创建一个新的空文件夹

只能在主进程使用的:
app:控制你整个 Electron 应用的生命周期
BrowserWindow:创建和控制应用的窗口
ipcMain:用于主进程中,和渲染进程通信的
webContents:渲染和控制你窗口中的 web 内容的(因为 Electron 中,你是用 web 写的界面)
可以在渲染进程使用的:

ipcRenderer:用于渲染进程中,和主进程通信的
remote:可以方便你在渲染进程中直接调用主进程的方法
<webview> Tag:可以载入外界的网页

第三方库   electron-vue 脚手架创建项目  

2.npm install -g vue-cli
vue init simulatedgreg/electron-vue my-project
# 安装依赖并运行你的程序
cd my-project
yarn # 或者 npm install
yarn run dev # 或者 npm run dev

用 electron 搭建载体   运行vue项目  可以使用 electron的 api

thyleamf

 		<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>
        //@Controller 不能是 @RestController

//yml 
spring:
  # 模板引擎
  thymeleaf:
    mode: HTML
    encoding: utf-8
    # 禁用缓存
    cache: false

语法

 • th:action 定义后台控制器路径。
    • th:each 1,盾环语-句。
    • th:field 表单字段绑定。
    • th:href 定义超链接。
    • th:id div 标签中的ID 声明,类似HTML 标签中的归属性。
    • th:if 条件判断语句。
    • th:include 布局标签,替换内容到引入文件。
    • th :企agment 布局标签,定义一个代码片段,方便其他地方引用。
    • th:object 替换对象。
    • th:src 图片类地址引入。
    • th:text 显示文本。
    • th:value 属性赋值。


    • ${...}变量表达式。
    •*{ .. . } 选择表达式。
    •#{...}消息文字表达式。
    •@{} 链接url 表达式。
    • #maps 工具对象表达式。

     public ModelAndView test(HttpServletRequest req) {
	        // UserEntity userEntity = getCurrentUser(req);
	        UserEntity user = new UserEntity();
	        user.setLoginName("tom");
	        user.setId(234);
	        user.setBindType(1);
	        ModelAndView mv = new ModelAndView();
	        mv.addObject("user", user);
	        mv.setViewName("/user/show.html");
	        return mv;
	    }

th:fragment=header(title)
th:fragment=“footer”
th:object
th:field

eq:


循环

th:each属性用于迭代循环,语法:th:each=“obj,iterStat:${objList}”
迭代对象可以是java.util.List,java.util.Map,数组等;

iterStat称作状态变量,属性有:
    index:当前迭代对象的index(从0开始计算)
    count: 当前迭代对象的index(从1开始计算)
    size:被迭代对象的大小
    current:当前迭代变量
    even/odd:布尔值,当前循环是否是偶数/奇数(从0开始计算)
    first:布尔值,当前循环是否是第一个
    last:布尔值,当前循环是否是最后一个
逻辑运算
${id ?: 'toolbar1'}
eq:
<block th:if="${btns}" >
</block>
<!--/* btns为空时显示(除非btns不为空才不显示) */-->   等同   th:if="${not testBoolean}"  
<block th:unless="${btns}" >      

</block>

模板

xmlns:th=“http://www.thymeleaf.org”
xmlns:shiro=“http://www.pollix.at/thymeleaf/shiro”

<!DOCTYPE html>
<html lang="zh" xmlns:th="http://www.thymeleaf.org">
<head>
    <th:block th:include="include_test :: header('代码生成列表')" />
</head>
<body>
<th:block th:include="include_test :: footer" />
<script th:inline="javascript">
   // 初始时候触发
    $(function() {
        var options = {

        }
    });
    </script>
</body>
</html>

被包含的html

include_test.html

<!-- 通用 头 -->
<head th:fragment=header(title)>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="keywords" content="">
    <meta name="description" content="">
    <title th:text="${title}"></title>
    <link rel="shortcut icon" href="favicon.ico">
    <link th:href="@{/css/bootstrap.min.css}" rel="stylesheet"/>
</head>
<!-- 通用JS -->
<div th:fragment="footer">
    <script th:inline="javascript"> var ctx = [[@{/}]]; var lockscreen = [[${session.lockscreen}]]; if(lockscreen){window.top.location=ctx+"lockscreen";} </script>
    <a id="scroll-up" href="#" class="btn btn-sm display"><i class="fa fa-angle-double-up"></i></a>
    <script th:src="@{/js/jquery.min.js}"></script>
    <script th:src="@{/js/bootstrap.min.js}"></script>
    <!-- bootstrap-table 表格插件 -->
    <script th:src="@{/ajax/libs/bootstrap-table/bootstrap-table.min.js?v=20210202}"></script>
    <script th:src="@{/ajax/libs/bootstrap-table/locale/bootstrap-table-zh-CN.min.js?v=20210202}"></script>
    <script th:src="@{/ajax/libs/bootstrap-table/extensions/mobile/bootstrap-table-mobile.min.js?v=20210202}"></script>
    <!-- jquery-validate 表单验证插件 -->
    <script th:src="@{/ajax/libs/validate/jquery.validate.min.js}"></script>
    <script th:src="@{/ajax/libs/validate/messages_zh.min.js}"></script>
    <script th:src="@{/ajax/libs/validate/jquery.validate.extend.js}"></script>
    <!-- jquery-validate 表单树插件 -->
    <script th:src="@{/ajax/libs/bootstrap-treetable/bootstrap-treetable.js}"></script>
    <!-- 遮罩层 -->
    <script th:src="@{/ajax/libs/blockUI/jquery.blockUI.js}"></script>
    <script th:src="@{/ajax/libs/iCheck/icheck.min.js}"></script>
    <script th:src="@{/ajax/libs/layer/layer.min.js}"></script>
    <script th:src="@{/ajax/libs/layui/layui.js}"></script>
    <script th:src="@{/test/test.js}"></script>
</div>

Freemarker

语法指令

循环

逻辑

	${!("")}  
	<#if c??>   
	
	</#if> 

直接调用后台方法代码
<PRE class=ftl name="code">默认两种用法   
${!("")}   
${default("")}</PRE>   
<@s.property value="%{getPieceByType(type)}"/>   
getPieceByType为方法名,type为值  

Ftl代码默认两种用法   ${!("")}   ${default("")}  默认两种用法 
${!("")} 
${default("")} 
<@s.property value="%{getPieceByType(type)}"/> 
getPieceByType为方法名,type为值 

时间格式化的方法代码 
最好加上 判断下c时候存在   
<#if c??>   
${c.addtime?string("yyyy-MM-dd HH:mm:ss")   
</#if>  

最好加上判断下c时候存在 
<#if c??> 
${c.addtime?string("yyyy-MM-dd HH:mm:ss") 
</#if>  

判断长度并截取代码 
<#if c.titleH1??>   
<#if c.titleH1?length lt 33>   
${c.titleH1}   
action 中   
配置    
private String inputPath;    
private HttpServletResponse servletResponse;    

public void setServletResponse(HttpServletResponse arg0) {   
this.servletResponse = arg0;    
}   

public HttpServletResponse getServletResponse() {   
return servletResponse;   
}    

public String formguideDownloads() throws Exception {   
formguide.setTemplateId(formguide.getTemplateId()+".jsp");     
return SUCCESS;         
}   

xml中配置   
<action name="formguideDownloads" class="com.jcauto.cms.action.FormguideAction" method="formguideDownloads">       
<result name="success" type="stream">       
<param name="contentType">text/plain;charset=utf-8</param>     
<param name="inputName">inputStream</param>         
<param name="contentDisposition">attachment;filename="${formguide.templateId}"</param>     
<param name="bufferSize">4096</param>       
</result>     
</action>      

页面上   
formguide/formguideDownloads.action?formguide.templateId=${form.templateId?if_exists}&inputPath=${fileUrlFileName?if_exists}${form.templateId?if_exists}.jsp" <#else>   
${c.titleH1[0..32]}...   
</#if>   
</#if>   
注意length是从0开始算所以如果想截取33位就使用0..32就可以了  

<#if c.titleH1??> 
<#if c.titleH1?length lt 33> 
${c.titleH1} 
action 中 
配置 
private String inputPath; 
private HttpServletResponse servletResponse; 

public void setServletResponse(HttpServletResponse arg0) { 
this.servletResponse = arg0; 
} 

public HttpServletResponse getServletResponse() { 
return servletResponse; 
} 

public String formguideDownloads() throws Exception { 
formguide.setTemplateId(formguide.getTemplateId()+".jsp");  
return SUCCESS;      
} 

xml中配置 
<action name="formguideDownloads" class="com.jcauto.cms.action.FormguideAction" method="formguideDownloads">    
<result name="success" type="stream">    
<param name="contentType">text/plain;charset=utf-8</param>  
<param name="inputName">inputStream</param>      
<param name="contentDisposition">attachment;filename="${formguide.templateId}"</param>  
<param name="bufferSize">4096</param>    
</result>  
</action>   

页面上 
formguide/formguideDownloads.action?formguide.templateId=${form.templateId?if_exists}&inputPath=${fileUrlFileName?if_exists}${form.templateId?if_exists}.jsp" <#else> 
${c.titleH1[0..32]}... 
</#if> 
</#if> 
注意length是从0开始算所以如果想截取33位就使用0..32就可以了 

List-map使用代码 
ftl.list   
<#list List as list>   
${list}   
</#list>   
list_index取出行号索引从0开始                 
formguideList?size 可以判断list大小   
这里多说一句有很多list中属性的用法不一一列举,大家可以查下ftl API    
ftl.map   
<#list Map?keys as s>   
${Map[s]}   
</#list>   

s.list   
<@s.iterater value="List" var=list>   
</@s.iterater>   
s.if   
<@s.if>   
</@>   
<@s.else>   
</@>   
ftl.if   
<#if>   
<#else>   
</#if>  

ftl.list 
<#list List as list> 
${list} 
</#list> 
list_index取出行号索引从0开始              
formguideList?size 可以判断list大小 
这里多说一句有很多list中属性的用法不一一列举,大家可以查下ftl API 
ftl.map 
<#list Map?keys as s> 
${Map[s]} 
</#list> 

s.list 
<@s.iterater value="List" var=list> 
</@s.iterater> 
s.if 
<@s.if> 
</@> 
<@s.else> 
</@> 
ftl.if 
<#if> 
<#else> 
</#if> 

上传代码 
<form actoin="${path}/piece/findPiece.action" name="form1" method="Post" enctype="multipart/form-data">    
<s:file name="sfile"/>   
</form>   
后台action中配置   
File sfile;   
String sfileName;   
String sfileType;  

<form actoin="${path}/piece/findPiece.action" name="form1" method="Post" enctype="multipart/form-data"> 
<s:file name="sfile"/> 
</form> 
后台action中配置 
File sfile; 
String sfileName; 
String sfileType; 

下载代码 
前台   
<a href="${path}/formguide /formguideDownloads.action?formguide.templateId=${form.templateId?if_exists}& amp;inputPath=${fileUrlFileName?if_exists}${form.templateId?if_exists}.jsp"& gt;下载</a> |     

后台   
private HttpServletResponse servletResponse;     
private String inputPath;    
public void setServletResponse(HttpServletResponse arg0) {   
this.servletResponse = arg0;    
}   

public HttpServletResponse getServletResponse() {   
return servletResponse;   
}   
public String formguideDownloads() throws Exception {   
formguide.setTemplateId(formguide.getTemplateId()+".jsp");     
return SUCCESS;         
}   

public InputStream getInputStream() throws Exception {    
return ServletActionContext.getServletContext().getResourceAsStream(   
inputPath);     
}   

xml   
<action name="formguideDownloads" class="com.jcauto.cms.action.FormguideAction" method="formguideDownloads">       
<result name="success" type="stream">       
<param name="contentType">text/plain;charset=utf-8</param>     
<param name="inputName">inputStream</param>         
<param name="contentDisposition">attachment;filename="${formguide.templateId}"</param>     
<param name="bufferSize">4096</param>       
</result>     
</action>    

前台 
<a href="${path}/formguide /formguideDownloads.action?formguide.templateId=${form.templateId?if_exists}& amp;inputPath=${fileUrlFileName?if_exists}${form.templateId?if_exists}.jsp"& gt;下载</a> |  

后台 
private HttpServletResponse servletResponse;  
private String inputPath; 
public void setServletResponse(HttpServletResponse arg0) { 
this.servletResponse = arg0; 
} 

public HttpServletResponse getServletResponse() { 
return servletResponse; 
} 
public String formguideDownloads() throws Exception { 
formguide.setTemplateId(formguide.getTemplateId()+".jsp");  
return SUCCESS;      
} 

public InputStream getInputStream() throws Exception { 
return ServletActionContext.getServletContext().getResourceAsStream( 
inputPath);  
} 
xml 
<action name="formguideDownloads" class="com.jcauto.cms.action.FormguideAction" method="formguideDownloads">    
<result name="success" type="stream">    
<param name="contentType">text/plain;charset=utf-8</param>  
<param name="inputName">inputStream</param>      
<param name="contentDisposition">attachment;filename="${formguide.templateId}"</param>  
<param name="bufferSize">4096</param>    
</result>  
</action>    

Ftl中的循环代码 
使用宏标签来循环生成固定的值   
其中local中来定义值   
repeat用来生成   
<#macro repeat count>   
<#local y = "<img src='http://www.jcauto.com.cn/ProConsole/images/star0506.gif' border='0' alt='' width='11' height='11'/>">   
<#list 1..count as x>   
${y} ${count}/${x}: <#nested>   
</#list>   
</#macro>   
<@repeat count=3>${y?default("?")} ${x?default("?")} ${count?default("?")}</@repeat>  

使用宏标签来循环生成固定的值 
其中local中来定义值 
repeat用来生成 
<#macro repeat count> 
<#local y = "<img src='http://www.jcauto.com.cn/ProConsole/images/star0506.gif' border='0' alt='' width='11' height='11'/>"> 
<#list 1..count as x> 
${y} ${count}/${x}: <#nested> 
</#list> 
</#macro> 
<@repeat count=3>${y?default("?")} ${x?default("?")} ${count?default("?")}</@repeat> 

Ftl变量转换代码 
?number转为数字   
?c转为字符串   
?string转为字符串   
?currency(货币)   
?percent(百分比)   
trim 删除字符串首尾空格 ${“  String ”?trim} 结果为String   
split使用指定的分隔符将一个字符串拆分为一组字符串   
<#list “This|is|split”?split(“|”) as s>   
${s}   
</#list>   
${“strabg”?replace(“ab”,”in”)} 结果为string   
${“string”?contains(“ing”)?string} 结果为true   
注意:布尔值必须转换为字符串才能输出   
${“string”?index_of(“in”) 结果为3  
${“string”?index_of(“ab”) 结果为-1  
length返回字符串的长度 ${“string”?length}结果为6  
lower_case将字符串转为小写   
${“STRING”?lower_case}à结果为string   
upper_case将字符串转为大写   
${“string”?upper_case}à结果为STRING   
ends_with 判断某个字符串是否由某个子串结尾,返回布尔值。   
${“string”?ends_with(“ing”)?string} 返回结果为true   
注意:布尔值必须转换为字符串才能输出   
html 用于将字符串中的<、>、&和“替换为对应得&lt;&gt;&quot:&amp   
index_of(substring,start)在字符串中查找某个子串,返回找到子串的第一个字符的索引,如果没有找到子串,则返回-1。   
Start参数用于指定从字符串的那个索引处开始搜索,start为数字值。   
如果start大于字符串长度,则start取值等于字符串长度,如果start小于0, 则start取值为   
${‘str’?substring(0)}à结果为str   
${‘str’?substring(0,1)}à结果为s   

2.cap_first 将字符串中的第一个单词的首字母变为大写。   
${‘str’?cap_first}à结果为Str   

3.uncap_first将字符串中的第一个单词的首字母变为小写。   
${‘Str’?cap_first}à结果为str   

4.capitalize将字符串中的所有单词的首字母变为大写   
${‘str’? capitalize}à结果为STR   
date,time,datetime将字符串转换为日期   
例如:   
<#assign date1=”2009-10-12”?date(“yyyy-MM-dd”)>   
<#assign date2=”9:28:20”?time(“HH:mm:ss”)>   
<#assign date3=” 2009-10-12 9:28:20”?time(“HH:mm:ss”)>   
${date1}à结果为2009-10-12  
${date2}à结果为9:28:20  
${date3}à结果为2009-10-12 9:28:20  

?number转为数字 
?c转为字符串 
?string转为字符串 
?currency(货币) 
?percent(百分比) 
trim 删除字符串首尾空格 ${“  String ”?trim} 结果为String 
split使用指定的分隔符将一个字符串拆分为一组字符串 
<#list “This|is|split”?split(“|”) as s> 
${s} 
</#list> 
${“strabg”?replace(“ab”,”in”)} 结果为string 
${“string”?contains(“ing”)?string} 结果为true 
注意:布尔值必须转换为字符串才能输出 
${“string”?index_of(“in”) 结果为3 
${“string”?index_of(“ab”) 结果为-1 
length返回字符串的长度 ${“string”?length}结果为6 
lower_case将字符串转为小写 
${“STRING”?lower_case}à结果为string 
upper_case将字符串转为大写 
${“string”?upper_case}à结果为STRING 
ends_with 判断某个字符串是否由某个子串结尾,返回布尔值。 
${“string”?ends_with(“ing”)?string} 返回结果为true 
注意:布尔值必须转换为字符串才能输出 
html 用于将字符串中的<、>、&和“替换为对应得&lt;&gt;&quot:&amp 
index_of(substring,start)在字符串中查找某个子串,返回找到子串的第一个字符的索引,如果没有找到子串,则返回-1。 
Start参数用于指定从字符串的那个索引处开始搜索,start为数字值。 
如果start大于字符串长度,则start取值等于字符串长度,如果start小于0, 则start取值为 
${‘str’?substring(0)}à结果为str 
${‘str’?substring(0,1)}à结果为s 

2.cap_first 将字符串中的第一个单词的首字母变为大写。 
${‘str’?cap_first}à结果为Str 

3.uncap_first将字符串中的第一个单词的首字母变为小写。 
${‘Str’?cap_first}à结果为str 

4.capitalize将字符串中的所有单词的首字母变为大写 
${‘str’? capitalize}à结果为STR 

date,time,datetime将字符串转换为日期 
例如: 
<#assign date1=”2009-10-12”?date(“yyyy-MM-dd”)> 
<#assign date2=”9:28:20”?time(“HH:mm:ss”)> 
<#assign date3=” 2009-10-12 9:28:20”?time(“HH:mm:ss”)> 
${date1}à结果为2009-10-12 
${date2}à结果为9:28:20 
${date3}à结果为2009-10-12 9:28:20 

宏定义hash内置函数代码 
Hash的内置函数   
1.hash?keys 返回hash里的所有key,返回结果为sequence   

2.hash?values 返回hash里的所有value,返回结果为sequence   
例如:   
<#assign user={“name”:“hailang”, “sex”:“man”}>   
<#assign keys=user?keys>   
<#list keys as key>   
${key}=${user[key]}   
</#list>  

Hash的内置函数 
1. hash?keys 返回hash里的所有key,返回结果为sequence 

2.hash?values 返回hash里的所有value,返回结果为sequence 
例如: 
<#assign user={“name”:“hailang”, “sex”:“man”}> 
<#assign keys=user?keys> 
<#list keys as key> 
${key}=${user[key]} 
</#list>

 类似资料: