Open jingzhiMo opened 5 years ago
之前一段时间就大概把这个轮子弄好了,但是一直没有整理成文章。今天完善一下使用这个轮子的例子,顺便发现之前的几个bug,一同修复。看来后面还是需要把测试用例补充,否则很难避免使用起来遗漏的地方。目前这个工具托管在friendly-query,欢迎大家尝试使用并提issue。
通常路由库可以处理从:/path1 => path2的跳转切换不同的页面;但是对/path1?foo=1切换到/path2?foo=2这种情况支持不是很好。如果页面对应的参数不增加到url中,用户在页面更改部分参数后,刷新页面,用户之前选择的这一部分参数就会被重置而不会选中后的页面处理。 在开发的过程中,想实现页面的部分表单参数同步到url的query参数;
/path1
path2
/path1?foo=1
/path2?foo=2
popstate
总体来说,这个工具就是解决以上两个问题
上面图主要描述了三种情况:
enter page
update data
friendly-query
init
instance.load()
store
instance.convert
通常这一步是用户触发更改不同的参数,前端根据不同的参数请求相应的数据
history
history.pushState()
callback
init([{ type: { foo: {} }, callback () {} }, { type: { bar: {} }, callback () {} }])
若在popstate事件发生的时候,foo参数相比旧url发生了改变,则foo对应分组的callback会调用;bar对应的分组的callback不会被调用;这种情况适用于页面有多个不同请求,并且这些请求都需要更新到url。
foo
bar
从图可以看出,核心方法是load与convert的处理,是字符串数据与复杂数据之间桥梁。
load
convert
instance.load方法的核心是parse的方法,parse不是只有一个,而是对于多种不同的数据类型,从字符串转换为需要类型的转换函数,例如:Int与Array的parse过程是不同的,parse函数主要接收三个参数:
instance.load
parse
Int
Array
{String} str
{Any} value
{Object} option
与parse对应的处理函数stringify,在instance.convert()实现,则是把不同的数据类型转换为字符串,例如把数组:['foo', 'bar']转换为字符串:'foo,bar',该函数主要接收两个参数:
stringify
instance.convert()
['foo', 'bar']
'foo,bar'
{Array|Object} groupQuery
{Boolean} isMerged
默认支持的类型有:
Float
String
Date
Boolean
IntArray
FloatArray
每种类型都有自己的处理规则,例如Array的配置当中,默认分隔符是逗号:separator: ',';在parse的时候,会根据逗号,来分割字符串,在stringify的时候,会根据逗号,来拼接字符串。如果想更改为别的分隔符,例如更改为连接符号-,则可以在init的时候,传入第二个参数,对需要更改的规则进行处理:
separator: ','
,
-
init([ // ... ], { Array: { separator: '-' }, IntArray: { // ... } })
不同数据类型详细的配置,可以看这里
如果上述默认的类型都不能支持项目所用,可以使用extend的全局方法来扩充所需要的类型,下面这个例子是扩充一个DateArray的类型:
extend
DateArray
// dateformat 为一个日期格式类型处理的库 import dateformat from 'dateformat' extend({ DateArray: { // 从字符串转换为 Array 的方法 parse (str, value, option) { if (!str) return value return str.split(option.separator).map(item => { return new Date(item) }) }, // 从 Array 转换为字符串的方法 stringify (value, option) { if (!value.length) return '' return value.map(item => dateformat(item, option.format)).join(option.separator) }, option: { // 分隔符 separator: ',', // 转换的时间格式 format: 'yyyy/mm/dd hh:MM' } } })
需要注意的是,使用extend扩充的类型,会全局影响,因此最好在项目入口定义新的类型
目前暂时只支持HTML5 history的模式,暂还没支持hash的路由模式
HTML5 history
hash
更详细的API可以查看这里
之前一段时间就大概把这个轮子弄好了,但是一直没有整理成文章。今天完善一下使用这个轮子的例子,顺便发现之前的几个bug,一同修复。看来后面还是需要把测试用例补充,否则很难避免使用起来遗漏的地方。目前这个工具托管在friendly-query,欢迎大家尝试使用并提issue。
背景
通常路由库可以处理从:
/path1
=>path2
的跳转切换不同的页面;但是对/path1?foo=1
切换到/path2?foo=2
这种情况支持不是很好。如果页面对应的参数不增加到url中,用户在页面更改部分参数后,刷新页面,用户之前选择的这一部分参数就会被重置而不会选中后的页面处理。 在开发的过程中,想实现页面的部分表单参数同步到url的query参数;popstate
的事件,然后根据回调事件来监听参数发生变化,根据更改后的url参数,再进行处理;参数发生改变可能只影响一部分,通常只需要触发该部分的回调就可以了;总体来说,这个工具就是解决以上两个问题
应用过程
上面图主要描述了三种情况:
enter page
update data
popstate
初始化进入页面
friendly-query
的init
方法生成实例instance.load()
方法,该方法会从url上获取所有参数,并根据初始化传入的转换的数据类型,进行处理;返回的数据则为我们定义的数据类型store
instance.convert
方法,把原有复杂的数据类型转换为字符串类型,把参数发送到后端页面数据发生改变
通常这一步是用户触发更改不同的参数,前端根据不同的参数请求相应的数据
instance.convert
方法,获取新的数据转换后的字符串参数history
添加记录;添加记录这一步可能部分路由已支持;若不支持,则需要手动调用:history.pushState()
添加记录用户点击浏览器前进/后退按钮
popstate
事件(监听事件这一步,在init
的时候进行了绑定)callback
函数;这个callback
函数为初始化init
传入的参数;若对参数进行分多组处理,则改变的参数对应的分组回调才被调用,例如:若在
popstate
事件发生的时候,foo
参数相比旧url发生了改变,则foo
对应分组的callback
会调用;bar
对应的分组的callback
不会被调用;这种情况适用于页面有多个不同请求,并且这些请求都需要更新到url。处理过程
从图可以看出,核心方法是
load
与convert
的处理,是字符串数据与复杂数据之间桥梁。instance.load
方法的核心是parse
的方法,parse
不是只有一个,而是对于多种不同的数据类型,从字符串转换为需要类型的转换函数,例如:Int
与Array
的parse
过程是不同的,parse
函数主要接收三个参数:{String} str
url 对应参数的数据{Any} value
初始化传入该参数的默认数据{Object} option
该参数对应的数据类型的配置与
parse
对应的处理函数stringify
,在instance.convert()
实现,则是把不同的数据类型转换为字符串,例如把数组:['foo', 'bar']
转换为字符串:'foo,bar'
,该函数主要接收两个参数:{Array|Object} groupQuery
需要从设定的数据类型转换为url参数所用的字符串类型{Boolean} isMerged
对转换后的数组字符串数据合并到一个对象中,默认合并更改类型配置
默认支持的类型有:
Int
Float
String
Date
Boolean
Array
IntArray
FloatArray
每种类型都有自己的处理规则,例如
Array
的配置当中,默认分隔符是逗号:separator: ','
;在parse
的时候,会根据逗号,
来分割字符串,在stringify
的时候,会根据逗号,
来拼接字符串。如果想更改为别的分隔符,例如更改为连接符号-
,则可以在init
的时候,传入第二个参数,对需要更改的规则进行处理:不同数据类型详细的配置,可以看这里
扩充类型
如果上述默认的类型都不能支持项目所用,可以使用
extend
的全局方法来扩充所需要的类型,下面这个例子是扩充一个DateArray
的类型:需要注意的是,使用
extend
扩充的类型,会全局影响,因此最好在项目入口定义新的类型目前暂时只支持
HTML5 history
的模式,暂还没支持hash
的路由模式更详细的API可以查看这里