-
Notifications
You must be signed in to change notification settings - Fork 0
Open
Description
先看写法
render (h) {
var me = this
jsx.h = h
var hr = jsx.__('hr')
var rinput = jsx.__('r-input')
var rselect = jsx.__('r-select')
var roption = jsx.__('r-select-option')
var rradio = jsx.__('r-radio')
var rcheckbox = jsx.__('r-checkbox')
var {div,h2,ul,li,input,h3,select,option} = jsx
var node =
div('.box',
h2('.title', {s_color:'red'}, '文章列表'),
ul('.list',
li({o_click:this.liClick}, '乒乓健儿大杀四方...'),
li({
c_foo: true,
c_bar: false,
s_color: 'blue',
s_fontSize: '12px',
a_id: 'foo',
o_click: this.liClick
}, '柯洁又输了....')
),
hr(),
div(
h3('form input text'),
input({a_type:'text', vmodel: [me, 'name']}),
rinput({vmodel: [me, 'name']}),
hr()
),
div(
h3('form input radio'),
input({a_type:'radio', a_value:'boy', vmodel: [me, 'radio']}),
input({a_type:'radio', a_value:'girl', vmodel: [me, 'radio']}),
rradio({a_label:'boy', a_value:'boy', vmodel: [me, 'radio']}),
rradio({a_label:'girl', a_value:'girl', vmodel: [me, 'radio']}),
hr()
),
div(
h3('form input checkbox single'),
input({a_type: 'checkbox', vmodel: [me, 'singleCheckbox']}),
rcheckbox({vmodel: [me, 'singleCheckbox']})
),
div(
h3('form input checkbox multi'),
input({a_type: 'checkbox', a_value: '呵呵', vmodel: [me, 'multiCheckbox']}),
input({a_type: 'checkbox', a_value: '哈哈', vmodel: [me, 'multiCheckbox']}),
rcheckbox({a_value: '呵呵', vmodel: [me, 'multiCheckbox']}),
rcheckbox({a_value: '哈哈', vmodel: [me, 'multiCheckbox']}),
),
div(
h3('form select single'),
select({vmodel: [me, 'singleSelect']},
option({a_value:'a'}, 'one'),
option({a_value:'b'}, 'two'),
option({a_value:'c'}, 'three'),
),
rselect({vmodel: [me, 'singleSelect']},
roption({a_value:'a', a_label:'one'}),
roption({a_value:'b', a_label:'two'}),
roption({a_value:'c', a_label:'three'}),
)
),
div(
h3('form multi single'),
select({a_multiple:true, vmodel: [me, 'multiSelect']},
option({a_value:'a'}, 'one'),
option({a_value:'b'}, 'two'),
option({a_value:'c'}, 'three'),
),
rselect({vmodel: [me, 'multiSelect']},
roption({a_value:'a', a_label:'one'}),
roption({a_value:'b', a_label:'two'}),
roption({a_value:'c', a_label:'three'}),
)
),
)
return node
}vue 提供了两种写组件的方式,template属性和render 方法,template写起来比较直观,但render控制力更强。直接写render的话,createElement不要太繁琐,虽然有jsx,又需要额外的编译,只能想办法简化写法了。具体辅助函数如下:
var jsx = {
h () {},
getProp (context, prop) {
var props = prop.split('.'), i
while (i = props.shift()){
context = context[i]
}
return context
},
setProp (context, prop, value) {
var props = prop.split('.'), i
while (i = props.shift()){
if (!props.length){
break
}
context = context[i]
}
context[i] = value
},
_ (...params) {
var node = {tag: 'div', props: {'class':{},style:{},attrs:{},props:{},domProps:{},on:{},nativeOn:{}}, children: []}
var plen = params.length
if (!plen){
return node
}
if (plen > 1){
var second = params[1]
var i = 1
if ( (typeof second === 'object') && (second.__proto__.constructor.name !== 'VNode') ){
var table = {c:'class', s:'style', a:'attrs', p:'props', dp:'domProps', o:'on', no:'nativeOn'}
for (var k in second){
if (k.includes('_')){
var [a, b] = k.split('_')
var aa = table[a]
node['props'][aa][b] = second[k]
}
else {
node['props'][k] = second[k]
}
}
i = 2
}
node.children.push(...params.slice(i))
}
var first = params[0]
if (first.includes('.')){
var [t, s] = first.split('.')
node['tag'] = t
s.split('+').forEach(i => {
node['props']['class'][i.trim()] = true
})
}
else {
node['tag'] = first
}
//- 处理vmodel
if ('vmodel' in node.props){
var [context, model] = node.props['vmodel']
var tag = node.tag
var props = node.props
var inputType = props['attrs']['type']
var isInput = tag === 'input'
var isText = (isInput && (inputType === 'text')) || (tag === 'textarea')
var isRadio = isInput && (inputType === 'radio')
var isCheckbox = isInput && (inputType === 'checkbox')
var isSelect = tag === 'select'
//- 针对rainbow自定义vmodel的组件
var isRRadio = tag === 'r-radio' || tag === 'r-checkbox'
if (isText){
props['domProps']['value'] = jsx.getProp(context, model)
props['on']['input'] = e => {
jsx.setProp(context, model, e.target.value)
}
}
else if (isRadio){
props['domProps']['checked'] = props['attrs']['value'] === jsx.getProp(context, model) ? true : false
props['on']['change'] = e => {
jsx.setProp(context, model, e.target.value)
}
}
else if (isCheckbox){
//- 如果model是array
if (Array.isArray(jsx.getProp(context, model))){
var value = props['attrs']['value']
var isChecked = props['domProps']['checked'] = jsx.getProp(context, model).includes(value)
props['on']['change'] = e => {
if (isChecked){
jsx.getProp(context, model).splice(jsx.getProp(context, model).indexOf(value), 1)
}
else {
jsx.getProp(context, model).push(value)
}
}
}
else {
props['domProps']['checked'] = jsx.getProp(context, model) === true ? true : false
props['on']['change'] = e => {
jsx.setProp(context, model, !props['domProps']['checked'])
}
}
}
else if (isSelect){
//- 如果model是array
if (Array.isArray(jsx.getProp(context, model))){
//- 好像有点麻烦,需要反推option children
}
else {
props['domProps']['value'] = jsx.getProp(context, model)
props['on']['change'] = e => {
jsx.setProp(context, model, e.target.value)
}
}
}
//- 假设其他都是自定义组件
else {
var modelProp = 'value'
var modelEvent = 'input'
if (isRRadio){
modelProp = 'checkedValue'
}
props['props'][modelProp] = jsx.getProp(context, model)
props['on']['input'] = val => {
jsx.setProp(context, model, val)
}
}
}
return jsx.h(node.tag, node.props, node.children)
},
__ (tag) {
return (...params) => {
if ( (typeof params[0] === 'string') && (params[0][0] === '.') ){
params[0] = tag + params[0]
}
else {
params.unshift(tag)
}
return jsx._(...params)
}
}
}
'a,b,button,dd,div,dl,dt,em,form,i,iframe,img,input,label,li,ol,optgroup,option,p,select,span,table,th,thead,tr,td,ul,h1,h2,h3,h4,h5,h6'.split(',').forEach(tag=>{
jsx[tag] = jsx.__(tag)
})Metadata
Metadata
Assignees
Labels
No labels