├── .babelrc ├── .editorconfig ├── .eslintrc ├── .gitignore ├── README.md ├── build ├── karma.conf.js ├── webpack.base.config.js ├── webpack.dev.config.js └── webpack.prod.config.js ├── index.html ├── package.json └── src ├── App.vue ├── assets ├── semantic.min.css ├── semantic.min.js ├── style.css └── themes │ ├── basic │ └── assets │ │ └── fonts │ │ ├── icons.eot │ │ ├── icons.svg │ │ ├── icons.ttf │ │ └── icons.woff │ └── default │ └── assets │ ├── fonts │ ├── icons.eot │ ├── icons.otf │ ├── icons.svg │ ├── icons.ttf │ ├── icons.woff │ └── icons.woff2 │ └── images │ └── flags.png ├── components ├── categoryModal.vue ├── editCategoryModal.vue ├── editNoteModal.vue ├── noteItem.vue ├── noteList.vue └── sideBar.vue ├── filters └── index.js ├── main.js └── store └── index.js /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["es2015", "stage-0"], 3 | "plugins": ["transform-runtime"] 4 | } 5 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | indent_style = space 5 | end_of_line = lf 6 | charset = utf-8 7 | trim_trailing_whitespace = true 8 | insert_final_newline = true 9 | 10 | [*.{vue,js,json,html,yml}] 11 | indent_style = space 12 | indent_size = 2 13 | 14 | [*.md] 15 | trim_trailing_whitespace = false 16 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "browser": true, 4 | "node": true 5 | }, 6 | 7 | "ecmaFeatures": { 8 | "arrowFunctions": true, 9 | "destructuring": true, 10 | "classes": true, 11 | "defaultParams": true, 12 | "blockBindings": true, 13 | "modules": true, 14 | "objectLiteralComputedProperties": true, 15 | "objectLiteralShorthandMethods": true, 16 | "objectLiteralShorthandProperties": true, 17 | "restParams": true, 18 | "spread": true, 19 | "templateStrings": true 20 | }, 21 | 22 | "rules": { 23 | "accessor-pairs": 2, 24 | "array-bracket-spacing": 0, 25 | "block-scoped-var": 0, 26 | "brace-style": [2, "1tbs", { "allowSingleLine": true }], 27 | "camelcase": 0, 28 | "comma-dangle": [2, "never"], 29 | "comma-spacing": [2, { "before": false, "after": true }], 30 | "comma-style": [2, "last"], 31 | "complexity": 0, 32 | "computed-property-spacing": 0, 33 | "consistent-return": 0, 34 | "consistent-this": 0, 35 | "constructor-super": 2, 36 | "curly": [2, "multi-line"], 37 | "default-case": 0, 38 | "dot-location": [2, "property"], 39 | "dot-notation": 0, 40 | "eol-last": 2, 41 | "eqeqeq": [2, "allow-null"], 42 | "func-names": 0, 43 | "func-style": 0, 44 | "generator-star-spacing": [2, { "before": true, "after": true }], 45 | "guard-for-in": 0, 46 | "handle-callback-err": [2, "^(err|error)$" ], 47 | "indent": [2, 2, { "SwitchCase": 1 }], 48 | "key-spacing": [2, { "beforeColon": false, "afterColon": true }], 49 | "linebreak-style": 0, 50 | "lines-around-comment": 0, 51 | "max-nested-callbacks": 0, 52 | "new-cap": [2, { "newIsCap": true, "capIsNew": false }], 53 | "new-parens": 2, 54 | "newline-after-var": 0, 55 | "no-alert": 0, 56 | "no-array-constructor": 2, 57 | "no-caller": 2, 58 | "no-catch-shadow": 0, 59 | "no-cond-assign": 2, 60 | "no-console": 0, 61 | "no-constant-condition": 0, 62 | "no-continue": 0, 63 | "no-control-regex": 2, 64 | "no-debugger": 2, 65 | "no-delete-var": 2, 66 | "no-div-regex": 0, 67 | "no-dupe-args": 2, 68 | "no-dupe-keys": 2, 69 | "no-duplicate-case": 2, 70 | "no-else-return": 0, 71 | "no-empty": 0, 72 | "no-empty-character-class": 2, 73 | "no-empty-label": 2, 74 | "no-eq-null": 0, 75 | "no-eval": 2, 76 | "no-ex-assign": 2, 77 | "no-extend-native": 2, 78 | "no-extra-bind": 2, 79 | "no-extra-boolean-cast": 2, 80 | "no-extra-parens": 0, 81 | "no-extra-semi": 0, 82 | "no-fallthrough": 2, 83 | "no-floating-decimal": 2, 84 | "no-func-assign": 2, 85 | "no-implied-eval": 2, 86 | "no-inline-comments": 0, 87 | "no-inner-declarations": [2, "functions"], 88 | "no-invalid-regexp": 2, 89 | "no-irregular-whitespace": 2, 90 | "no-iterator": 2, 91 | "no-label-var": 2, 92 | "no-labels": 2, 93 | "no-lone-blocks": 2, 94 | "no-lonely-if": 0, 95 | "no-loop-func": 0, 96 | "no-mixed-requires": 0, 97 | "no-mixed-spaces-and-tabs": 2, 98 | "no-multi-spaces": 2, 99 | "no-multi-str": 2, 100 | "no-multiple-empty-lines": [2, { "max": 1 }], 101 | "no-native-reassign": 2, 102 | "no-negated-in-lhs": 2, 103 | "no-nested-ternary": 0, 104 | "no-new": 2, 105 | "no-new-func": 0, 106 | "no-new-object": 2, 107 | "no-new-require": 2, 108 | "no-new-wrappers": 2, 109 | "no-obj-calls": 2, 110 | "no-octal": 2, 111 | "no-octal-escape": 2, 112 | "no-param-reassign": 0, 113 | "no-path-concat": 0, 114 | "no-process-env": 0, 115 | "no-process-exit": 0, 116 | "no-proto": 0, 117 | "no-redeclare": 2, 118 | "no-regex-spaces": 2, 119 | "no-restricted-modules": 0, 120 | "no-return-assign": 2, 121 | "no-script-url": 0, 122 | "no-self-compare": 2, 123 | "no-sequences": 2, 124 | "no-shadow": 0, 125 | "no-shadow-restricted-names": 2, 126 | "no-spaced-func": 2, 127 | "no-sparse-arrays": 2, 128 | "no-sync": 0, 129 | "no-ternary": 0, 130 | "no-this-before-super": 2, 131 | "no-throw-literal": 2, 132 | "no-trailing-spaces": 2, 133 | "no-undef": 2, 134 | "no-undef-init": 2, 135 | "no-undefined": 0, 136 | "no-underscore-dangle": 0, 137 | "no-unexpected-multiline": 2, 138 | "no-unneeded-ternary": 2, 139 | "no-unreachable": 2, 140 | "no-unused-expressions": 0, 141 | "no-unused-vars": [2, { "vars": "all", "args": "none" }], 142 | "no-use-before-define": 0, 143 | "no-var": 0, 144 | "no-void": 0, 145 | "no-warning-comments": 0, 146 | "no-with": 2, 147 | "object-curly-spacing": 0, 148 | "object-shorthand": 0, 149 | "one-var": [2, { "initialized": "never" }], 150 | "operator-assignment": 0, 151 | "operator-linebreak": [2, "after", { "overrides": { "?": "before", ":": "before" } }], 152 | "padded-blocks": 0, 153 | "prefer-const": 0, 154 | "quote-props": 0, 155 | "quotes": [2, "single", "avoid-escape"], 156 | "radix": 2, 157 | "semi": [2, "never"], 158 | "semi-spacing": 0, 159 | "sort-vars": 0, 160 | "space-after-keywords": [2, "always"], 161 | "space-before-blocks": [2, "always"], 162 | "space-before-function-paren": [2, "always"], 163 | "space-in-parens": [2, "never"], 164 | "space-infix-ops": 2, 165 | "space-return-throw-case": 2, 166 | "space-unary-ops": [2, { "words": true, "nonwords": false }], 167 | "spaced-comment": [2, "always", { "markers": ["global", "globals", "eslint", "eslint-disable", "*package", "!"] }], 168 | "strict": 0, 169 | "use-isnan": 2, 170 | "valid-jsdoc": 0, 171 | "valid-typeof": 2, 172 | "vars-on-top": 0, 173 | "wrap-iife": [2, "any"], 174 | "wrap-regex": 0, 175 | "yoda": [2, "never"] 176 | } 177 | } 178 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | dist -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # vue-note-firebase-app 2 | 一个基于vue.js和Firebase制作的笔记spa(PC端). 3 | 4 | 使用vue.js组件开发模式,将spa分为5个component进行开发,基本使用到了vue.js事件通信、过滤器等功能,同时使用Firebase作为后台数据存储端,实现了跨平台数据同步。 5 | 6 | 目前该spa已经可以实现标签分类、标签\笔记删除、添加以及编辑等基本功能。 7 | 8 | 本项目有mobile端版本,请移步[vue-vueRouter-note-Firebase-mobile](https://github.com/Geocld/vue-vueRouter-note-Firebase-mobile) 9 | 10 | 在线[demo](http://geocld.github.io/demo/pc-note/index.html) 11 | 12 | #技术栈 13 | 14 | 框架:[vue.js](http://cn.vuejs.org/) 15 | 16 | 后台数据同步:[Firebse](https://www.firebase.com/) 17 | 18 | UI库:[Semantic UI](http://www.semantic-ui.cn/) 19 | 20 | #项目安装 21 | 1、安装项目依赖 22 | 23 | npm install 24 | 25 | 2、发开模式下运行项目 26 | 27 | npm run dev 28 | 29 | 3、项目正式文件发布 30 | 31 | npm run build 32 | 33 | #效果预览 34 | ![](http://i.imgur.com/I2KkSfi.png) 35 | 36 | #TODO 37 | 增加笔记根据日历排序功能 38 | 39 | 登陆认证功能 -------------------------------------------------------------------------------- /build/karma.conf.js: -------------------------------------------------------------------------------- 1 | // we can just use the exact same webpack config by requiring it 2 | // but make sure to delete the normal entry 3 | var webpackConf = require('./webpack.base.config') 4 | delete webpackConf.entry 5 | 6 | module.exports = function (config) { 7 | config.set({ 8 | browsers: ['PhantomJS'], 9 | frameworks: ['jasmine'], 10 | reporters: ['spec'], 11 | // this is the entry file for all our tests. 12 | files: ['../test/unit/index.js'], 13 | // we will pass the entry file to webpack for bundling. 14 | preprocessors: { 15 | '../test/unit/index.js': ['webpack'] 16 | }, 17 | webpack: webpackConf, 18 | webpackMiddleware: { 19 | noInfo: true 20 | }, 21 | singleRun: true 22 | }) 23 | } 24 | -------------------------------------------------------------------------------- /build/webpack.base.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | entry: './src/main.js', 3 | output: { 4 | path: './dist', 5 | publicPath: 'dist/', 6 | filename: 'build.js' 7 | }, 8 | module: { 9 | loaders: [ 10 | { 11 | test: /\.vue$/, 12 | loader: 'vue' 13 | }, 14 | { 15 | test: /\.js$/, 16 | //loader: 'babel!eslint', 17 | loader: 'babel', 18 | // make sure to exclude 3rd party code in node_modules 19 | exclude: /node_modules/ 20 | }, 21 | { 22 | // edit this for additional asset file types 23 | test: /\.(png|jpg|gif)$/, 24 | loader: 'url', 25 | query: { 26 | // inline files smaller then 10kb as base64 dataURL 27 | limit: 10000, 28 | // fallback to file-loader with this naming scheme 29 | name: '[name].[ext]?[hash]' 30 | } 31 | } 32 | ] 33 | }, 34 | // vue-loader config: 35 | // lint all JavaScript inside *.vue files with ESLint 36 | // make sure to adjust your .eslintrc 37 | vue: { 38 | loaders: { 39 | //js: 'babel!eslint' 40 | js: 'babel' 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /build/webpack.dev.config.js: -------------------------------------------------------------------------------- 1 | var config = require('./webpack.base.config') 2 | 3 | config.devtool = '#eval-source-map' 4 | 5 | config.devServer = { 6 | noInfo: true 7 | } 8 | 9 | module.exports = config 10 | -------------------------------------------------------------------------------- /build/webpack.prod.config.js: -------------------------------------------------------------------------------- 1 | var webpack = require('webpack') 2 | var config = require('./webpack.base.config') 3 | 4 | config.plugins = (config.plugins || []).concat([ 5 | // this allows uglify to strip all warnings 6 | // from Vue.js source code. 7 | new webpack.DefinePlugin({ 8 | 'process.env': { 9 | NODE_ENV: '"production"' 10 | } 11 | }), 12 | // This minifies not only JavaScript, but also 13 | // the templates (with html-minifier) and CSS (with cssnano)! 14 | new webpack.optimize.UglifyJsPlugin({ 15 | compress: { 16 | warnings: false 17 | } 18 | }), 19 | new webpack.optimize.OccurenceOrderPlugin() 20 | ]) 21 | 22 | module.exports = config 23 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | note app 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vue-note-Firebase", 3 | "version": "1.0.0", 4 | "description": "A note app use vue.js and Firebase", 5 | "main": "index.js", 6 | "scripts": { 7 | "dev": "webpack-dev-server --inline --hot --config build/webpack.dev.config.js", 8 | "build": "webpack --progress --hide-modules --config build/webpack.prod.config.js", 9 | "test": "karma start build/karma.conf.js" 10 | }, 11 | "author": "lijiahao", 12 | "license": "ISC", 13 | "dependencies": { 14 | "firebase": "^2.4.2", 15 | "jquery": "^2.2.2", 16 | "moment": "^2.13.0", 17 | "vue": "^1.0.16" 18 | }, 19 | "devDependencies": { 20 | "babel-core": "^6.1.2", 21 | "babel-loader": "^6.1.0", 22 | "babel-plugin-transform-runtime": "^6.1.2", 23 | "babel-preset-es2015": "^6.1.2", 24 | "babel-preset-stage-0": "^6.1.2", 25 | "babel-runtime": "^5.8.0", 26 | "css-loader": "^0.23.0", 27 | "eslint": "^1.10.3", 28 | "eslint-loader": "^1.3.0", 29 | "file-loader": "^0.8.4", 30 | "function-bind": "^1.0.2", 31 | "inject-loader": "^2.0.1", 32 | "jade": "^1.11.0", 33 | "jasmine-core": "^2.4.1", 34 | "karma": "^0.13.15", 35 | "karma-jasmine": "^0.3.6", 36 | "karma-phantomjs-launcher": "^0.2.1", 37 | "karma-spec-reporter": "0.0.23", 38 | "karma-webpack": "^1.7.0", 39 | "phantomjs": "^1.9.19", 40 | "stylus-loader": "^1.4.0", 41 | "template-html-loader": "0.0.3", 42 | "url-loader": "^0.5.7", 43 | "vue-hot-reload-api": "^1.2.0", 44 | "vue-html-loader": "^1.0.0", 45 | "vue-loader": "^8.0.0", 46 | "vue-style-loader": "^1.0.0", 47 | "webpack": "^1.12.2", 48 | "webpack-dev-server": "^1.12.0" 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/App.vue: -------------------------------------------------------------------------------- 1 | 7 | 8 | 44 | -------------------------------------------------------------------------------- /src/assets/style.css: -------------------------------------------------------------------------------- 1 | @import url(https://fonts.googleapis.com/css?family=Raleway:400,300); 2 | body { 3 | margin: 0; 4 | padding: 0; 5 | border: 0; 6 | overflow: hidden; 7 | height: 100%; 8 | max-height: 100%; 9 | } 10 | 11 | .right-float { 12 | float: right; 13 | } 14 | 15 | .selected { 16 | color: #87568D; 17 | } 18 | 19 | .clickable { 20 | opacity: 1; 21 | -webkit-transition: opacity .25s ease-in-out; 22 | transition: opacity .25s ease-in-out; 23 | } 24 | 25 | .clickable:hover { 26 | cursor: pointer; 27 | opacity: 0.5; 28 | } 29 | 30 | #categories button { 31 | position: absolute; 32 | bottom: 15px; 33 | right: 15px; 34 | } 35 | 36 | .container { 37 | margin: 15px; 38 | } 39 | 40 | i.remove.icon { 41 | opacity: 0; 42 | -webkit-transition: opacity .25s ease-in-out; 43 | transition: opacity .25s ease-in-out; 44 | } 45 | 46 | i.write.icon { 47 | opacity: 0; 48 | -webkit-transition: opacity .25s ease-in-out; 49 | transition: opacity .25s ease-in-out; 50 | } 51 | 52 | div.content:hover i.write.icon { 53 | opacity: 1; 54 | } 55 | 56 | div.content:hover i.remove.icon { 57 | opacity: 1; 58 | } 59 | 60 | #links-container { 61 | position: fixed; 62 | top: 0; 63 | left: 300px; 64 | right: 0; 65 | bottom: 0; 66 | overflow: auto; 67 | background-color: #D4D9DA; 68 | color: #5F676A; 69 | } 70 | 71 | #links-container .list { 72 | margin-top: 0px; 73 | } 74 | 75 | #toolbar { 76 | background-color: #D4D9DA; 77 | border-bottom: 1px; 78 | border-bottom-style: solid; 79 | border-bottom-color: #C2C7CA; 80 | height: 60px; 81 | padding-top: 10px; 82 | padding-left: 30px; 83 | padding-right: 30px; 84 | } 85 | 86 | #links-container .list .item { 87 | padding: 15px; 88 | } 89 | 90 | .item .description { 91 | margin-top: 5px; 92 | } 93 | 94 | i.remove.icon { 95 | opacity: 0; 96 | -webkit-transition: opacity .25s ease-in-out; 97 | transition: opacity .25s ease-in-out; 98 | } 99 | 100 | div.content:hover i.remove.icon { 101 | opacity: 0.5; 102 | } 103 | -------------------------------------------------------------------------------- /src/assets/themes/basic/assets/fonts/icons.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Geocld/vue-note-firebase-app/7e9b9add1617bd107dc73a26b0c13521d8fcc134/src/assets/themes/basic/assets/fonts/icons.eot -------------------------------------------------------------------------------- /src/assets/themes/basic/assets/fonts/icons.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Created by FontForge 20100429 at Thu Sep 20 22:09:47 2012 6 | By root 7 | Copyright (C) 2012 by original authors @ fontello.com 8 | 9 | 10 | 11 | 24 | 26 | 28 | 30 | 32 | 35 | 37 | 41 | 44 | 47 | 49 | 51 | 53 | 55 | 57 | 59 | 61 | 63 | 65 | 68 | 71 | 74 | 76 | 80 | 86 | 89 | 91 | 101 | 103 | 105 | 108 | 110 | 112 | 115 | 118 | 121 | 123 | 125 | 127 | 129 | 131 | 133 | 135 | 137 | 140 | 142 | 146 | 149 | 153 | 158 | 161 | 163 | 165 | 169 | 172 | 174 | 178 | 181 | 184 | 191 | 193 | 196 | 199 | 203 | 206 | 209 | 213 | 217 | 219 | 221 | 223 | 225 | 228 | 231 | 234 | 237 | 240 | 243 | 245 | 247 | 250 | 253 | 255 | 258 | 262 | 264 | 266 | 268 | 270 | 273 | 275 | 278 | 283 | 289 | 292 | 295 | 299 | 301 | 304 | 307 | 311 | 315 | 317 | 322 | 325 | 329 | 334 | 341 | 344 | 347 | 351 | 354 | 358 | 362 | 367 | 372 | 377 | 380 | 385 | 388 | 392 | 398 | 401 | 403 | 409 | 411 | 413 | 418 | 422 | 425 | 428 | 431 | 434 | 436 | 440 | 443 | 446 | 449 | 450 | 451 | -------------------------------------------------------------------------------- /src/assets/themes/basic/assets/fonts/icons.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Geocld/vue-note-firebase-app/7e9b9add1617bd107dc73a26b0c13521d8fcc134/src/assets/themes/basic/assets/fonts/icons.ttf -------------------------------------------------------------------------------- /src/assets/themes/basic/assets/fonts/icons.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Geocld/vue-note-firebase-app/7e9b9add1617bd107dc73a26b0c13521d8fcc134/src/assets/themes/basic/assets/fonts/icons.woff -------------------------------------------------------------------------------- /src/assets/themes/default/assets/fonts/icons.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Geocld/vue-note-firebase-app/7e9b9add1617bd107dc73a26b0c13521d8fcc134/src/assets/themes/default/assets/fonts/icons.eot -------------------------------------------------------------------------------- /src/assets/themes/default/assets/fonts/icons.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Geocld/vue-note-firebase-app/7e9b9add1617bd107dc73a26b0c13521d8fcc134/src/assets/themes/default/assets/fonts/icons.otf -------------------------------------------------------------------------------- /src/assets/themes/default/assets/fonts/icons.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Geocld/vue-note-firebase-app/7e9b9add1617bd107dc73a26b0c13521d8fcc134/src/assets/themes/default/assets/fonts/icons.ttf -------------------------------------------------------------------------------- /src/assets/themes/default/assets/fonts/icons.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Geocld/vue-note-firebase-app/7e9b9add1617bd107dc73a26b0c13521d8fcc134/src/assets/themes/default/assets/fonts/icons.woff -------------------------------------------------------------------------------- /src/assets/themes/default/assets/fonts/icons.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Geocld/vue-note-firebase-app/7e9b9add1617bd107dc73a26b0c13521d8fcc134/src/assets/themes/default/assets/fonts/icons.woff2 -------------------------------------------------------------------------------- /src/assets/themes/default/assets/images/flags.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Geocld/vue-note-firebase-app/7e9b9add1617bd107dc73a26b0c13521d8fcc134/src/assets/themes/default/assets/images/flags.png -------------------------------------------------------------------------------- /src/components/categoryModal.vue: -------------------------------------------------------------------------------- 1 | 29 | 30 | 70 | -------------------------------------------------------------------------------- /src/components/editCategoryModal.vue: -------------------------------------------------------------------------------- 1 | 29 | 30 | 72 | -------------------------------------------------------------------------------- /src/components/editNoteModal.vue: -------------------------------------------------------------------------------- 1 | 35 | 36 | 97 | -------------------------------------------------------------------------------- /src/components/noteItem.vue: -------------------------------------------------------------------------------- 1 | 13 | 14 | 26 | -------------------------------------------------------------------------------- /src/components/noteList.vue: -------------------------------------------------------------------------------- 1 | 24 | 25 | 70 | -------------------------------------------------------------------------------- /src/components/sideBar.vue: -------------------------------------------------------------------------------- 1 | 104 | 143 | 144 | 186 | -------------------------------------------------------------------------------- /src/filters/index.js: -------------------------------------------------------------------------------- 1 | export function filterBytitle (value, title) { 2 | return filternotes(value, 'title', title); 3 | } 4 | 5 | export function filterByCategory (value, category) { 6 | if (!category) return value 7 | return filternotes(value, 'category', category) 8 | } 9 | 10 | 11 | //helper 12 | function filternotes (notes, filterBy, filterValue) { 13 | var filteredNotes = {}; 14 | for (var note in notes) { 15 | if (notes[note][filterBy].indexOf(filterValue) > -1) { 16 | filteredNotes[note] = notes[note]; 17 | } 18 | } 19 | return filteredNotes; 20 | } -------------------------------------------------------------------------------- /src/main.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import app from './App.vue' 3 | 4 | new Vue({ 5 | el: 'body', 6 | components: { app } 7 | }); 8 | -------------------------------------------------------------------------------- /src/store/index.js: -------------------------------------------------------------------------------- 1 | import { EventEmitter } from 'events' 2 | import Firebase from 'firebase' 3 | 4 | //实例化Firebase 5 | const db = new Firebase("https://geocld-app1.firebaseio.com/") 6 | //获取categories和notes的目录链接 7 | const categoriesRef = db.child('categories') 8 | const notesRef = db.child('notes') 9 | 10 | //实例化EventEmitter事件触发器 11 | const store = new EventEmitter() 12 | 13 | let categories = {} 14 | let notes = {} 15 | 16 | export default store 17 | 18 | db.on('value', (snapshot) => { 19 | var noteData = snapshot.val(); 20 | if (noteData) { 21 | categories = noteData.categories; 22 | notes = noteData.notes; 23 | //当数据库categories和notes更新时出发data-updated事件 24 | store.emit('data-updated', categories, notes); 25 | } 26 | }) 27 | 28 | store.addCategory = (category) => { 29 | categoriesRef.update(category) 30 | } 31 | 32 | store.editCategory = (category, category_name, old_name) => { 33 | if (category_name === old_name) { 34 | categoriesRef.child(category_name).set(category[category_name]) 35 | } 36 | else { 37 | categoriesRef.update(category); 38 | for (var key in notes) { 39 | if (notes[key].category === old_name) { 40 | notesRef.child(key).update({category: category_name}) 41 | } 42 | } 43 | categoriesRef.child(old_name).remove(); 44 | } 45 | } 46 | 47 | store.deleteCategory = (catName) => { 48 | // first check if an 'Uncategorized' category exists, if not, create it 49 | if (!('Uncategorized' in categories)) { 50 | categoriesRef.update({'Uncategorized': 'white'}) 51 | } 52 | 53 | for (var key in notes) { 54 | if (notes[key].category === catName) { 55 | notesRef.child(key).update({category: 'Uncategorized'}) 56 | } 57 | } 58 | categoriesRef.child(catName).remove() 59 | } 60 | 61 | store.editNote = (noteId, content) => { 62 | notesRef.child(noteId).update(content); 63 | } 64 | 65 | store.addNote = (note) => { 66 | notesRef.push(note); 67 | } 68 | 69 | store.deleteNote = (noteId) => { 70 | notesRef.child(noteId).remove(); 71 | } --------------------------------------------------------------------------------