Browse Source

update

master
zsmj 2 years ago
parent
commit
51f25e41c3
  1. 17
      README.md
  2. BIN
      images/8.png
  3. BIN
      images/9.png
  4. 174
      questions/2.组件的代码设计基本思路.md
  5. 1
      questions/30.Fix中对于对象属性的监听,为什么要先定义属性才可以.md
  6. 31
      questions/41.绝对布局的隐藏知识点.md
  7. 55
      questions/55.Fix中对于对象属性的监听,为什么要先定义属性才可以正常watch,如何解决.md
  8. 0
      questions/81.combo的一些特性.md

17
README.md

@ -4,11 +4,15 @@ FineUI入门100题,带你走进FineUI的世界
此系列内容来源于日常开发积累与沉淀,用于大家学习交流与项目中踩坑
## 题目
## 100-Questions列表
### 项目基础
---
### 基础
- [0、前端工作进阶需要哪些必备技能](./questions/0.前端工作进阶需要哪些必备技能.md)
- [1、前端如何正确书写资源路径](./questions/50.前端如何正确书写资源路径.md)
- [2、组件的代码设计基本思路](./questions/2.组件的代码设计基本思路.md)
### 布局篇
@ -16,8 +20,15 @@ FineUI入门100题,带你走进FineUI的世界
- [3、我们为什么要设计el这个属性](./questions/40.我们为什么要设计el这个属性.md)
- [4、绝对布局的隐藏知识点](./questions/41.绝对布局的隐藏知识点.md)
### Fix数据流篇
- [4、Fix中对于对象属性的监听,为什么要先定义属性才可以正常watch,如何解决](./questions/55.Fix中对于对象属性的监听,为什么要先定义属性才可以正常watch,如何解决.md)
### 进阶
- [1、如何获取当前时间](./questions/1.如何获取当前时间.md)
- [2、如何格式化输出日期](./questions/2.如何格式化输出日期.md)
- [3、为什么传递时间信息时候推荐使用时间戳](./questions/3.为什么传递时间信息时候推荐使用时间戳.md)
- [3、为什么传递时间信息时候推荐使用时间戳](./questions/3.为什么传递时间信息时候推荐使用时间戳.md)
- [4、BI.config都可以做那些事情](./questions/9.BI.config都可以做那些事情.md)
- [5、BI.config的执行顺序是什么,为什么这么设计](./questions/10.BI.config的执行顺序是什么,为什么这么设计.md)
- [6、combo的一些特性详解](./questions/80.combo的一些特性详解.md)

BIN
images/8.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

BIN
images/9.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

174
questions/2.组件的代码设计基本思路.md

@ -0,0 +1,174 @@
# 组件的代码设计基本思路
我们以一个分页组件为例,阐述一下FineUI中组件代码的基本思路
## 控件功能
上一页,下一页,带个输入框,有总页数.四个按钮带disabled逻辑,无上一页或者下一页时候灰化
![示例](../images/9.png)
## 第一步: 明确对外提供的props
总页数,当前页数 就这两个属性够了
```javascript
const props = {
total: 200,
page: 10,
}
```
## 第二步: 明确要对外提供哪些方法
一个getValue方法加一个populate就行了
```javascript
// 获取当前页码
const page = this.page.getValue()
// 设置总页数和页码
this.pager.attr("total", 100)
this.pager.attr("page", 1)
this.pager.populate()
```
## 第三步: 明确对外提供哪些事件
事件只需要一个就够了,通知外部使用者当前page,养成良好习惯,事件尽量带上参数
```javascript
this.fireEvent("EVENT_CHANGE", page)
```
## 生命周期
万物皆render,能render一遍就执行好的,尽量别用其他生命周期,mounted之类的,避免没必要的回流重绘 如果组件是异步的, beforeInit/beforeRender.那么你在render中一定可以拿到所有的状态了,就没必要再通过一次watch来实现效果.当然,有些事情必须在mounted中做(例如获取组件宽高)那就另说了.
## 抛砖引玉
比如这个pager组件按钮的灰化,我就借用最新的响应式写个例子 [自动相应变更](http://fanruan.design/doc.html?post=afe4c84120)
```demo
const Pager = BI.inherit(BI.Widget, {
props: {
total: 1,
page: 1,
},
init: function () {
this.state = Fix.define({
currentPage: this.options.page,
total: this.options.total,
});
},
render: function () {
return {
type: "bi.vertical_adapt",
columnSize: [24, 24, "fill", "", 24, 24],
hgap: 5,
items: [
{
type: "bi.icon_button",
cls: "pre-page-h-font",
disabled: () => {
return this.state.currentPage === 1;
},
handler: () => {
this.state.currentPage = 1;
this.fireEvent("EVENT_CHANGE", this.getValue());
},
}, {
type: "bi.icon_button",
cls: "pre-page-h-font",
disabled: () => {
return this.state.currentPage === 1;
},
handler: () => {
this.state.currentPage--;
this.fireEvent("EVENT_CHANGE", this.getValue());
},
}, {
type: "bi.text_editor",
ref: ref => this.editor = ref,
value: () => this.state.currentPage,
validationChecker: (v) => (BI.parseInt(v) >= 1) && (BI.parseInt(v) <= this.state.total),
errorText: "error",
listeners: [
{
eventName: "EVENT_CHANGE",
action: () => {
this.state.currentPage = BI.parseInt(this.editor.getValue());
this.fireEvent("EVENT_CHANGE", this.getValue());
},
},
],
}, {
type: "bi.label",
text: () => "/" + this.state.total,
}, {
type: "bi.icon_button",
cls: "next-page-h-font",
disabled: () => {
return this.state.currentPage === this.state.total;
},
handler: () => {
this.state.currentPage++;
this.fireEvent("EVENT_CHANGE", this.getValue());
},
}, {
type: "bi.icon_button",
cls: "next-page-h-font",
disabled: () => {
return this.state.currentPage === this.state.total;
},
handler: () => {
this.state.currentPage = this.state.total;
this.fireEvent("EVENT_CHANGE", this.getValue());
},
},
],
};
},
getValue: function () {
return this.state.currentPage;
},
populate: function () {
this.state.currentPage = this.options.page;
this.state.total = this.options.total;
},
});
BI.shortcut("pager", Pager);
let pager;
BI.createWidget({
type: "bi.vertical",
vgap: 20,
items: [
{
type: "pager",
ref: ref => pager = ref,
height: 24,
width: 250,
total: 100,
page: 2,
}, {
type: "bi.button",
text: "populate",
handler: () => {
pager.attr("total", 500);
pager.attr("page", 400);
pager.populate();
},
},
],
});
```

1
questions/30.Fix中对于对象属性的监听,为什么要先定义属性才可以.md

@ -1 +0,0 @@
# Fix中对于对象属性的监听,为什么要先定义属性才可以

31
questions/41.绝对布局的隐藏知识点.md

@ -105,9 +105,36 @@ BI.createWidget({
![示例](../images/7.png)
4. 绝对布局支持shorthand写法inset
4. 位置属性使用负值会有起效
使用Chrome审查元素的同学可能发现了,绝对布局的元素在chrome中会显示`inset: 0`这种形式,实际上这是top right bottom left属性的简写,规则遵循顺时针方向.需要注意的是只有第一种情况支持属性名为数字,其余情况需要加引号,毕竟我们是写js而不是css
在开发过程中会遇到有些按钮图标为了位置美观,会脱离正常位置的情况,此时利用负值属性可以很轻松实现
```demo
BI.createWidget({
type: "bi.absolute",
width: 300,
height: 300,
css: {
background: "red",
},
items: [
{
el: {
type: "bi.button",
text: "保存",
},
top: -30,
right: 10,
},
],
});
```
![示例](../images/8.png)
5. 绝对布局支持shorthand写法inset
使用Chrome审查元素的同学可能发现了,绝对布局的元素在chrome中会显示`inset: 0`这种形式,实际上这是top right bottom left属性的简写,规则遵循顺时针方向.FineUI同样支持了这种写法,需要注意的是只有第一种情况支持属性名为数字,其余情况需要加引号,毕竟我们是写js而不是css
```
inset: 10 /* value applied to all edges */

55
questions/55.Fix中对于对象属性的监听,为什么要先定义属性才可以正常watch,如何解决.md

@ -0,0 +1,55 @@
# Fix中对于对象属性的监听,为什么要先定义属性才可以正常watch,如何解决?
先看如下代码示例,很明显按钮被点击后并不会输出phone的值,其实这和Vue2类似,是因为Fix在响应式处理的时候,遍历对象的每一个属性添加依赖的,并不能检测到新增的属性.
```javascript
const state = Fix.define({
name: "小明",
details: {
age: 18,
address: "北京",
},
});
Fix.watch(state, "details.phone", phone => {
console.log(phone);
});
const widget = BI.createWidget({
type: "bi.button",
text: "button",
handler: () => {
state.details.phone = "123456789";
},
});
```
在日常实践中我们一般采用两种方式来处理这种情况
1. 修改整个对象的引用
```
const widget = BI.createWidget({
type: "bi.button",
text: "button",
handler: () => {
state.details = { ...state.details, phone: "123456789"};
},
});
```
2. 使用Fix.set方法
类似vue的$set方法
```
const widget = BI.createWidget({
type: "bi.button",
text: "button",
handler: () => {
Fix.set(state.details, "phone", "123456789");
},
});
```

0
questions/81.combo的一些特性.md

Loading…
Cancel
Save