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 代理
可在点此在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
设置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
主要配置文件
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组件
npm install --global vue-cli
1.创建基于 webpack 模板的项目
Vue init webpack my-project
是否安装路由 yes
等。。。
npm uninstall -g vue-cli – 卸载
npm install -g @vue/cli
import merge from 'lodash/merge'
或
const merge = require('webpack-merge')
objA = merge(objB,objC)
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'
})
require 是赋值过程并且是运行时才执行,require可以理解为一个全局方法 带index.js 入口的 文件夹
import 是解构过程并且是编译时执行,import必须写在文件的顶部 import 是 js文件 export function login () { } 或 module.exports = { }
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");
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 // 具体到那个模块的变量
}
}
},
1.父组件 在子组件上绑定方法
@fatherMethod="getTodayReports"
2 子组件内部
this.$emit('fatherMethod',params);
配置
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 加载程序
vue ui 可视化管理工具
<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>
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>
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;
}
}
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 正则匹配-------------
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
<!-- 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的生态圈非常庞大,第三方的构建工具也有很多种,比如圈内常用的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名称
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
<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>
语法指令
${!("")}
<#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 用于将字符串中的<、>、&和“替换为对应得<>":&
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 用于将字符串中的<、>、&和“替换为对应得<>":&
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>