Vuex Structure (#8054)

* wip: vuex structure

* add missing files

* client: do not fail dev build on eslint error

* eslint does not block compilation, mount app when data is ready

* eslintrc.js -> eslintrc
This commit is contained in:
Matteo Pagliazzi
2016-09-23 19:49:11 +02:00
committed by GitHub
parent 5480157977
commit d3371e323e
12 changed files with 102 additions and 10 deletions

View File

@@ -13,8 +13,8 @@
"async": "^1.5.0",
"autoprefixer": "^6.4.0",
"aws-sdk": "^2.0.25",
"babel-loader": "^6.0.0",
"babel-core": "^6.0.0",
"babel-loader": "^6.0.0",
"babel-plugin-transform-async-to-module-method": "^6.8.0",
"babel-polyfill": "^6.6.1",
"babel-preset-es2015": "^6.6.0",
@@ -108,6 +108,7 @@
"vue": "^2.0.0-rc.6",
"vue-hot-reload-api": "^1.2.0",
"vue-loader": "^9.4.0",
"vue-resource": "^1.0.2",
"vue-router": "^2.0.0-rc.5",
"vuex": "^2.0.0-rc.5",
"vuex-router-sync": "^3.0.0",

View File

@@ -1,6 +1,6 @@
/* eslint-disable */
require('eventsource-polyfill')
var hotClient = require('webpack-hot-middleware/client?noInfo=true&reload=true')
var hotClient = require('webpack-hot-middleware/client?noInfo=true&reload=true&overlay=false')
hotClient.subscribe(function (event) {
if (event.action === 'reload') {

View File

@@ -86,6 +86,7 @@ var baseConfig = {
if (!IS_PROD) {
baseConfig.eslint = {
formatter: require('eslint-friendly-formatter'),
emitWarning: true,
};
}
module.exports = baseConfig;

View File

@@ -23,7 +23,6 @@ module.exports = merge(baseWebpackConfig, {
// https://github.com/glenjamin/webpack-hot-middleware#installation--usage
new webpack.optimize.OccurenceOrderPlugin(),
new webpack.HotModuleReplacementPlugin(),
new webpack.NoErrorsPlugin(),
// https://github.com/ampedandwired/html-webpack-plugin
new HtmlWebpackPlugin({
filename: 'index.html',

View File

@@ -6,5 +6,4 @@
"plugins": [
"html"
]
}
}

View File

@@ -1,6 +1,7 @@
<template lang="pug">
#app
site-header
p Welcome back {{user.profile.name}}
ul
li
router-link(to='/') Home
@@ -11,15 +12,35 @@
<script>
import SiteHeader from './siteHeader';
import { mapState } from 'vuex';
export default {
components: {
SiteHeader,
},
computed: mapState(['user']),
};
</script>
<style>
html, body {
width: 100%;
height: 100%;
margin: 0;
padding: 0;
}
#loading-screen { /* outside Vue because can't wait for rendering to finish */
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
background: #fff;
z-index: 10001;
}
#app {
margin: 0 auto;
width: 80%;

View File

@@ -1,6 +1,7 @@
<template lang="pug">
#app
site-header
p Welcome back {{user.profile.name}}
ul
li
router-link(to='/') Home
@@ -11,15 +12,35 @@
<script>
import SiteHeader from './siteHeader';
import { mapState } from 'vuex';
export default {
components: {
SiteHeader,
},
computed: mapState(['user']),
};
</script>
<style>
html, body {
width: 100%;
height: 100%;
margin: 0;
padding: 0;
}
#loading-screen { /* outside Vue because can't wait for rendering to finish */
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
background: #fff;
z-index: 10001;
}
#app {
margin: 0 auto;
width: 80%;

View File

@@ -5,6 +5,8 @@
<title>Habitica</title>
</head>
<body>
<!-- #loading-screen needs to be rendered before vue, will be deleted once app is loaded -->
<div id="loading-screen">Loading...</div>
<div id="app"></div>
<!-- built files will be auto injected -->
</body>

View File

@@ -4,16 +4,37 @@ require('babel-polyfill');
import Vue from 'vue';
import VuexRouterSync from 'vuex-router-sync';
import App from './components/app';
import VueResource from 'vue-resource';
import AppComponent from './components/app';
import router from './router';
import store from './vuex/store';
Vue.use(VueResource);
Vue.http.headers.common['x-api-user'] = '';
Vue.http.headers.common['x-api-key'] = '';
// Sync Vuex and Router
VuexRouterSync.sync(store, router);
new Vue({ // eslint-disable-line no-new
const app = new Vue({ // eslint-disable-line no-new
router,
store,
el: '#app',
render: h => h(App),
});
render: h => h(AppComponent),
mounted () { // Remove the loading screen when the app is mounted
let loadingScreen = document.getElementById('loading-screen');
if (loadingScreen) document.body.removeChild(loadingScreen);
},
});
// Setup listener for title that is outside Vue's scope
store.watch(state => state.title, (title) => {
document.title = title;
});
// Mount the app when the user is loaded
let userWatcher = store.watch(state => state.user, (user) => {
if (user && user._id) {
userWatcher(); // remove the watcher
app.$mount('#app');
}
});

View File

@@ -0,0 +1,15 @@
import Vue from 'vue';
export function setTitle (store, title) {
store.commit('SET_TITLE', title);
}
export function fetchUser (store) {
let promise = Vue.http.get('/api/v3/user');
promise.then(response => {
store.commit('SET_USER', response.body.data);
});
return promise;
}

View File

@@ -0,0 +1,7 @@
export function SET_TITLE (state, title) {
state.title = title;
}
export function SET_USER (state, userJson) {
state.user = userJson;
}

View File

@@ -1,12 +1,17 @@
import Vue from 'vue';
import Vuex from 'vuex';
import * as mutations from './mutations';
import * as actions from './actions';
Vue.use(Vuex);
const state = {
title: 'Habitica',
user: {},
};
export default new Vuex.Store({
state,
mutations,
actions,
});