├── .eslintignore ├── .eslintrc.js ├── .gitignore ├── LICENSE ├── README.md ├── components ├── App.vue ├── Editor.vue ├── NotesList.vue └── Toolbar.vue ├── index.html ├── main.js ├── package.json ├── static └── build.js ├── styles.css ├── vuex ├── actions.js └── store.js └── webpack.config.js /.eslintignore: -------------------------------------------------------------------------------- 1 | node_modules/ -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | // https://github.com/feross/standard/blob/master/RULES.md#javascript-standard-style 4 | extends: 'standard', 5 | // required to lint *.vue files 6 | plugins: [ 7 | 'html' 8 | ], 9 | // add your custom rules here 10 | 'rules': { 11 | // allow paren-less arrow functions 12 | 'arrow-parens': 0, 13 | 'no-undef': 0, 14 | 'one-var': 0, 15 | // allow debugger during development 16 | 'no-debugger': process.env.NODE_ENV === 'production' ? 2 : 0 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | 6 | # Runtime data 7 | pids 8 | *.pid 9 | *.seed 10 | 11 | # Directory for instrumented libs generated by jscoverage/JSCover 12 | lib-cov 13 | 14 | # Coverage directory used by tools like istanbul 15 | coverage 16 | 17 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 18 | .grunt 19 | 20 | # node-waf configuration 21 | .lock-wscript 22 | 23 | # Compiled binary addons (http://nodejs.org/api/addons.html) 24 | build/Release 25 | 26 | # Dependency directory 27 | node_modules 28 | 29 | # Optional npm cache directory 30 | .npm 31 | 32 | # Optional REPL history 33 | .node_repl_history 34 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 coligo 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Firebase + Vuex 构建 Notes App 2 | 3 | 之前翻译了基于博客 [coligo](http://coligo.io/learn-vuex-by-building-notes-app/) 的文章:[用 Vuex 构建一个笔记应用](https://segmentfault.com/a/1190000005015164),这次在此基础上做了一点更新: 4 | 5 | * 把数据放在 Firebase 上,不会每次关掉浏览器就丢失数据 6 | * 添加了笔记检索功能 7 | * 为了保证代码整洁,加上了 eslint 8 | * more... 9 | 10 | 在运行之前,记得把 store.js 里面的数据引用改成你自己账号的链接。 11 | 12 | ```js 13 | // 改一下数据应用 14 | let notesRef = new Firebase('https://crackling-inferno-296.firebaseio.com/notes') 15 | ``` 16 | 17 | ### Install the dependencies 18 | 19 | ```bash 20 | npm install 21 | ``` 22 | 23 | ### Run the dev server with hot reload at localhost:8080 24 | 25 | ```bash 26 | npm run dev 27 | ``` 28 | 29 | ### Build the app for production 30 | 31 | ```bash 32 | npm run build 33 | ``` 34 | -------------------------------------------------------------------------------- /components/App.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 22 | -------------------------------------------------------------------------------- /components/Editor.vue: -------------------------------------------------------------------------------- 1 | 10 | 11 | 25 | -------------------------------------------------------------------------------- /components/NotesList.vue: -------------------------------------------------------------------------------- 1 | 46 | 47 | 95 | -------------------------------------------------------------------------------- /components/Toolbar.vue: -------------------------------------------------------------------------------- 1 | 10 | 11 | 27 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Notes | coligo.io 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /main.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import store from './vuex/store' 3 | import App from './components/App.vue' 4 | 5 | /* eslint-disable */ 6 | new Vue({ 7 | store, // inject store to all children 8 | el: 'body', 9 | components: { App } 10 | }) 11 | /* eslint-disable */ -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "note-app-vuejs-vuex", 3 | "version": "1.0.0", 4 | "description": "A notes application built using VueJs and Vuex", 5 | "main": "index.js", 6 | "repository": { 7 | "type": "git", 8 | "url": "https://github.com/coligo-io/notes-app-vuejs-vuex.git" 9 | }, 10 | "scripts": { 11 | "dev": "webpack-dev-server --inline --hot", 12 | "build": "webpack -p" 13 | }, 14 | "keywords": [ 15 | "vuejs", 16 | "vuex", 17 | "notes" 18 | ], 19 | "author": "Fady Makram", 20 | "license": "MIT", 21 | "devDependencies": { 22 | "babel-core": "^6.7.6", 23 | "babel-loader": "^6.2.4", 24 | "babel-plugin-transform-runtime": "^6.7.5", 25 | "babel-preset-es2015": "^6.6.0", 26 | "babel-runtime": "^5.8.38", 27 | "css-loader": "^0.23.1", 28 | "eslint": "^2.0.0", 29 | "eslint-config-standard": "^5.1.0", 30 | "eslint-friendly-formatter": "^1.2.2", 31 | "eslint-loader": "^1.3.0", 32 | "eslint-plugin-html": "^1.3.0", 33 | "eslint-plugin-promise": "^1.0.8", 34 | "eslint-plugin-standard": "^1.3.2", 35 | "vue-hot-reload-api": "^1.3.2", 36 | "vue-html-loader": "^1.2.2", 37 | "vue-loader": "^8.2.3", 38 | "vue-style-loader": "^1.0.0", 39 | "webpack": "^1.12.15", 40 | "webpack-dev-server": "^1.14.1" 41 | }, 42 | "dependencies": { 43 | "vue": "^1.0.21", 44 | "vuex": "^0.6.2", 45 | "firebase": "^2.4.2" 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /styles.css: -------------------------------------------------------------------------------- 1 | @import url(https://fonts.googleapis.com/css?family=Raleway:400,300); 2 | 3 | html, #app { 4 | height: 100%; 5 | } 6 | 7 | body { 8 | margin: 0; 9 | padding: 0; 10 | border: 0; 11 | height: 100%; 12 | max-height: 100%; 13 | position: relative; 14 | } 15 | 16 | #toolbar { 17 | float: left; 18 | width: 80px; 19 | height: 100%; 20 | background-color: #30414D; 21 | color: #767676; 22 | padding: 35px 25px 25px 25px; 23 | } 24 | 25 | #notes-list { 26 | float: left; 27 | width: 300px; 28 | height: 100%; 29 | background-color: #F5F5F5; 30 | font-family: 'Raleway', sans-serif; 31 | font-weight: 400; 32 | } 33 | 34 | input { 35 | margin-bottom: 20px; 36 | width: 100%; 37 | border-radius: 4px; 38 | line-height: 25px; 39 | } 40 | 41 | #notes-list .input{ 42 | width: 80%; 43 | margin: auto; 44 | text-align: center; 45 | } 46 | 47 | #list-header { 48 | padding: 5px 25px 25px 25px; 49 | } 50 | 51 | #list-header h2 { 52 | font-weight: 300; 53 | text-transform: uppercase; 54 | text-align: center; 55 | font-size: 22px; 56 | padding-bottom: 8px; 57 | } 58 | 59 | #notes-list .container { 60 | height: calc(100% - 137px); 61 | max-height: calc(100% - 137px); 62 | overflow: auto; 63 | width: 100%; 64 | padding: 0; 65 | } 66 | 67 | #notes-list .container .list-group-item { 68 | /*border: 0;*/ 69 | border-radius: 0; 70 | } 71 | 72 | .list-group-item { 73 | border-bottom: 1px solid #d4d4d4; 74 | } 75 | 76 | .list-group-item-heading { 77 | font-weight: 300; 78 | font-size: 15px; 79 | } 80 | 81 | #note-editor { 82 | height: 100%; 83 | margin-left: 380px; 84 | } 85 | 86 | #note-editor textarea { 87 | height: 100%; 88 | border: 0; 89 | border-radius: 0; 90 | } 91 | 92 | #toolbar i { 93 | font-size: 30px; 94 | margin-bottom: 35px; 95 | cursor: pointer; 96 | opacity: 0.8; 97 | transition: opacity 0.5s ease; 98 | } 99 | 100 | #toolbar i:hover { 101 | opacity: 1; 102 | } 103 | 104 | .starred { 105 | color: #F7AE4F; 106 | } 107 | -------------------------------------------------------------------------------- /vuex/actions.js: -------------------------------------------------------------------------------- 1 | export const addNote = ({ dispatch }) => { 2 | dispatch('ADD_NOTE') 3 | } 4 | 5 | export const editNote = ({ dispatch }, e) => { 6 | dispatch('EDIT_NOTE', e.target.value) 7 | } 8 | 9 | export const deleteNote = ({ dispatch }) => { 10 | dispatch('DELETE_NOTE') 11 | } 12 | 13 | export const updateActiveNote = ({ dispatch }, key, note) => { 14 | dispatch('SET_ACTIVE_NOTE', key, note) 15 | } 16 | 17 | export const toggleFavorite = ({ dispatch }) => { 18 | dispatch('TOGGLE_FAVORITE') 19 | } 20 | -------------------------------------------------------------------------------- /vuex/store.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import Vuex from 'vuex' 3 | import Firebase from 'firebase' 4 | 5 | Vue.use(Vuex) 6 | 7 | let notesRef = new Firebase('https://crackling-inferno-296.firebaseio.com/notes') 8 | 9 | notesRef.on('value', snapshot => { 10 | state.notes = snapshot.val() 11 | }) 12 | 13 | const state = { 14 | notes: {}, 15 | activeNote: {}, 16 | activeKey: '' 17 | } 18 | 19 | const mutations = { 20 | ADD_NOTE (state) { 21 | const newNote = { 22 | text: 'New note', 23 | favorite: false 24 | } 25 | var addRef = notesRef.push() 26 | state.activeKey = addRef.key() 27 | addRef.set(newNote) 28 | state.activeNote = newNote 29 | }, 30 | 31 | EDIT_NOTE (state, text) { 32 | notesRef.child(state.activeKey).update({ 33 | 'text': text 34 | }) 35 | }, 36 | 37 | DELETE_NOTE (state) { 38 | // notesRef.(state.activeNote) 39 | notesRef.child(state.activeKey).set(null) 40 | // state.activeNote = state.notes[0] 41 | }, 42 | 43 | TOGGLE_FAVORITE (state) { 44 | state.activeNote.favorite = !state.activeNote.favorite 45 | notesRef.child(state.activeKey).update({ 46 | 'favorite': state.activeNote.favorite 47 | }) 48 | // state.activeNote.favorite = !state.activeNote.favorite 49 | }, 50 | 51 | SET_ACTIVE_NOTE (state, key, note) { 52 | state.activeNote = note 53 | state.activeKey = key 54 | } 55 | } 56 | 57 | export default new Vuex.Store({ 58 | state, 59 | mutations 60 | }) 61 | -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | entry: './main.js', 3 | output: { 4 | path: './static', 5 | publicPath: '/static/', 6 | filename: 'build.js' 7 | }, 8 | module: { 9 | preLoaders: [{ 10 | test: /\.vue$/, 11 | loader: 'eslint' 12 | }, { 13 | test: /\.js$/, 14 | loader: 'eslint' 15 | }], 16 | loaders: [{ 17 | test: /\.js$/, 18 | loader: 'babel', 19 | exclude: /node_modules/ 20 | }, { 21 | test: /\.vue$/, 22 | loader: 'vue' 23 | }] 24 | }, 25 | babel: { 26 | presets: ['es2015'], 27 | plugins: ['transform-runtime'] 28 | }, 29 | eslint: { 30 | formatter: require('eslint-friendly-formatter') 31 | }, 32 | devtools: '#source-map' 33 | } 34 | --------------------------------------------------------------------------------