After Width: | Height: | Size: 8.4 KiB |
After Width: | Height: | Size: 24 KiB |
After Width: | Height: | Size: 45 KiB |
After Width: | Height: | Size: 16 KiB |
After Width: | Height: | Size: 55 KiB |
After Width: | Height: | Size: 17 KiB |
After Width: | Height: | Size: 71 KiB |
@ -0,0 +1,63 @@ |
|||||||
|
let selectedValues = ["1", "2"]; |
||||||
|
|
||||||
|
var Model = BI.inherit(Fix.Model, { |
||||||
|
state: function () { |
||||||
|
return { |
||||||
|
selectedValues: ["1", "2"], |
||||||
|
} |
||||||
|
}, |
||||||
|
computed: { |
||||||
|
selectedNodes: function () { |
||||||
|
return this.model.selectedValues; |
||||||
|
} |
||||||
|
}, |
||||||
|
actions: { |
||||||
|
setSelectedValue: function (v) { |
||||||
|
this.model.selectedValues = v; |
||||||
|
} |
||||||
|
} |
||||||
|
}) |
||||||
|
BI.model("demo_chooser_combo", Model); |
||||||
|
|
||||||
|
var model = BI.Models.getModel("demo_chooser_combo"); |
||||||
|
|
||||||
|
BI.createWidget({ |
||||||
|
type: "bi.value_chooser_no_bar_combo", |
||||||
|
ref: (_ref) => { |
||||||
|
this.combo = _ref; |
||||||
|
}, |
||||||
|
value: model.model.selectedValues, |
||||||
|
items: [ |
||||||
|
{ |
||||||
|
text: "11", |
||||||
|
value: "1", |
||||||
|
disabled: () => { |
||||||
|
var isSelected = !!model.model.selectedNodes.find(value => value === "1"); |
||||||
|
return !isSelected && model.model.selectedNodes.length >= 2; |
||||||
|
} |
||||||
|
}, { |
||||||
|
text: "22", |
||||||
|
value: "2", |
||||||
|
disabled: () => { |
||||||
|
var isSelected = !!model.model.selectedNodes.find(value => value === "2"); |
||||||
|
return !isSelected && model.model.selectedNodes.length >= 2; |
||||||
|
} |
||||||
|
}, { |
||||||
|
text: "33", |
||||||
|
value: "3", |
||||||
|
disabled: () => { |
||||||
|
var isSelected = !!model.model.selectedNodes.find(value => value === "3"); |
||||||
|
return !isSelected && model.model.selectedNodes.length >= 2; |
||||||
|
} |
||||||
|
} |
||||||
|
], |
||||||
|
listeners: [ |
||||||
|
{ |
||||||
|
eventName: BI.ValueChooserNoBarCombo.EVENT_CLICK_ITEM, |
||||||
|
action: () => { |
||||||
|
const selectedNodesID = this.combo.getValue(); |
||||||
|
model.setSelectedValue(selectedNodesID); |
||||||
|
}, |
||||||
|
} |
||||||
|
] |
||||||
|
}); |
@ -0,0 +1,148 @@ |
|||||||
|
# 有没有一种布局方式,在文本保持垂直居中的情况下,文本很多时,可以限制其不超出外层高度 并出现滚动条 |
||||||
|
|
||||||
|
## 场景再现 |
||||||
|
|
||||||
|
业务中场景的confirm框,警示图标加文字的结构.要求是图标和文字水平垂直居中,文字过长时优先占满横向空间,横向空间不足时自动换行以及出现滚动条. |
||||||
|
|
||||||
|
![示例1](../images/39.png) |
||||||
|
![示例1](../images/40.png) |
||||||
|
|
||||||
|
首先,文字自动换行,我们需要为label添加`whiteSpace: "normal" |
||||||
|
|
||||||
|
## 旧时代的布局策略 |
||||||
|
|
||||||
|
传统布局下,图标与文字同时水平居中,我们最先想到的就是`bi.center_adapt`,在旧时代的水平垂直居中实现采用的是`display:inline-block`方式,容器设置`text-align:center`同时对每个子元素 |
||||||
|
设置`vertical-align:middle` |
||||||
|
|
||||||
|
```javascript |
||||||
|
{ |
||||||
|
type: "bi.inline_center_adapt", |
||||||
|
items: [ |
||||||
|
{ |
||||||
|
el: { |
||||||
|
type: "bi.icon_label", |
||||||
|
cls: o.iconCls + " icon-size-50", |
||||||
|
width: 50, |
||||||
|
}, |
||||||
|
}, { |
||||||
|
el: { |
||||||
|
type: "bi.label", |
||||||
|
cls: "content-text", |
||||||
|
text: this.options.text, |
||||||
|
whiteSpace: "normal", |
||||||
|
textAlign: "left", |
||||||
|
lgap: 10, |
||||||
|
}, |
||||||
|
}, |
||||||
|
], |
||||||
|
}; |
||||||
|
``` |
||||||
|
|
||||||
|
看起来一切都那么完美,但是当文字超长的时候,文字在垂直平方向上不受束缚的扩张,水平方向也超出了容器 |
||||||
|
|
||||||
|
![示例3](../images/43.png) |
||||||
|
|
||||||
|
有的朋友可能会想到了,那么给文字设置一个`max-wdith`样式,数值为容器宽度减去提示图标宽度.接下来在添加一个`max-height:100%`,这样文本区域的长和宽都被束缚住了 |
||||||
|
姑且不谈这样定宽是否考虑了通用性与自适应场景.看一下效果:文字确实换行了,但是在竖直方向上也可以正常出现滚动条 |
||||||
|
|
||||||
|
## 新时代的flex |
||||||
|
|
||||||
|
FineUI在现代浏览器上对大多数布局组件的实现策略都是基于flex的,那么flex布局处理这种场景是不是更加简便呢? |
||||||
|
|
||||||
|
flex实现水平居中设置`justify-content:center`即可,对应到布局组件的属性为`horizontalAlign:center`(此处指水平方向布局) |
||||||
|
限制文本换行后内容高度不会超过容器,那么需要设定`align-items:stretch`,对应到对应到布局组件的属性为`verticalAlign:center`(此处指水平方向布局) |
||||||
|
|
||||||
|
是不是so easy,理想很丰满,但是现实是文字并没有自动换行,而是超出了容器.因为我们的`justify-content:center`,致使flex总是让子项目居中分布即使是左右都超出了容器 |
||||||
|
|
||||||
|
```javascript |
||||||
|
{ |
||||||
|
type: "bi.flex_center_adapt", |
||||||
|
items: [ |
||||||
|
{ |
||||||
|
el: { |
||||||
|
type: "bi.icon_label", |
||||||
|
cls: o.iconCls + " icon-size-50", |
||||||
|
width: 50, |
||||||
|
}, |
||||||
|
}, { |
||||||
|
el: { |
||||||
|
type: "bi.label", |
||||||
|
cls: "content-text", |
||||||
|
text: this.options.text, |
||||||
|
whiteSpace: "normal", |
||||||
|
textAlign: "left", |
||||||
|
lgap: 10, |
||||||
|
}, |
||||||
|
}, |
||||||
|
], |
||||||
|
}; |
||||||
|
``` |
||||||
|
|
||||||
|
![示例3](../images/44.png) |
||||||
|
|
||||||
|
连老王都不知道flex是个好东西还是个不好的东西,我们就不对flex的好与坏进行评判了.只要探究该如何解决问题 |
||||||
|
|
||||||
|
参考旧时代解决方案,对label文本添加一个`max-wdith`样式,这样便满足了功能需求. |
||||||
|
|
||||||
|
但是,这个方案完美吗?`max-width`的具体值,需要根据容器宽度指定,这样使组件失去了复用性和独立性,倘若哪天popover尺寸规范变了,`max-width`的值也需要随之变更. |
||||||
|
|
||||||
|
既然`max-width`是不固定的,那使用calc可以吗?`max-width:calc(100% - 50px)`.当然可以,这样更精确,但是,`100%`是相对谁的,百分百确定吗? |
||||||
|
|
||||||
|
多数情况下,能够合理利用max-width控制,实现功能效果,就已经超越大多数布局使用者了.精益求精的话,有没有完美的方案呢? |
||||||
|
|
||||||
|
拓展思路,将问题进行拆分,拆分为两个问题解决.首先需要垂直水平居中,然后需要图标宽度固定和文字随内容增加占满剩余空间. |
||||||
|
|
||||||
|
为了实现水平垂直居中,我们需要设置如下props |
||||||
|
```javascript |
||||||
|
verticalAlign: "middle", |
||||||
|
horizontalAlign: "center", |
||||||
|
``` |
||||||
|
映射到flex属性即为 |
||||||
|
```css |
||||||
|
justify-content: center; |
||||||
|
align-items: center; |
||||||
|
``` |
||||||
|
|
||||||
|
图标宽度固定,则其在flex容器内既不拉伸也不收缩,文字随内容增加占满剩余空间,则其在空间剩余时不会拉伸,在空间不足时将自动收缩,那么props为 |
||||||
|
```javascript |
||||||
|
columnSize: [50, ""] |
||||||
|
``` |
||||||
|
映射到flex属性,图标: |
||||||
|
```css |
||||||
|
flex-grow: 0; |
||||||
|
flex-shrink: 0; |
||||||
|
``` |
||||||
|
label文字 |
||||||
|
```css |
||||||
|
flex-grow: 0; |
||||||
|
flex-shrink: 1; |
||||||
|
``` |
||||||
|
|
||||||
|
最终基于FineUI布局组件的的完整实现方式 |
||||||
|
```javascript |
||||||
|
{ |
||||||
|
type: "bi.horizontal", |
||||||
|
verticalAlign: "stretch", |
||||||
|
horizontalAlign: "center", |
||||||
|
scrollx: false, |
||||||
|
columnSize: [50, ""], |
||||||
|
items: [ |
||||||
|
{ |
||||||
|
el: { |
||||||
|
type: "bi.icon_label", |
||||||
|
cls: o.iconCls + " icon-size-50", |
||||||
|
width: 50, |
||||||
|
}, |
||||||
|
}, { |
||||||
|
el: { |
||||||
|
type: "bi.label", |
||||||
|
cls: "content-text", |
||||||
|
text: this.options.text, |
||||||
|
whiteSpace: "normal", |
||||||
|
textAlign: "left", |
||||||
|
lgap: 10, |
||||||
|
}, |
||||||
|
}, |
||||||
|
], |
||||||
|
}; |
||||||
|
``` |