This repository has been archived on 2023-08-30. You can view files and clone it, but cannot push or open issues/pull-requests.
bytedo
/
wcui
Archived
1
0
Fork 0

优化组件机制;data指令支持过滤器;完成单选,开关,按钮表单组件

old
宇天 2018-06-14 14:52:52 +08:00
parent 8ed9ecd462
commit d769c8d31d
6 changed files with 398 additions and 59 deletions

View File

@ -1745,10 +1745,14 @@ const _Anot = (function() {
v.$fire && v.$fire.apply(v, [ee, a])
}
// component! 这是一个特殊的标识,可以直接修改子组件的state值
// 且只针对指定子组件有效
} else if (path.indexOf('component!') === 0) {
var ee = path.slice(10)
var ee = path.slice(10).split('!')
for (var i in $vmodel.$children) {
$vmodel.$children[i][ee] = a
if ($vmodel.$children[i].$id === ee[0]) {
$vmodel.$children[i][ee[1]] = a
break
}
}
} else {
$emit.call($vmodel, path, [a])
@ -1772,7 +1776,14 @@ const _Anot = (function() {
if (watches) {
delete watches.props
for (var key in watches) {
$watch.call($vmodel, key, watches[key])
if (Array.isArray(watches[key])) {
var tmp
while ((tmp = watches[key].pop())) {
$watch.call($vmodel, key, tmp)
}
} else {
$watch.call($vmodel, key, watches[key])
}
}
}
@ -3346,7 +3357,8 @@ const _Anot = (function() {
var rnoCollect = /^(:\S+|data-\S+|on[a-z]+|id|style|class)$/
var ronattr = '__fn__'
var specifiedVars = [':disabled', ':loading']
var specifiedVars = [':disabled', ':loading', ':value']
var filterTypes = ['html', 'text', 'attr', 'data']
function getOptionsFromTag(elem, vmodels) {
var attributes = aslice.call(elem.attributes, 0)
var ret = {}
@ -3420,7 +3432,7 @@ const _Anot = (function() {
(directives[type].priority || type.charCodeAt(0) * 10) +
(Number(param.replace(/\D/g, '')) || 0)
}
if (type === 'html' || type === 'text' || type === 'attr') {
if (filterTypes.includes(type)) {
var filters = getToken(value).filters
binding.expr = binding.expr.replace(filters, '')
binding.filters = filters
@ -3784,6 +3796,7 @@ const _Anot = (function() {
//如果还没有解析完,就延迟一下 #1155
return
}
hooks.watch = hooks.watch || {}
var parentVm = host.vmodels[0]
var state = {}
var props = getOptionsFromTag(elem, host.vmodels)
@ -3800,19 +3813,34 @@ const _Anot = (function() {
var disabledKey = props[':disabled']
state.disabled = parentVm[disabledKey]
parentVm.$watch(disabledKey, function(val) {
parentVm.$fire('component!disabled', val)
parentVm.$fire('component!' + $id + '!disabled', val)
})
delete props[':disabled']
}
if (props.hasOwnProperty(':loading')) {
var loadingKey = props[':loading']
state.loading = parentVm[loadingKey]
parentVm.$watch(loadingKey, function(val) {
parentVm.$fire('component!loading', val)
parentVm.$fire('component!' + $id + '!loading', val)
})
delete props[':loading']
}
// :value可实现双向同步值
if (props.hasOwnProperty(':value')) {
var valueKey = props[':value']
state.value = parentVm[valueKey]
parentVm.$watch(valueKey, function(val) {
parentVm.$fire('component!' + $id + '!value', val)
})
hooks.watch.value = hooks.watch.value ? [hooks.watch.value] : []
hooks.watch.value.push(function(val) {
parentVm[valueKey] = val
})
delete props[':value']
}
delete props.uuid
delete props.name
@ -4143,11 +4171,6 @@ const _Anot = (function() {
}
})
//这几个指令都可以使用插值表达式,如:src="aaa/{{b}}/{{c}}.html"
'css,include,data'.replace(rword, function(name) {
directives[name] = attrDir
})
//类名定义, :class="xx:yy" :class="{xx: yy}" :class="xx" :class="{{xx}}"
Anot.directive('class', {
init: function(binding) {
@ -4262,6 +4285,7 @@ const _Anot = (function() {
//兼容2种写法 :data-xx="yy", :data="{xx: yy}"
Anot.directive('data', {
priority: 100,
init: directives.attr.init,
update: function(val) {
var obj = val
if (typeof obj === 'object' && obj !== null) {

View File

@ -1760,10 +1760,14 @@
v.$fire && v.$fire.apply(v, [ee, a])
}
// component! 这是一个特殊的标识,可以直接修改子组件的state值
// 且只针对指定子组件有效
} else if (path.indexOf('component!') === 0) {
var ee = path.slice(10)
var ee = path.slice(10).split('!')
for (var i in $vmodel.$children) {
$vmodel.$children[i][ee] = a
if ($vmodel.$children[i].$id === ee[0]) {
$vmodel.$children[i][ee[1]] = a
break
}
}
} else {
$emit.call($vmodel, path, [a])
@ -1787,7 +1791,14 @@
if (watches) {
delete watches.props
for (var key in watches) {
$watch.call($vmodel, key, watches[key])
if (Array.isArray(watches[key])) {
var tmp
while ((tmp = watches[key].pop())) {
$watch.call($vmodel, key, tmp)
}
} else {
$watch.call($vmodel, key, watches[key])
}
}
}
@ -3361,7 +3372,8 @@
var rnoCollect = /^(:\S+|data-\S+|on[a-z]+|id|style|class)$/
var ronattr = '__fn__'
var specifiedVars = [':disabled', ':loading']
var specifiedVars = [':disabled', ':loading', ':value']
var filterTypes = ['html', 'text', 'attr', 'data']
function getOptionsFromTag(elem, vmodels) {
var attributes = aslice.call(elem.attributes, 0)
var ret = {}
@ -3435,7 +3447,7 @@
(directives[type].priority || type.charCodeAt(0) * 10) +
(Number(param.replace(/\D/g, '')) || 0)
}
if (type === 'html' || type === 'text' || type === 'attr') {
if (filterTypes.includes(type)) {
var filters = getToken(value).filters
binding.expr = binding.expr.replace(filters, '')
binding.filters = filters
@ -3799,6 +3811,7 @@
//如果还没有解析完,就延迟一下 #1155
return
}
hooks.watch = hooks.watch || {}
var parentVm = host.vmodels[0]
var state = {}
var props = getOptionsFromTag(elem, host.vmodels)
@ -3815,19 +3828,34 @@
var disabledKey = props[':disabled']
state.disabled = parentVm[disabledKey]
parentVm.$watch(disabledKey, function(val) {
parentVm.$fire('component!disabled', val)
parentVm.$fire('component!' + $id + '!disabled', val)
})
delete props[':disabled']
}
if (props.hasOwnProperty(':loading')) {
var loadingKey = props[':loading']
state.loading = parentVm[loadingKey]
parentVm.$watch(loadingKey, function(val) {
parentVm.$fire('component!loading', val)
parentVm.$fire('component!' + $id + '!loading', val)
})
delete props[':loading']
}
// :value可实现双向同步值
if (props.hasOwnProperty(':value')) {
var valueKey = props[':value']
state.value = parentVm[valueKey]
parentVm.$watch(valueKey, function(val) {
parentVm.$fire('component!' + $id + '!value', val)
})
hooks.watch.value = hooks.watch.value ? [hooks.watch.value] : []
hooks.watch.value.push(function(val) {
parentVm[valueKey] = val
})
delete props[':value']
}
delete props.uuid
delete props.name
@ -4158,11 +4186,6 @@
}
})
//这几个指令都可以使用插值表达式,如:src="aaa/{{b}}/{{c}}.html"
'css,include,data'.replace(rword, function(name) {
directives[name] = attrDir
})
//类名定义, :class="xx:yy" :class="{xx: yy}" :class="xx" :class="{{xx}}"
Anot.directive('class', {
init: function(binding) {
@ -4277,6 +4300,7 @@
//兼容2种写法 :data-xx="yy", :data="{xx: yy}"
Anot.directive('data', {
priority: 100,
init: directives.attr.init,
update: function(val) {
var obj = val
if (typeof obj === 'object' && obj !== null) {

View File

@ -1745,10 +1745,14 @@ const _Anot = (function() {
v.$fire && v.$fire.apply(v, [ee, a])
}
// component! 这是一个特殊的标识,可以直接修改子组件的state值
// 且只针对指定子组件有效
} else if (path.indexOf('component!') === 0) {
var ee = path.slice(10)
var ee = path.slice(10).split('!')
for (var i in $vmodel.$children) {
$vmodel.$children[i][ee] = a
if ($vmodel.$children[i].$id === ee[0]) {
$vmodel.$children[i][ee[1]] = a
break
}
}
} else {
$emit.call($vmodel, path, [a])
@ -1772,7 +1776,14 @@ const _Anot = (function() {
if (watches) {
delete watches.props
for (var key in watches) {
$watch.call($vmodel, key, watches[key])
if (Array.isArray(watches[key])) {
var tmp
while ((tmp = watches[key].pop())) {
$watch.call($vmodel, key, tmp)
}
} else {
$watch.call($vmodel, key, watches[key])
}
}
}
@ -3346,7 +3357,8 @@ const _Anot = (function() {
var rnoCollect = /^(:\S+|data-\S+|on[a-z]+|id|style|class)$/
var ronattr = '__fn__'
var specifiedVars = [':disabled', ':loading']
var specifiedVars = [':disabled', ':loading', ':value']
var filterTypes = ['html', 'text', 'attr', 'data']
function getOptionsFromTag(elem, vmodels) {
var attributes = aslice.call(elem.attributes, 0)
var ret = {}
@ -3420,7 +3432,7 @@ const _Anot = (function() {
(directives[type].priority || type.charCodeAt(0) * 10) +
(Number(param.replace(/\D/g, '')) || 0)
}
if (type === 'html' || type === 'text' || type === 'attr') {
if (filterTypes.includes(type)) {
var filters = getToken(value).filters
binding.expr = binding.expr.replace(filters, '')
binding.filters = filters
@ -3784,6 +3796,7 @@ const _Anot = (function() {
//如果还没有解析完,就延迟一下 #1155
return
}
hooks.watch = hooks.watch || {}
var parentVm = host.vmodels[0]
var state = {}
var props = getOptionsFromTag(elem, host.vmodels)
@ -3800,19 +3813,34 @@ const _Anot = (function() {
var disabledKey = props[':disabled']
state.disabled = parentVm[disabledKey]
parentVm.$watch(disabledKey, function(val) {
parentVm.$fire('component!disabled', val)
parentVm.$fire('component!' + $id + '!disabled', val)
})
delete props[':disabled']
}
if (props.hasOwnProperty(':loading')) {
var loadingKey = props[':loading']
state.loading = parentVm[loadingKey]
parentVm.$watch(loadingKey, function(val) {
parentVm.$fire('component!loading', val)
parentVm.$fire('component!' + $id + '!loading', val)
})
delete props[':loading']
}
// :value可实现双向同步值
if (props.hasOwnProperty(':value')) {
var valueKey = props[':value']
state.value = parentVm[valueKey]
parentVm.$watch(valueKey, function(val) {
parentVm.$fire('component!' + $id + '!value', val)
})
hooks.watch.value = hooks.watch.value ? [hooks.watch.value] : []
hooks.watch.value.push(function(val) {
parentVm[valueKey] = val
})
delete props[':value']
}
delete props.uuid
delete props.name
@ -4143,11 +4171,6 @@ const _Anot = (function() {
}
})
//这几个指令都可以使用插值表达式,如:src="aaa/{{b}}/{{c}}.html"
'css,include,data'.replace(rword, function(name) {
directives[name] = attrDir
})
//类名定义, :class="xx:yy" :class="{xx: yy}" :class="xx" :class="{{xx}}"
Anot.directive('class', {
init: function(binding) {
@ -4262,6 +4285,7 @@ const _Anot = (function() {
//兼容2种写法 :data-xx="yy", :data="{xx: yy}"
Anot.directive('data', {
priority: 100,
init: directives.attr.init,
update: function(val) {
var obj = val
if (typeof obj === 'object' && obj !== null) {

View File

@ -1760,10 +1760,14 @@
v.$fire && v.$fire.apply(v, [ee, a])
}
// component! 这是一个特殊的标识,可以直接修改子组件的state值
// 且只针对指定子组件有效
} else if (path.indexOf('component!') === 0) {
var ee = path.slice(10)
var ee = path.slice(10).split('!')
for (var i in $vmodel.$children) {
$vmodel.$children[i][ee] = a
if ($vmodel.$children[i].$id === ee[0]) {
$vmodel.$children[i][ee[1]] = a
break
}
}
} else {
$emit.call($vmodel, path, [a])
@ -1787,7 +1791,14 @@
if (watches) {
delete watches.props
for (var key in watches) {
$watch.call($vmodel, key, watches[key])
if (Array.isArray(watches[key])) {
var tmp
while ((tmp = watches[key].pop())) {
$watch.call($vmodel, key, tmp)
}
} else {
$watch.call($vmodel, key, watches[key])
}
}
}
@ -3361,7 +3372,8 @@
var rnoCollect = /^(:\S+|data-\S+|on[a-z]+|id|style|class)$/
var ronattr = '__fn__'
var specifiedVars = [':disabled', ':loading']
var specifiedVars = [':disabled', ':loading', ':value']
var filterTypes = ['html', 'text', 'attr', 'data']
function getOptionsFromTag(elem, vmodels) {
var attributes = aslice.call(elem.attributes, 0)
var ret = {}
@ -3435,7 +3447,7 @@
(directives[type].priority || type.charCodeAt(0) * 10) +
(Number(param.replace(/\D/g, '')) || 0)
}
if (type === 'html' || type === 'text' || type === 'attr') {
if (filterTypes.includes(type)) {
var filters = getToken(value).filters
binding.expr = binding.expr.replace(filters, '')
binding.filters = filters
@ -3799,6 +3811,7 @@
//如果还没有解析完,就延迟一下 #1155
return
}
hooks.watch = hooks.watch || {}
var parentVm = host.vmodels[0]
var state = {}
var props = getOptionsFromTag(elem, host.vmodels)
@ -3815,19 +3828,34 @@
var disabledKey = props[':disabled']
state.disabled = parentVm[disabledKey]
parentVm.$watch(disabledKey, function(val) {
parentVm.$fire('component!disabled', val)
parentVm.$fire('component!' + $id + '!disabled', val)
})
delete props[':disabled']
}
if (props.hasOwnProperty(':loading')) {
var loadingKey = props[':loading']
state.loading = parentVm[loadingKey]
parentVm.$watch(loadingKey, function(val) {
parentVm.$fire('component!loading', val)
parentVm.$fire('component!' + $id + '!loading', val)
})
delete props[':loading']
}
// :value可实现双向同步值
if (props.hasOwnProperty(':value')) {
var valueKey = props[':value']
state.value = parentVm[valueKey]
parentVm.$watch(valueKey, function(val) {
parentVm.$fire('component!' + $id + '!value', val)
})
hooks.watch.value = hooks.watch.value ? [hooks.watch.value] : []
hooks.watch.value.push(function(val) {
parentVm[valueKey] = val
})
delete props[':value']
}
delete props.uuid
delete props.name
@ -4158,11 +4186,6 @@
}
})
//这几个指令都可以使用插值表达式,如:src="aaa/{{b}}/{{c}}.html"
'css,include,data'.replace(rword, function(name) {
directives[name] = attrDir
})
//类名定义, :class="xx:yy" :class="{xx: yy}" :class="xx" :class="{{xx}}"
Anot.directive('class', {
init: function(binding) {
@ -4277,6 +4300,7 @@
//兼容2种写法 :data-xx="yy", :data="{xx: yy}"
Anot.directive('data', {
priority: 100,
init: directives.attr.init,
update: function(val) {
var obj = val
if (typeof obj === 'object' && obj !== null) {

View File

@ -8,14 +8,28 @@
import './style.scss'
const log = console.log
export default Anot.component('button', {
Anot.ui.form = '0.1.0'
// 按钮
Anot.component('button', {
construct(props, state) {
log(props)
state.text = this.textContent
state.style = { 'border-radius': props.radius }
this.classList.add('do-fn-noselect')
this.classList.add('do-button')
this.setAttribute(':click', 'onClick')
this.setAttribute(':class', '{disabled: disabled}')
this.setAttribute(':css', 'style')
this.classList.add(props.color || 'grey')
if (props.size) {
this.classList.add(props.size)
}
if (props.hasOwnProperty('disabled')) {
state.disabled = true
}
delete props.disabled
delete props.color
delete props.size
},
render() {
let icon = ''
@ -25,26 +39,113 @@ export default Anot.component('button', {
return `${icon}<span class="do-button__text" :text="text"></span>`
},
state: {
state: '',
text: '',
disabled: false,
foo: true,
style: {}
},
props: {
click: Anot.PropsTypes.isFunction()
},
skip: ['style'],
componentDidMount() {
Anot(this.$elem).css(this.style)
},
watch: {},
methods: {
onClick() {
// log(this)
if (this.disabled) {
return
}
log('hello world, button')
if (typeof this.props.click === 'function') {
this.props.click()
}
}
}
})
// 单选按钮
Anot.component('radio', {
construct(props, state) {
state.text = this.textContent
state.checked = state.value === props.label
if (props.hasOwnProperty('disabled')) {
state.disabled = true
}
this.classList.add('do-radio')
this.classList.add('do-fn-noselect')
if (!state.disabled) {
this.classList.add(props.color || 'grey')
}
this.setAttribute(':class', '{disabled: disabled, checked: checked}')
this.setAttribute(':click', 'onClick')
delete props.disabled
delete props.color
},
render() {
return `
<span class="do-radio__box"></span>
<span class="do-radio__text" :text="text"></span>
`
},
state: {
value: null,
text: '',
checked: false,
disabled: false
},
watch: {
value(val) {
this.checked = this.props.label === val
}
},
methods: {
onClick() {
if (this.disabled) {
return
}
if (!this.checked) {
this.checked = true
this.value = this.props.label
}
}
}
})
// 开关
Anot.component('switch', {
construct(props, state) {
if (props.hasOwnProperty('disabled')) {
state.disabled = true
}
this.classList.add('do-switch')
this.classList.add('do-fn-noselect')
if (!state.disabled) {
this.classList.add(props.color || 'grey')
}
this.setAttribute(':class', '{disabled: disabled, checked: value}')
this.setAttribute(':click', 'onClick')
delete props.disabled
delete props.color
},
render() {
return `
<span class="do-switch__label"><i class="do-switch__dot"></i></span>
`
},
state: {
value: false,
disabled: false
},
methods: {
onClick() {
if (this.disabled) {
return
}
this.value = !this.value
}
}
})
export default Anot

View File

@ -9,14 +9,156 @@
@import "var.scss";
.do-button {overflow:hidden;position:relative;display:inline-block;width:auto;min-width:60px;height:30px;margin-left:5px;padding:0 10px;color:nth($ct, 1);text-align:center;cursor:pointer;
.do-button {overflow:hidden;position:relative;display:inline-block;width:auto;height:30px;padding:0 10px;line-height:30px;text-align:center;cursor:pointer;font-size:14px;
&::before {position:absolute;left:-50%;top:-50%;display:block;width:200%;height:200%;border-radius:50%;background:nth($cp, 2); content:"";opacity:0;transform: scale(0, .0); transition:opacity 1.3s cubic-bezier(0.23, 1, 0.32, 1),transform 1.3s cubic-bezier(0.23, 1, 0.32, 1);}
&:hover {
&::before {opacity:1;transform:scale(1, .8);}
}
&:active {background:nth($cp, 1)}
&:active {
&::before {background:rgba(0,0,0,.1);}
}
&__text,&__icon {position:relative;display:inline-block;}
&__icon {font-size:20px;vertical-align:top;}
&.small {height:20px;padding:0 5px;line-height:20px;font-size:12px;
i {font-size:16px;}
}
&.medium {min-width:100px;height:35px;line-height:35px;font-size:16px;
i {padding-right:5px;font-size:24px;}
}
&.large {min-width:150px;height:50px;padding:0 13px;line-height:50px;font-size:18px;
i {padding-right:10px;font-size:28px;}
}
&.teal {color:nth($ct, 1);}
&.green {color:nth($cg, 1);}
&.blue {color:nth($cb, 1);}
&.purple {color:nth($cpp, 1);}
&.red {color:nth($cr, 1);}
&.orange {color:nth($co, 1);}
&.plain {color:nth($cp, 3);}
&.grey {color:nth($cgr, 1);}
&.disabled {color:nth($cp, 1);cursor:not-allowed;
&::before {display:none;}
}
}
.do-radio {position:relative;display:inline-block;width:auto;height:30px;padding:0 10px;line-height:30px;text-align:center;cursor:default;font-size:14px;
&.disabled {cursor:not-allowed;}
&__box {float:left;width:20px;height:20px;margin:5px;border:1px solid nth($cgr, 1);border-radius:50%;
}
&.checked &__box::after {display:block;width:14px;height:14px;margin:2px;border-radius:50%;content:""}
&__text {color:nth($cgr, 1);}
&.teal &__box {border-color:nth($ct, 1);
&::after {background:nth($ct, 1);}
}
&.teal &__text {color:nth($ct, 1);}
&.green &__box {border-color:nth($cg, 1);
&::after {background:nth($cg, 1);}
}
&.green &__text {color:nth($cg, 1);}
&.blue &__box {border-color:nth($cb, 1);
&::after {background:nth($cb, 1);}
}
&.blue &__text {color:nth($cb, 1);}
&.purple &__box {border-color:nth($cpp, 1);
&::after {background:nth($cpp, 1);}
}
&.purple &__text {color:nth($cpp, 1);}
&.red &__box {border-color:nth($cr, 1);
&::after {background:nth($cr, 1);}
}
&.red &__text {color:nth($cr, 1);}
&.orange &__box {border-color:nth($co, 1);
&::after {background:nth($co, 1);}
}
&.orange &__text {color:nth($co, 1);}
&.plain &__box {border-color:nth($cp, 3);
&::after {background:nth($cp, 3);}
}
&.plain &__text {color:nth($cp, 3);}
&.grey &__box {border-color:nth($cgr, 1);
&::after {background:nth($cgr, 1);}
}
&.grey &__text {color:nth($cgr, 1);}
&.disabled &__box {border-color:nth($cp, 1);
&::after {background:nth($cp, 1);}
}
&.disabled &__text {color:nth($cp, 1);}
&.disabled.checked &__text {color:nth($cgr, 1);}
}
.do-switch {position:relative;display:inline-block;width:40px;height:30px;cursor:default;
&__label {position:relative;display:inline-block;width:100%;height:16px;margin:7px 0;background:nth($cp, 3);border-radius:12px;}
&__dot {position:absolute;left:0;top:-2px;width:20px;height:20px;border-radius:50%;background:#fff;box-shadow:0 1px 3px rgba(0,0,0,.3);}
&:hover &__dot {transform:scale(1.1);}
&.disabled {cursor:not-allowed;}
&.disabled:hover &__dot {transform:scale(1);}
&.checked &__dot {left:auto;right:0;}
&.teal.checked &__dot {background:nth($ct, 1);}
&.teal.checked &__label {background:nth($ct, 2) + a0;}
&.green.checked &__dot {background:nth($cg, 1);}
&.green.checked &__label {background:nth($cg, 2) + a0;}
&.blue.checked &__dot {background:nth($cb, 1);}
&.blue.checked &__label {background:nth($cb, 2) + a0;}
&.purple.checked &__dot {background:nth($cpp, 1);}
&.purple.checked &__label {background:nth($cpp, 2) + a0;}
&.red.checked &__dot {background:nth($cr, 1);}
&.red.checked &__label {background:nth($cr, 2) + a0;}
&.orange.checked &__dot {background:nth($co, 1);}
&.orange.checked &__label {background:nth($co, 2) + a0;}
&.plain.checked &__dot {background:nth($cp, 3);}
&.plain.checked &__label {background:nth($cp, 2);}
&.grey.checked &__dot {background:nth($cgr, 1);}
&.grey.checked &__label {background:nth($cgr, 2) + a0;}
&.disabled.checked &__dot {background:#fff;}
&.disabled &__label, &.disabled.checked &__label {background:nth($cp, 2);
&::before {display:block;position:absolute;top:6px;width:8px;height:4px;border-radius:2px;background:#fff;content:"";}
}
&.disabled &__label::before {right:7px;}
&.disabled.checked &__label::before {left:7px;}
}