Hybrid
基于 Vue 的前后端混合开发环境
安装使用
<script src="//pubic.zhfile.com/js/ray.js">
<script src="//pubic.zhfile.com/js/pack.hybrid.js">
基础选项
# 调试模式,使用 Vue devtools
debug : false
# 签名参数
token : ''
# 版本编号
build : ''
# 百度统计ID
baidu : ''
# 阿里妈妈PID
mapid : ''
# 附件目录
attach : '/attach/'
# 公共文件目录
public : '/public/'
# 文件上传接口
upload : '/upload/native'
# 文件删除接口
remove : '/upload/remove'
# 返回顶部元素
scroll : '.gotop'
# Vue 可选数据
option : {}
# Vue 扩展对象
extend : {}
# Vue 绑定元素
element : '#app'
# 标题规则
docname : {}
# 模块配置
modules : {}
# Cookie 前缀
prefix : ''
# 短网址生成接口
shorten : '/fn/tinyurl'
# 错误消息收集接口
jserror : '/fn/jserror'
初始化
# 默认配置
Hybrid.Start( );
# 指定标题名称
Hybrid.Start( { docname : { 'result' : 'goods_name' } } );
# 附加可选数据
Hybrid.Start( option : ( typeof option != 'undefined' ? option : {} ), { docname : { 'result' : 'goods_name' } } );
# 附加扩展对象
Hybrid.Start( option : ( typeof extend != 'undefined' ? extend : {} ), { docname : { 'result' : 'goods_name' } } );
# 更改其他选项
Hybrid.Start( token : '4e51967f2d70f4b6', { docname : { 'result' : 'goods_name' }, shorten : 'http://dwz.cn/add' } );
数据模板
基本模板
<fragment type="template">...</fragment>
flag
数据标识,用于 Vue 模板访问
<fragment type="template" flag="sample">
<a v-bind:href="'detail?id=' + object.sample.goods_id">{{object.sample.goods_name}}</a>
</fragment>
source
数据来源:URL 地址
<fragment type="template" flag="sample" source="/detail/related">...</fragment>
cache
是否缓存:true 或 false,默认 false
<fragment type="template" flag="sample" cache="true">...</fragment>
lazy
延迟加载:数值,单位秒,默认 0
<fragment type="template" flag="sample" lazy="5">...</fragment>
reload
自动刷新:数值,单位秒,默认 0
<fragment type="template" flag="sample" reload="10">...</fragment>
listen
监听对象:选择器,通常与 event 属性配合使用
<fragment type="template" flag="sample" listen=".btn a">...</fragment>
<fragment type="template" flag="sample" listen="window">...</fragment>
event
事件行为:有效的事件名称,如 click / change / scroll 等
<fragment type="template" flag="sample" event="click">...</fragment>
通常与 listen 属性配合使用
<fragment type="template" flag="sample" listen=".btn a" event="click">...</fragment>
<fragment type="template" flag="sample" listen="window" event="scroll">...</fragment>
initial
是否初始化数据:true 或 false,事件触发时不会主动加载,可以使用此选项来初始化
<fragment type="template" flag="sample" initial="true">...</fragment>
paging
是否有分页:true 或 false,默认 false,会处理页码,通常与 分页组件 配合使用
<fragment type="template" flag="sample" paging="true">...</fragment>
padding
是否启用数据填充:true 或 false,默认 false,为 true 时将不断进行数据累加
<fragment type="template" flag="sample" padding="true">...</fragment>
history
是否启用历史记录:true 或 false,会更新 URL 至 state
<fragment type="template" flag="sample" history="true">...</fragment>
分页组件
next 仅下一页
<paging next="true" :numbers="numbers" :current="current" :pagenum="pagenum" v-on:paging="paging"></paging>
prev 上下分页
<paging prev="true" next="true" :numbers="numbers" :current="current" :pagenum="pagenum" v-on:paging="paging"></paging>
nums 带页码分页
<paging prev="true" next="true" nums="true" :numbers="numbers" :current="current" :pagenum="pagenum" v-on:paging="paging"></paging>
表单提交
标签属性
<form method="post" target="ajax"></form>
表单验证
语法示例
<input type="text" class="form-control" data-valid-name="用户昵称" data-valid-empty="yes" />
支持属性
# data-valid-name
提示文字 * 必填项
# data-valid-empty
"yes" 强制检查,"no" 值可为空,不为空时检查
# data-valid-number
同上,数字类检查
# data-valid-secure
同上,安全字符检查
# data-valid-password
同上,密码类型属性,CSS 表达式或其他
# data-valid-ip
同上,IP地址型属性
# data-valid-url
同上,链接地址属性
# data-valid-email
同上,邮箱地址属性
# data-valid-idcard
同上,身份证号属性
# data-valid-phone
同上,电话号码属性
# data-valid-mobile
同上,手机号码属性
# data-valid-datetime
同上,时间日期属性
# data-valid-regexp
同上,正则表达式
# data-valid-confirm
字符串,将当前值与目标元素的值进行比较(CSS 选择器)
# data-valid-minsize
数值,字符最小长度
# data-valid-maxsize
数值,字符最大长度
# data-valid-accept
字符串,允许上传的扩展名(以空隔分隔),针对文件选择器有效
Ajax 处理
A 标签
<a data-type="ajax" data-href="/detail/request">...</a>
INPUT 标签
<input type="text" name="url" data-type="ajax" data-href="/debug/checkin?url=" />
input 的值会附加到 data-href 内容后面,然后发起 Ajax 请求,可以配合 data-variable 将返回的值写入变量
data-confirm 确认操作
<a data-type="ajax" data-href="/detail/request" data-confirm="确定吗?">...</a>
当点击 "确定" 后,才会发起 Ajax 请求
data-message 提示信息
<a data-type="ajax" data-href="/detail/request" data-message="我知道了">...</a>
仅弹出提示信息,不会发起 Ajax 请求
data-caching 是否缓存
<a data-type="ajax" data-href="/detail/request" data-caching="true">...</a>
data-execute 执行事件
<a data-type="ajax" data-href="/detail/request" data-execute="click">...</a>
会在页面加载完成后,自动执行一次事件
data-variable 更新变量
# 更新指定变量
<a data-type="ajax" data-href="/detail/request" data-variable="object.result.goods_name">...</a>
# 更新动态变量
<div v-for="(v, k) in object.manual">
<a data-type="ajax" data-href="/detail/change" v-bind:data-variable="'object.manual.'+ k +'.price'">
¥ <strong>{{v.price}}</strong>
</a>
</div>
data-padding 追加数据
<a data-type="ajax" data-href="/detail/request" data-variable="object.comment" data-padding="true">...</a>
当 object.comment 不存在时,会使用 Vue.set 方法创建对象并赋值,否则将会执行 push 方法追加数据
data-callback 回调方法
<a data-type="ajax" data-href="/detail/request" data-callback="console.log">...</a>
回调函数可以接收两个参数 console.log( data, node ),其中 data 为当前返回数据,node 是当前 ajax 发起元素 <a />
data-duration 消息时长,单位:秒
<button data-duration="10" data-type="ajax" data-message="Hello World!">消息提示</button>
后端响应
处理返回
<?php
Response::callback( array( 'status'=> 0, 'result'=> $result ), $this->ajax );
常规数据
{
'status'=> 0,
'result'=> $data
}
Ajax 消息
{
'status'=> 0,
'result'=> '操作成功'
}
变量数据
{
'status'=> 0,
'result'=> '操作成功',
'variable'=> '这是一条字符串'
}
{
'status'=> 0,
'result'=> '操作成功',
'variable'=> {
'goods_id' => 530598549821,
'goods_name' => '美多丝洗发'
}
}
{
'status'=> -1000,
'result'=> '操作失败',
'variable'=> null
}
带分页信息
{
// 返回状态
'status'=> 0,
// 当前页码
'paging'=> $page,
// 每页数量
'limit'=> $size,
// 总记录数
'total'=> $this->db->numRows,
// 本页数据
'result'=> $data
}
其他数据
{
// 重置表单:true 或 false
'reset'=> true,
// 是否刷新:true 或 false
'reload'=> true,
// 是否回退:true 或 false
'backing'=> true,
// 替换链接
'replace'=> 'http://www.baidu.com',
// 跳转链接
'target'=> 'http://www.baidu.com'
}
status 规范
0 没有错误
{
'status'=> 0,
'result'=> '操作成功'
}
> 0 消息编号
{
'status'=> 12345,
'result'=> '用户注册成功'
}
< 0 错误编号
{
'status'=> -1000,
'result'=> '必要的错误不能为空'
}
Vue 方法
nl2br( value )
将换行符替换成 <br />
Hybrid.App.nl2br();
format( value, format )
日期和时间格式化
Hybrid.App.format();
truncate( value, length )
字符串截断方法
Hybrid.App.truncate();
currency( value )
货币金额格式化
Hybrid.App.currency();
numerical( value )
大数字格式化,如:9.5万
Hybrid.App.numerical();
resized( imgsrc, sized )
调整图片尺寸
Hybrid.App.nl2br();
convert( detail )
商品详情链接
Hybrid.App.convert( detail );
wechat()
检测是否为微信浏览器,在微信中会返回微信版本号,否则返回 false
Hybrid.App.wechat();
"6.0.2.56"
nettype()
检测网络类型(微信环境),在微信中会返回当前网络类型(WIFI / 2G / 3G+),否则返回 null
Hybrid.App.nettype();
"WIFI"
mobile()
检测是否为手机浏览器,在移动设备中返回设备类型(iPhone / iPod / Android / iOS / SymbianOS / Windows Phone),否则返回 false
Hybrid.App.mobile();
"Android"
qrcode( data )
返回二维码 URL 地址
Hybrid.App.qrcode( data );
createUrl( parts, param, anchor )
URL 生成,parts:路径参数,param:GET 参数,anchor:锚点名称
多模块时,需要在 modules 中传入模块信息
Hybrid.App.createUrl( parts, param, anchor );
其他功能
Vue 可选数据
{{ option }}
Vue 扩展对象
var extend = {
data : {
option : {
sites : {"baidu.com":"weibo.com","sina.com"}
}
},
methods : {
test: function(){
alert( this.pagenum );
}
},
mounted : function(){
console.log('mounted');
}
};
Hybrid.Start( 'extend' : extend );
{{ option.sites }}
<a v-on:click="test()">Test!</a>
Vue URL参数
{{ params }}
示例数据,从当前 URL 中提取 GET 参数,其中数组(parent[child])将自动转换成 parent.child 格式
{ 'id' : 123456, 'text' : 'hello', 'data' : { 0 : 'aaa', 1 : 'bbb' }, 'extra.site' : 'tmall', 'extra.name' : '天猫' }
Vue 模板
Vue 处理完成后,显示元素,需要在 CSS 中定义 [v-cloak]{ display:none; }
<fragment type="template" v-cloak>...</fragment>
编辑器对象
Hybrid.Editor
日志上报
# 暂存一条记录
Hybrid.Context( 'foo', 'abc' );
# 清空上下文
Hybrid.Context();
# 暂存多条记录
Hybrid.Context( 'foo', '123', 'bar', '456' );
# 上报日志信息
Hybrid.Report( message, source, lineno, colno, error );
提示样式
#toast{ }
#toast.default{ /* 普通样式 */ }
#toast.success{ /* 成功样式 */ }
#toast.invalid{ /* 失败样式 */ }
原生上传
<input type="file" model="native" config="" />
<input type="file" model="native" config='{ "model" : "pics", "multi" : 5 }' />
<input type="file" model="native" config='{ "model" : "pics", "multi" : 5 }' value="//www.baidu.com/img/baidu_logo.gif" readonly />
<input type="file" model="native" config='{ "model" : "pics", "range" : [1000, 1200], "thumb" : 50 }' />
<input type="file" model="native" config='{ "model" : "pics", "slice" : [ 200, 150 ], "thumb" : [ 200, 150 ] }' />
<input type="file" model="native" config='{ "model" : "pics", "range" : [1000, 1200], "group" : [ 50, [ 400, 300 ], [800, 600] ] }' />
参考资料:http://www.veryide.com/projects/upload/
高级图片上传
<input type="file" model="magick" storage="" preview="" config="" />
<input type="file" model="magick" storage=".text" preview="#view" config='{ "quality" : "50","output" : "jpg" }' />
<input type="file" model="magick" name="image" config='{ "slice" : [ 200, 150 ], "thumb" : [ 200, 150 ] }' />
参考资料:[http://www.veryide.com/projects/magick/](http://www.veryide.com/projects/magick/)
上传参数
model: 上传模式(native 原生文件上传 / magick 图片压缩算法上传 / editor 编辑器文件上传)
token: 签名参数(可能是加密后的用户信息)
config: 上传配置(可选)
thumb: 可选,创建一个图片缩略图副本;
group: 可选,同时创建多个尺寸图片副本,如:[ 50, [ 400, 300 ], [800, 600] ]
slice: 可选,对原图进行裁切处理;按指定尺寸裁切:[1024, 768];按宽度百分比裁切:80
range: 可选,对原图限制最大尺寸;限制最大的宽度和高度:[1024, 768],超出时将缩放;
文本复制
<input type="text" clipboard />
<input type="text" data-clipboard-tips="复制成功" clipboard />
参考资料:[https://clipboardjs.com/](https://clipboardjs.com/)
URL简化
<input type="text" data-url-simplify />
URL缩短
<input type="text" data-url-tinyurl />
标签嗅探
原生文件上传、图片压缩上传、复制到剪贴板、富文本编辑器,都依赖了标签嗅探,用来判断是否需要加载相关的脚本和资源文件
1. 图片延迟加载 img[raw] 如:<img raw="https://www.baidu.com/img/baidu.gif" />
2. 原生文件上传 input[model=native] 如:<input type="file" model="native" config="" />
3. 图片压缩上传 input[model=magick] 如:<input type="file" model="magick" storage="" preview="" />
4. 富文本编辑器 textarea[editor] 如:<textarea editor="" /> <textarea editor='{ "filterMode": false }' />
5. 复制到剪贴板 [clipboard] 如:<input type="text" data-clipboard-target="#target" clipboard />
参考资料:[http://kindeditor.net/docs/option.html](http://kindeditor.net/docs/option.html)
已知问题
1. 不能使用 <template> 包含 <fragment>,会导致 <fragment> 无法生效
2. <fragment> 中动态创建的 Vue 数据,使用前需要使用 v-if 判断
3. 不同类型的上传都是经过 Hybrid.config.upload,其中 model 参数表示上传方式
4. 表单 Ajax 提交,仅对 method="post" target="ajax" 有效,所有的 Ajax 请求都需返回 xml 数据
5. 优化考虑,当页面不可见时(document.visibilityState == 'hidden'),将暂停数据定时请求