From 3db05813a2ecacd1c4d0687224303544dea1447b Mon Sep 17 00:00:00 2001 From: kirakiray Date: Sun, 9 Jun 2019 23:09:42 +0800 Subject: [PATCH] add todolist --- demo/todilist/main.html | 16 -- .../js/components/todolist/temp.html | 137 ++++++++++ .../js/components/todolist/test.html | 36 +++ .../js/components/todolist/todilist.css | 1 + .../js/components/todolist/todilist.css.map | 1 + .../js/components/todolist/todilist.less | 233 ++++++++++++++++++ .../js/components/todolist/todoitem.js | 105 ++++++++ .../js/components/todolist/todolist.js | 96 ++++++++ demo/todilist_test/js/main.js | 90 +++++++ demo/todilist_test/main.html | 29 +++ .../{todolist_view.png => todolist_view.jpeg} | Bin doc/todolist.md | 50 +++- 12 files changed, 774 insertions(+), 20 deletions(-) delete mode 100644 demo/todilist/main.html create mode 100644 demo/todilist_test/js/components/todolist/temp.html create mode 100644 demo/todilist_test/js/components/todolist/test.html create mode 100644 demo/todilist_test/js/components/todolist/todilist.css create mode 100644 demo/todilist_test/js/components/todolist/todilist.css.map create mode 100644 demo/todilist_test/js/components/todolist/todilist.less create mode 100644 demo/todilist_test/js/components/todolist/todoitem.js create mode 100644 demo/todilist_test/js/components/todolist/todolist.js create mode 100644 demo/todilist_test/js/main.js create mode 100644 demo/todilist_test/main.html rename doc/sources/{todolist_view.png => todolist_view.jpeg} (100%) diff --git a/demo/todilist/main.html b/demo/todilist/main.html deleted file mode 100644 index ca31488a..00000000 --- a/demo/todilist/main.html +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - - ToDoList - - - - - - - - \ No newline at end of file diff --git a/demo/todilist_test/js/components/todolist/temp.html b/demo/todilist_test/js/components/todolist/temp.html new file mode 100644 index 00000000..97bedb14 --- /dev/null +++ b/demo/todilist_test/js/components/todolist/temp.html @@ -0,0 +1,137 @@ + + + + + + + + TODOlist静态模板 + + + + + + +
+
ALL
+
DAY
+
WEEK
+
MONTH
+
+
+
+ +
+
我是任务我是任务我是任务我是任务我是任务我是任务我是任务我是任务是任务我是任务我是任务是任务我是任务我是任务
+
+
28 day
+
Change + +
+
+
+ +
+
我是任务1
+
+
2 hours
+
Change
+
+
+ +
+
我是任务2
+
+
30 min
+
Change
+
+
+ +
+
我是任务3
+
+
LATE
+
Change
+
+
+ +
+
我是任务4
+
+
DONE
+
Change
+
+
+ +
+
{{name}}
+
+
{{showTime}}
+
Change + +
+
+
+
+
+
+
+ + +
任务内容: + +
+
+ 后 +
+ +
+
+ + +
+
ALL
+
DAY
+
WEEK
+
MONTH
+
+
+
+
+
+ + + \ No newline at end of file diff --git a/demo/todilist_test/js/components/todolist/test.html b/demo/todilist_test/js/components/todolist/test.html new file mode 100644 index 00000000..7d34db7b --- /dev/null +++ b/demo/todilist_test/js/components/todolist/test.html @@ -0,0 +1,36 @@ + + + + + + + + todolist 模块使用测试 + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/demo/todilist_test/js/components/todolist/todilist.css b/demo/todilist_test/js/components/todolist/todilist.css new file mode 100644 index 00000000..0d01354c --- /dev/null +++ b/demo/todilist_test/js/components/todolist/todilist.css @@ -0,0 +1 @@ +todolist{display:flex;flex-direction:column;border-radius:8px;background-color:#3e404d;-webkit-font-smoothing:antialiased;font-family:"FZLanTingHei-R-GBK",STHeiti STXihei,Microsoft Yahei,Arial;-webkit-tap-highlight-color:rgba(0,0,0,0);color:#fefdff;user-select:none}todolist .tl_tabs{display:flex;height:70px;color:#fafaff}todolist .tl_tabs .tl_tab{position:relative;display:flex;justify-content:center;align-items:center;padding:0 10px;flex:1;text-align:center;font-size:12px;cursor:pointer}todolist .tl_tabs .tl_tab:after{display:block;position:absolute;bottom:0;left:0;width:100%;height:1px;background-color:#515360;content:"";transition:all ease .3s}todolist .tl_tabs .tl_tab.active{font-weight:bold;color:#fff;cursor:default}todolist .tl_tabs .tl_tab.active:after{background-color:#fffeff}todolist .tl_main{position:relative;flex:1}todolist .tl_main .tl_main_scroller{position:absolute;left:0;top:0;width:100%;height:100%;overflow-y:auto}todolist todoitem{display:flex;height:70px;align-items:center;font-size:14px;border-bottom:rgba(27,29,42,0.521) solid 1px;overflow:hidden;transition:all ease .3s;animation:todoitem_anime ease .3s}todolist todoitem.hide{opacity:0;height:0}todolist todoitem .tdi_point{margin:0 20px 0 30px;width:10px;height:10px;border-radius:6px;background-color:#cacaca;box-shadow:rgba(0,0,0,0.2) 0 0 3px}todolist todoitem .tdi_name{flex:1;text-overflow:ellipsis;overflow:hidden;white-space:nowrap}todolist todoitem .tdi_right{display:flex;justify-content:center;align-items:center;flex-direction:column;width:100px;font-size:11px;color:#aaacb9}todolist todoitem[tdtype="1"] .tdi_point{background-color:#36d147}todolist todoitem[tdtype="2"] .tdi_point{background-color:#fa9e49}todolist todoitem .timecon{height:18px;line-height:18px;overflow:hidden;transition:height ease .3s}todolist todoitem[tdtype="3"] .timecon,todolist todoitem[tdtype="4"] .timecon{display:block;width:40px;font-size:9px;color:#fff;font-weight:bold;text-align:center}todolist todoitem[tdtype="3"] .tdi_point{background-color:#f94f5a}todolist todoitem[tdtype="3"] .timecon{background-color:#f94f5a}todolist todoitem[tdtype="4"] .tdi_point{background-color:#1596e9}todolist todoitem[tdtype="4"] .tdi_name{color:#a3a5a4;text-decoration:line-through;text-decoration-color:#000000}todolist todoitem[tdtype="4"] .timecon{background-color:#1596e9}todolist todoitem .change_btn{position:relative;width:50px;height:18px;line-height:18px;font-size:9px;color:#2c2c2c;text-align:center;background-color:#dddddd;font-weight:bold;cursor:pointer;height:0;overflow:hidden;transition:all ease .3s}todolist todoitem .change_btn select{position:absolute;left:0;top:0;width:100%;height:100%;opacity:0;cursor:pointer}todolist todoitem:hover .change_btn{height:18px}todolist todoitem:hover .timecon{height:0}@keyframes todoitem_anime{0%{opacity:0;height:0}100%{opacity:1;height:70px}}todolist-input{display:flex;align-items:center;justify-content:space-around;width:400px;height:40px;border-radius:8px;background-color:#3e404d;color:#fdfdfd;font-size:12px}/*# sourceMappingURL=./todilist.css.map */ \ No newline at end of file diff --git a/demo/todilist_test/js/components/todolist/todilist.css.map b/demo/todilist_test/js/components/todolist/todilist.css.map new file mode 100644 index 00000000..61ac8e78 --- /dev/null +++ b/demo/todilist_test/js/components/todolist/todilist.css.map @@ -0,0 +1 @@ +{"version":3,"sources":["todilist.less"],"names":[],"mappings":"AACA,SACI,YAAA,CACA,qBAAA,CACA,iBAAA,CACA,wBAAA,CACA,kCAAA,CACA,YAAa,0DAAb,CACA,yCAAA,CACA,aAAA,CACA,iBATJ,QAWI,UACI,YAAA,CACA,WAAA,CACA,cAdR,QAWI,SAKI,SACI,iBAAA,CACA,YAAA,CACA,sBAAA,CACA,kBAAA,CACA,cAAA,CACA,MAAA,CACA,iBAAA,CACA,cAAA,CACA,eAEA,QAhBR,SAKI,QAWK,OACG,aAAA,CACA,iBAAA,CACA,QAAA,CACA,MAAA,CACA,UAAA,CACA,UAAA,CACA,wBAAA,CACA,QAAS,EAAT,CACA,wBAGJ,QA5BR,SAKI,QAuBK,QACG,gBAAA,CACA,UAAA,CACA,eAEA,QAjCZ,SAKI,QAuBK,OAKI,OACG,yBA7CpB,QAmDI,UACI,iBAAA,CACA,OArDR,QAmDI,SAII,mBACI,iBAAA,CACA,MAAA,CACA,KAAA,CACA,UAAA,CACA,WAAA,CACA,gBA7DZ,QAiEI,UACI,YAAA,CACA,WAAA,CACA,kBAAA,CACA,cAAA,CACA,4CAAA,CACA,eAAA,CACA,uBAAA,CACA,kCAEA,QAVJ,SAUK,MACG,SAAA,CACA,SA7EZ,QAiEI,SAmBI,YACI,oBAAA,CACA,UAAA,CACA,WAAA,CACA,iBAAA,CACA,wBAAA,CACA,mCA1FZ,QAiEI,SA4BI,WACI,MAAA,CACA,sBAAA,CACA,eAAA,CACA,mBAjGZ,QAiEI,SAmCI,YACI,YAAA,CACA,sBAAA,CACA,kBAAA,CACA,qBAAA,CACA,WAAA,CACA,cAAA,CACA,cAGJ,QA7CJ,SA6CK,YACG,YACI,yBAIR,QAnDJ,SAmDK,YACG,YACI,yBAtHhB,QAiEI,SAyDI,UACI,WAAA,CACA,gBAAA,CACA,eAAA,CACA,2BAGJ,QAhEJ,SAgEK,YAEG,UADJ,QAjEJ,SAiEK,YACG,UACI,aAAA,CACA,UAAA,CACA,aAAA,CACA,UAAA,CACA,gBAAA,CACA,kBAIR,QA5EJ,SA4EK,YACG,YACI,yBAFR,QA5EJ,SA4EK,YAKG,UACI,yBAIR,QAtFJ,SAsFK,YACG,YACI,yBAFR,QAtFJ,SAsFK,YAKG,WACI,aAAA,CACA,4BAAA,CACA,8BARR,QAtFJ,SAsFK,YAYG,UACI,yBApKhB,QAiEI,SAyGI,aACI,iBAAA,CACA,UAAA,CACA,WAAA,CACA,gBAAA,CACA,aAAA,CACA,aAAA,CACA,iBAAA,CACA,wBAAA,CACA,gBAAA,CACA,cAAA,CAEA,QAAA,CACA,eAAA,CACA,wBAxLZ,QAiEI,SAyGI,YAgBI,QACI,iBAAA,CACA,MAAA,CACA,KAAA,CACA,UAAA,CACA,WAAA,CACA,SAAA,CACA,eAIR,QApIJ,SAoIK,MACG,aACI,YAFR,QApIJ,SAoIK,MAKG,UACI,SAMhB,0BACI,GACI,SAAA,CACA,SAGJ,KACI,SAAA,CACA,aAIR,eACI,YAAA,CACA,kBAAA,CACA,4BAAA,CACA,WAAA,CACA,WAAA,CACA,iBAAA,CACA,wBAAA,CACA,aAAA,CACA"} \ No newline at end of file diff --git a/demo/todilist_test/js/components/todolist/todilist.less b/demo/todilist_test/js/components/todolist/todilist.less new file mode 100644 index 00000000..477ef733 --- /dev/null +++ b/demo/todilist_test/js/components/todolist/todilist.less @@ -0,0 +1,233 @@ +// compress: true, sourceMap: true +todolist { + display: flex; + flex-direction: column; + border-radius: 8px; + background-color: #3e404d; + -webkit-font-smoothing: antialiased; + font-family: "FZLanTingHei-R-GBK", STHeiti STXihei, Microsoft Yahei, Arial; + -webkit-tap-highlight-color: rgba(0, 0, 0, 0); + color: #fefdff; + user-select: none; + + .tl_tabs { + display: flex; + height: 70px; + color: #fafaff; + + .tl_tab { + position: relative; + display: flex; + justify-content: center; + align-items: center; + padding: 0 10px; + flex: 1; + text-align: center; + font-size: 12px; + cursor: pointer; + + &:after { + display: block; + position: absolute; + bottom: 0; + left: 0; + width: 100%; + height: 1px; + background-color: #515360; + content: ""; + transition: all ease .3s; + } + + &.active { + font-weight: bold; + color: #fff; + cursor: default; + + &:after { + background-color: #fffeff; + } + } + } + } + + .tl_main { + position: relative; + flex: 1; + + .tl_main_scroller { + position: absolute; + left: 0; + top: 0; + width: 100%; + height: 100%; + overflow-y: auto; + } + } + + todoitem { + display: flex; + height: 70px; + align-items: center; + font-size: 14px; + border-bottom: rgba(27, 29, 42, 0.521) solid 1px; + overflow: hidden; + transition: all ease .3s; + animation: todoitem_anime ease .3s; + + &.hide { + opacity: 0; + height: 0; + } + + // &:first-child { + // border-top: none; + // } + + .tdi_point { + margin: 0 20px 0 30px; + width: 10px; + height: 10px; + border-radius: 6px; + background-color: #cacaca; + box-shadow: rgba(0, 0, 0, .2) 0 0 3px; + } + + .tdi_name { + flex: 1; + text-overflow: ellipsis; + overflow: hidden; + white-space: nowrap; + } + + .tdi_right { + display: flex; + justify-content: center; + align-items: center; + flex-direction: column; + width: 100px; + font-size: 11px; + color: #aaacb9; + } + + &[tdtype="1"] { + .tdi_point { + background-color: #36d147; + } + } + + &[tdtype="2"] { + .tdi_point { + background-color: #fa9e49; + } + } + + .timecon { + height: 18px; + line-height: 18px; + overflow: hidden; + transition: height ease .3s; + } + + &[tdtype="3"], + &[tdtype="4"] { + .timecon { + display: block; + width: 40px; + font-size: 9px; + color: #fff; + font-weight: bold; + text-align: center; + } + } + + &[tdtype="3"] { + .tdi_point { + background-color: #f94f5a; + } + + .timecon { + background-color: #f94f5a; + } + } + + &[tdtype="4"] { + .tdi_point { + background-color: #1596e9; + } + + .tdi_name { + color: #a3a5a4; + text-decoration: line-through; + text-decoration-color: #000000; + } + + + .timecon { + background-color: #1596e9; + } + + // border-top: rgba(93, 95, 108, 0.753) solid 1px; + } + + .change_btn { + position: relative; + width: 50px; + height: 18px; + line-height: 18px; + font-size: 9px; + color: rgb(44, 44, 44); + text-align: center; + background-color: #dddddd; + font-weight: bold; + cursor: pointer; + + height: 0px; + overflow: hidden; + transition: all ease .3s; + + select { + position: absolute; + left: 0; + top: 0; + width: 100%; + height: 100%; + opacity: 0; + cursor: pointer; + } + } + + &:hover { + .change_btn { + height: 18px; + } + + .timecon { + height: 0; + } + } + } +} + +@keyframes todoitem_anime { + 0% { + opacity: 0; + height: 0; + } + + 100% { + opacity: 1; + height: 70px; + } +} + +todolist-input { + display: flex; + align-items: center; + justify-content: space-around; + width: 400px; + height: 40px; + border-radius: 8px; + background-color: #3e404d; + color: #fdfdfd; + font-size: 12px; +} \ No newline at end of file diff --git a/demo/todilist_test/js/components/todolist/todoitem.js b/demo/todilist_test/js/components/todolist/todoitem.js new file mode 100644 index 00000000..97491f75 --- /dev/null +++ b/demo/todilist_test/js/components/todolist/todoitem.js @@ -0,0 +1,105 @@ +define(async (load) => { + + let { + todoitem + } = await load("./temp.dcode -inner"); + + $.register({ + tag: "todoitem", + temp: todoitem, + data: { + // 任务名 + name: "默认名", + // 右边的展示时间 + showTime: "0 min", + // 制定的时间 + time: (new Date().getTime()) / 1000, + // 是否完成 + doType: "undo" + }, + attrs: ["name", "time"], + proto: { + // 刷新时间显示 + refreshShow() { + let diffTime = new Date(this.time * 1000).getTime() - new Date().getTime(); + + diffTime /= 1000; + + // 显示时间 + let showTime = ""; + + if (diffTime < 0) { + showTime = "LATE"; + } else if (diffTime <= 60) { + showTime = "1 min"; + } else if (diffTime <= 300) { + showTime = "5 min"; + } else if (diffTime <= 600) { + showTime = "10 min"; + } else if (diffTime <= 1800) { + showTime = "30 min"; + } else if (diffTime <= 3600) { + showTime = "1 hours"; + } else if (diffTime <= 7200) { + showTime = "2 hours"; + } else if (diffTime <= 10800) { + showTime = "3 hours"; + } else if (diffTime <= 21600) { + showTime = "6 hours"; + } else if (diffTime <= 43200) { + showTime = "6 hours"; + } else if (diffTime <= 86400) { + showTime = "12 hours"; + } else if (diffTime <= 172800) { + showTime = "1 days"; + } else if (diffTime <= 259200) { + showTime = "2 days"; + } else if (diffTime <= 604800) { + showTime = "1 weeks"; + } else if (diffTime <= 1209600) { + showTime = "2 weeks"; + } else if (diffTime <= 2592000) { + showTime = "1 months"; + } else { + showTime = "1 months later"; + } + + // 修正状态 + let tdtype = 1; + + if (diffTime <= 60) { + tdtype = 3; + } else if (diffTime <= 3600) { + tdtype = 2; + } + + if (this.doType == "done") { + tdtype = 4; + showTime = "DONE"; + } + + // 修正元素提示素材 + this.showTime = showTime; + this.attr("tdtype", tdtype); + this.$mainSelector.attr('title', new Date(this.time * 1000).toLocaleString()); + } + }, + watch: { + name(e, val) { + this.$name.attr("title", val); + }, + time(e, val) { + this.refreshShow(); + }, + doType(e, val) { + if (val == "close") { + // 先隐藏动画,再删除 + this.class.add("hide"); + setTimeout(() => this.remove(), 300); + return; + } + this.refreshShow(); + } + } + }); +}); \ No newline at end of file diff --git a/demo/todilist_test/js/components/todolist/todolist.js b/demo/todilist_test/js/components/todolist/todolist.js new file mode 100644 index 00000000..d682bbf8 --- /dev/null +++ b/demo/todilist_test/js/components/todolist/todolist.js @@ -0,0 +1,96 @@ +define(async (load) => { + // 添加样式 + await load("./todilist.css", "./todoitem"); + + let { + todolist, + todolistInput + } = await load("./temp.dcode -inner"); + + $.register({ + tag: "todolist", + temp: todolist, + inited() { + this.$tabs.on("click", ".tl_tab", (e) => { + let { + delegateTarget + } = e; + + if (delegateTarget.class.contains("active")) { + // 是当前激活的按钮,就不用继续 + return; + } + + // 去除之前激活状态 + this.$tabs.que(".active").class.remove("active"); + + // 当前按钮添加激活 + delegateTarget.class.add("active"); + + // 根据stime和btime定制规则 + let stime = parseInt(delegateTarget.attr("stime")); + let btime = parseInt(delegateTarget.attr("btime")); + + let nTime = new Date().getTime() / 1000; + + // 遍历 + this.forEach(todoItem => { + nTime, + stime, + btime + let diffTime = todoItem.time - nTime; + + if (diffTime > stime && diffTime < btime) { + todoItem.class.remove('hide'); + } else { + todoItem.class.add('hide'); + } + }); + }); + }, + attached() { + this._timer = setInterval(() => { + this.forEach(e => { + e.refreshShow(); + }); + }, 3000); + }, + detached() { + clearInterval(this._timer); + } + }); + + // 顺便封装了 input输入框 + $.register({ + tag: "todolist-input", + temp: todolistInput, + data: { + todoTime: "", + todoName: "" + }, + inited() { + // 点击了提交按钮 + this.$todoSubmit.on("click", e => { + let { + todoTime, + todoName + } = this; + + // 确定没有空值 + if (!todoTime || !todoName) { + return; + } + + // 清空数据 + this.todoTime = ""; + this.todoName = ""; + + // 提交事件 + this.emit("clickSubmit", { + todoTime, + todoName + }); + }); + } + }); +}); \ No newline at end of file diff --git a/demo/todilist_test/js/main.js b/demo/todilist_test/js/main.js new file mode 100644 index 00000000..f3398664 --- /dev/null +++ b/demo/todilist_test/js/main.js @@ -0,0 +1,90 @@ +(async () => { + drill.config({ + baseUrl: "js/" + }); + + // 等待载入 XD组件包 todolist + await load("components/todolist -pack"); + + // 获取组件 + let todolist = $(".mainList"); + let mainInput = $('.listInput'); + + // 获取数据 + let beforeDataStr = localStorage.getItem("_todolist_datas"); + if (beforeDataStr) { + // 存在数据的话,填充初始数据 + let data = JSON.parse(beforeDataStr); + + // 添加关键字 + data.forEach(e => { + e.xvele = 1; + }); + + // 还原数据 + todolist.extend(data); + } + + // 监听数据变动 + todolist.watch(e => { + // 转换普通 object + let data = todolist.object; + + // 设置length,转换Array + data.length = todolist.length; + data = Array.from(data); + + // 去除无用字段 + data.forEach(e => { + delete e.showTime; + delete e.xvele; + }); + + // 防止数据重复记录 + let dataStr = JSON.stringify(data); + + if (beforeDataStr === dataStr) { + return; + } + + beforeDataStr = dataStr; + + // 存储到localstorage + localStorage.setItem("_todolist_datas", dataStr); + + console.log('保存的数据 => ', data); + }); + + // 监听输入设施 + mainInput.on("clickSubmit", (e, data) => { + let time = parseInt(data.todoTime) + new Date().getTime() / 1000; + if (!todolist.length) { + // 添加队列 + todolist.push({ + tag: "todoitem", + name: data.todoName, + time: time, + xvele: 1 + }); + } else { + // 插入的id位置 + let slotId = -1; + todolist.find((item, i) => { + if (time > item.time) { + slotId = i; + } else { + return true; + } + }); + slotId++; + + // 插入相应位置 + todolist.splice(slotId, 0, { + tag: "todoitem", + name: data.todoName, + time: time, + xvele: 1 + }); + } + }); +})(); \ No newline at end of file diff --git a/demo/todilist_test/main.html b/demo/todilist_test/main.html new file mode 100644 index 00000000..e5498b73 --- /dev/null +++ b/demo/todilist_test/main.html @@ -0,0 +1,29 @@ + + + + + + + + ToDoList + + + + + + + + + + + \ No newline at end of file diff --git a/doc/sources/todolist_view.png b/doc/sources/todolist_view.jpeg similarity index 100% rename from doc/sources/todolist_view.png rename to doc/sources/todolist_view.jpeg diff --git a/doc/todolist.md b/doc/todolist.md index fd8c5919..183ee360 100644 --- a/doc/todolist.md +++ b/doc/todolist.md @@ -4,12 +4,54 @@ 从 dribbble 找的设计图; - + [原图片地址在这里](https://dribbble.com/shots/5441213-Daily-UI-042);本案例仅供学习,不可商用; -## 2.添加需求 +## 2.添加需求和确认思路 -如果只按照图中的需求来做,无法即时改变 item的状态,所以在图的基础上添加一个需求; +如果只按照图中的需求来做,无法即时改变 item的状态,所以在图的基础上添加3个需求; + +* 添加一个 ALL tab; +* 添加todoitem的输入框; +* 每个item都可以修改状态; + +确认制作思路,所有item 都在一个列表上;当切换 DAY WEEK MONTH 的 TAB 时,将不符合要求的隐藏; + +## 3.制作静态模板 + +静态模板在这里 [ToDoList静态模板](../demo/todilist/js/components/todolist/temp.html) + +对伪类不熟悉的同学,也可以把 `:hover` 放到组件逻辑里做;动画采用 css3 的 `transition`; + +需要提的css细节是,通过element的属性来控制element的样式; + +有机会作者会录个css教程视频; + +```less +[tdtype="3"] { + ... + .tdi_point { + background-color: #f94f5a; + } + ... +} +[tdtype="4"] { + ... + .tdi_point { + background-color: #1596e9; + } + ... +} +``` + +更具体css细节怎么写,这里不多说; + +## 4.封装组件包 + +在 XDFrame里,包就是一个文件夹;在 `drill.js` 模块管理体系里,同目录下的模块可以使用 `./` 开头引用;而采用 `-pack` 参数,可以载入同目录名的 `js` 文件; + +将组件的所有逻辑写在一个目录下,在通过目录同名的 `js` 文件作为目录的入口,进行组建封装,就是 `XD组件包`; + +参看 `demo/todilist/js/components/todolist`目录,就是 todolist 的组件包; -* 每个item都可以修改状态; \ No newline at end of file