├── .gitignore ├── README.md ├── js ├── demo.json ├── storage.js └── note.js ├── index.html └── css └── style.css /.gitignore: -------------------------------------------------------------------------------- 1 | .fuse* -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [百度前端学院task3](https://github.com/baidu-ife/ife/tree/master/2015_spring/task/task0003) 2 | 使用vue.js编写的记事本,localstorage作为数据存储。 -------------------------------------------------------------------------------- /js/demo.json: -------------------------------------------------------------------------------- 1 | { 2 | "catalogs": { 3 | "length": 3, 4 | "catalogs": [ 5 | { 6 | "id": 0, 7 | "name": "python" 8 | }, 9 | { 10 | "id": 1, 11 | "name": "javascript" 12 | }, 13 | { 14 | "id": 2, 15 | "name": "css" 16 | } 17 | ] 18 | }, 19 | "tasks": { 20 | "0": [ 21 | { 22 | "title": "call, apply和bind", 23 | "content": "call, apply和bindcall, apply和bind", 24 | "size": "1823", 25 | "createTime": "2015/11/2", 26 | "updateTime": "2015/11/14" 27 | } 28 | ], 29 | "1": [ 30 | { 31 | "title": "call, apply和bind", 32 | "content": "call, apply和bindcall, apply和bind", 33 | "size": "1823", 34 | "createTime": "2015/11/2", 35 | "updateTime": "2015/11/14" 36 | }, 37 | { 38 | "title": "call, apply和bind", 39 | "content": "call, apply和bindcall, apply和bind", 40 | "size": "1823", 41 | "createTime": "2015/11/2", 42 | "updateTime": "2015/11/14" 43 | } 44 | ] 45 | } 46 | } -------------------------------------------------------------------------------- /js/storage.js: -------------------------------------------------------------------------------- 1 | function Storage() { 2 | this.storage = window.localStorage; 3 | } 4 | 5 | Storage.prototype = { 6 | 7 | fetchCatalog: function() { 8 | return JSON.parse(this.storage.getItem('catalog') || '{"length":2,"catalogs":[{"id":0,"name":"python","length":0},{"id":1,"name":"javascript","length":0}]}') 9 | }, 10 | 11 | saveCatalog: function(catalogs) { 12 | this.storage.setItem('catalog', JSON.stringify(catalogs)); 13 | }, 14 | 15 | fetchTask: function() { 16 | return JSON.parse(this.storage.getItem('task')) || {"0":[{"title":"python列表推导式与字典推导式","content":"[i for i in range(100)]
{k:v for k,v in enumerate('abced')}","size":62,"createTime":"13/12/2015, 10:00:31","updateTime":"13/12/2015, 10:13:48"},{"title":"切片命名","content":"str = 'wangxiansdfasfasfasdfas'
name = slice(8)
str[name]    // wangxian","size":93,"createTime":"13/12/2015, 10:05:35","updateTime":"13/12/2015, 10:11:50"}],"1":[{"title":"ES6 promise的用法","content":"p.then(data =>{
    // dosomething
}).catch(err => {

});","size":90,"createTime":"13/12/2015, 10:16:29","updateTime":"13/12/2015, 10:16:29"}]}; 17 | }, 18 | 19 | saveTask: function(tasks) { 20 | this.storage.setItem('task', JSON.stringify(tasks)); 21 | }, 22 | 23 | getCid: function() { 24 | return JSON.parse(this.storage.getItem('taskOfCatalogId')) || 0; 25 | }, 26 | 27 | saveCid: function(cid) { 28 | this.storage.setItem('taskOfCatalogId', JSON.stringify(cid)); 29 | }, 30 | 31 | getEditTask: function() { 32 | return JSON.parse(this.storage.getItem('editTask')) || this.fetchTask()[0][0] || {}; 33 | }, 34 | 35 | saveEditTask: function(task) { 36 | this.storage.setItem('editTask', JSON.stringify(task)); 37 | } 38 | } 39 | 40 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Document 6 | 7 | 8 | 9 | 10 |
11 |
笔记本
12 |
13 |
14 |
15 | 22 |
23 | 新增分类 24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 | 新增笔记 35 |
36 |
37 |
38 |
39 |
40 |
41 | 编辑 42 | 删除 43 | 保存 44 |
45 |
46 |
47 |
48 |
49 |
50 | 创建于: {{ editTask.createTime }} 51 | 更新于:{{ editTask.updateTime }} 52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 | 62 | 提交 63 |
64 |
65 | 66 | 67 | 68 | 69 | -------------------------------------------------------------------------------- /js/note.js: -------------------------------------------------------------------------------- 1 | var storage = new Storage(); 2 | var vm = new Vue({ 3 | el: 'body', 4 | data: { 5 | tasks: storage.fetchTask(), 6 | catalogs: storage.fetchCatalog(), 7 | taskOfCatalogId: storage.getCid(), 8 | editTask: storage.getEditTask(), 9 | editable: false, 10 | newCatalog: '', 11 | model: false, 12 | }, 13 | methods: { 14 | toggleModel: function(event) { 15 | this.model = !this.model; 16 | }, 17 | 18 | addCatalog: function() { 19 | var catalogname = this.newCatalog; 20 | if (catalogname) { 21 | if (!this.catalogs['length']) { 22 | this.catalogs['length'] = 0; 23 | this.catalogs.catalogs = []; 24 | } 25 | var len = this.catalogs.length; 26 | var catalog = { 27 | 'id': len, 28 | 'name': catalogname, 29 | 'length': 0, 30 | } 31 | this.catalogs.length++; 32 | this.catalogs.catalogs.push(catalog); 33 | Vue.set(this.tasks, len, []); 34 | this.newCatalog = ''; 35 | this.model = false; 36 | this.taskOfCatalogId = len; 37 | } 38 | }, 39 | removeCatalog: function(catalog) { 40 | this.catalogs.catalogs.$remove(catalog); 41 | }, 42 | removeTask: function() { 43 | this.tasks[this.taskOfCatalogId].$remove(this.editTask); 44 | }, 45 | toggleTaskPanel: function() { 46 | this.editable = true; 47 | this.editTask = {}; 48 | document.getElementsByClassName('note-text')[0].innerHTML = ''; 49 | document.getElementsByClassName('edit-content')[0].innerHTML = ''; 50 | }, 51 | saveTask: function() { 52 | if (!this.editable) 53 | return; 54 | var id = this.taskOfCatalogId; 55 | var title = document.getElementsByClassName('note-text')[0].textContent.trim(); 56 | var content = document.getElementsByClassName('edit-content')[0].innerHTML.trim(); 57 | if (!this.editTask.title && title) { 58 | var task = { 59 | title: title, 60 | content: content, 61 | size: content.length, 62 | createTime: new Date().toLocaleString('en-GB', {hour12:false}), 63 | updateTime: new Date().toLocaleString('en-GB', {hour12:false}) 64 | }; 65 | this.tasks[id].push(task); 66 | this.editTask = task; 67 | 68 | } else { 69 | this.editTask.title = title ? title: 'untitled'; 70 | this.editTask.content = content; 71 | this.editTask.size = content.length; 72 | this.editTask.updateTime = new Date().toLocaleString('en-GB', {hour12:false}); 73 | } 74 | this.editable = false; 75 | }, 76 | }, 77 | watch: { 78 | catalogs: { 79 | handler: function(catalogs) { 80 | storage.saveCatalog(catalogs); 81 | }, 82 | deep: true, 83 | }, 84 | editable: { 85 | handler: function() { 86 | storage.saveTask(this.tasks); 87 | }, 88 | deep: true, 89 | }, 90 | tasks: { 91 | handler: function(tasks) { 92 | storage.saveTask(this.tasks); 93 | }, 94 | deep: true, 95 | }, 96 | taskOfCatalogId: { 97 | handler: function(cid) { 98 | storage.saveCid(cid); 99 | this.editTask = this.tasks[cid][0] || {}; 100 | } 101 | }, 102 | editTask: { 103 | handler: function(task) { 104 | storage.saveEditTask(task); 105 | } 106 | } 107 | } 108 | }); 109 | 110 | 111 | 112 | 113 | -------------------------------------------------------------------------------- /css/style.css: -------------------------------------------------------------------------------- 1 | /*reset*/ 2 | 3 | * { 4 | box-sizing: border-box; 5 | } 6 | 7 | html, 8 | body { 9 | height: 100%; 10 | padding: 0; 11 | margin: 0; 12 | font-family: "Lucida Console", Helvetica, "Microsoft Yahei", "Hiragino Sans GB", sans-serif; 13 | } 14 | 15 | ul { 16 | padding: 0; 17 | margin: 0; 18 | } 19 | 20 | li { 21 | display: block; 22 | padding-left: 25px; 23 | line-height: 35px; 24 | } 25 | 26 | a { 27 | color: #000; 28 | text-decoration: none; 29 | } 30 | 31 | .btn { 32 | padding: 5px; 33 | cursor: pointer; 34 | background-color: rgba(10, 10, 10, 0.1); 35 | border: 1px solid #ccc; 36 | border-radius: 4px; 37 | } 38 | 39 | /*头部*/ 40 | 41 | .header { 42 | position: absolute; 43 | top: 0; 44 | width: 100%; 45 | height: 55px; 46 | padding-left: 20px; 47 | line-height: 55px; 48 | background-color: #c7c7c7; 49 | border-bottom: 1px solid #aaa; 50 | } 51 | 52 | .title { 53 | font-size: 1.6em; 54 | line-height: 55px; 55 | color: #888; 56 | } 57 | 58 | /*内容区大致布局*/ 59 | 60 | .content { 61 | height: 100%; 62 | padding-top: 55px; 63 | } 64 | 65 | .catalog, 66 | .task { 67 | position: relative; 68 | z-index: 1; 69 | padding-bottom: 41px; 70 | border-right: 1px solid #ccc; 71 | } 72 | 73 | .catalog { 74 | float: left; 75 | width: 200px; 76 | height: 100%; 77 | } 78 | 79 | .task { 80 | float: left; 81 | width: 300px; 82 | height: 100%; 83 | } 84 | 85 | .detail { 86 | position: relative; 87 | height: 100%; 88 | padding-left: 500px; 89 | } 90 | 91 | /*左侧目录*/ 92 | 93 | .catalog .list { 94 | height: 100%; 95 | overflow-x: hidden; 96 | overflow-y: auto; 97 | } 98 | 99 | .catalog .item { 100 | cursor: pointer; 101 | /*background-color: #eff;*/ 102 | border-bottom: 1px solid #eee; 103 | } 104 | 105 | .catalog .item.active, 106 | .catalog .item:hover { 107 | background-color: #eee; 108 | } 109 | 110 | .add { 111 | position: absolute; 112 | bottom: 0; 113 | left: 0; 114 | z-index: 3; 115 | width: 100%; 116 | height: 40px; 117 | line-height: 39px; 118 | text-align: center; 119 | border-top: 1px solid #aaa; 120 | cursor: pointer; 121 | } 122 | 123 | .delete { 124 | color: #aaa; 125 | cursor: pointer; 126 | position: absolute; 127 | right: 10px; 128 | } 129 | 130 | /*中间任务列表*/ 131 | 132 | .task .btn { 133 | position: relative; 134 | left: 60px; 135 | } 136 | 137 | .task .list { 138 | position: relative; 139 | height: 100%; 140 | overflow-y: auto; 141 | } 142 | 143 | .task .item { 144 | padding: 10px 25px; 145 | word-break: break-all; 146 | cursor: pointer; 147 | background-color: #fff; 148 | border-bottom: 1px solid #cfe; 149 | } 150 | 151 | .task .item .date { 152 | font-size: 0.8em; 153 | color: rgba(0, 0, 0, 0.3); 154 | } 155 | 156 | .task .item.active, 157 | .task .item:hover { 158 | background-color: #eee; 159 | } 160 | 161 | /*右侧笔记区域*/ 162 | .detail-box { 163 | height: 100%; 164 | } 165 | 166 | .detail-date.editing, 167 | .detail-title.editing, 168 | .edit-content.editing { 169 | border-left: 3px solid #aaa; 170 | } 171 | 172 | .detail-title { 173 | position: absolute; 174 | right: 0; 175 | left: 500px; 176 | height: 50px; 177 | padding: 8px 20px; 178 | line-height: 33px; 179 | background-color: #fbfbfb; 180 | border-bottom: 1px solid #ccc; 181 | } 182 | 183 | .detail-title .note-text { 184 | width: 100%; 185 | height: 100%; 186 | } 187 | 188 | .detail-title .btns { 189 | float: right; 190 | } 191 | 192 | .detail-date { 193 | position: absolute; 194 | top: 50px; 195 | right: 0; 196 | left: 500px; 197 | height: 40px; 198 | padding-left: 20px; 199 | font-size: 0.9em; 200 | line-height: 40px; 201 | color: #bbb; 202 | background-color: #fbfbfb; 203 | border-bottom: 1px solid #ccc; 204 | } 205 | 206 | .edit-content { 207 | height: 100%; 208 | padding: 110px 20px 20px; 209 | font-size: 1.1em; 210 | word-wrap: break-word; 211 | font-family: "Source Code Pro",Consolas,Menlo,Monaco,"Courier New",monospace 212 | } 213 | 214 | /* 模态框*/ 215 | 216 | .model { 217 | position: absolute; 218 | top: 50%; 219 | left: 50%; 220 | z-index: 10; 221 | width: 300px; 222 | height: 100px; 223 | background-color: #fff; 224 | border: 1px solid #eef; 225 | transform: translate(-50%, -50%); 226 | box-shadow: 2px 2px 4px -1px rgba(0, 0, 0, 0.25); 227 | } 228 | 229 | .model-body { 230 | height: 100%; 231 | line-height: 100px; 232 | text-align: center; 233 | } 234 | 235 | .model input { 236 | width: 220px; 237 | height: 30px; 238 | padding-left: 8px; 239 | border: 1px solid #ccc; 240 | border-radius: 8px; 241 | } 242 | 243 | .model input:focus { 244 | border: 1px solid #aaa; 245 | } 246 | --------------------------------------------------------------------------------