本文基于工作项目开发,做的整理笔记
因工作需要,项目框架由最初的Java/jsp模式,逐渐转移成node/express模式。现在新项目又因为业务流程中的交互操作,会使页面dom根据数据data不断显示变化,便觉得此时是否是最佳实际,应该尝试一下vue框架。因为之前也偷偷的进行了一些vue框架的踩坑工作,已经填了一些坑或者有一些解决方案了,这也才敢用上。依然由后台Java提供API。本文就是做个笔记,说明如何使用Vue官方脚手架开始构建项目。
前提条件:
你已经听过、了解过Vue,至少一点点。
编码环境:
系统:OS X EI Capitan
版本:10.12.2
共2篇:
上篇:http://www.jianshu.com/p/ee2464501c65
下篇:http://www.jianshu.com/p/9baa03eb31fc(当前)
目录
| - 0.传送门
| - 1.安装
| - 2.项目初始化
| - 3.项目构建
| - Step1.阅读结构
| - Step2. 阅读代码(泛读)
| - 4.项目实操
| - Step1. 修改eslint配置
| - Step2. 调整结构
| - Step3. 添加登陆页面
| - Step4. 模版嵌套
| - (上下篇分割线)
| - Step5. 引入mockjs独立开发
| - Step6. 调用API接口
| - Step7. 状态管理(store仓库)
| - Step8. 抽离公共方法
| - Step9. 剥离组件
| - Finish. 生辰打包
| - 5.项目部署
| - a)本地部署
| - b)服务器部署
| - 6.结束
Step5. 引入mockjs独立开发
在前后端分离的开发中,为了不因为后端接口还没有弄好,前端开发处于Waiting状态,我们引入mock.js实现假数据接口,从而完成整个页面逻辑流程。
关于mock.js的知识,可以浏览官网http://mockjs.com/。
我们这里准备拿登录接口的请求做实验。
先去./src/api
文件夹下创建login.js
文件,代码如下所示:
vue-demo
| -
| - src
| - api
| - login.js (新增)
| -
| -
# ./src/api/login.js
import { fetch } from '@/utils/fetch'; //@表示的含义还记得是在webpack里定义的
export function loginByEmail(email, password) {
const data = {
email,
password
};
return fetch({
url: '/login/loginbyemail',
method: 'post',
params: data
});
}
export function logout() {
return fetch({
url: '/login/logout',
method: 'post'
});
}
发现代码里引用了一个公共方法,暂时还没有这个文件和方法,我们这就去./src/utils
文件夹下创建fetch.js
文件,代码如下所示:
vue-demo
| -
| - src
| -
| - utils
| - fetch.js (新增)
| -
| -
import axios from 'axios';
import { Message } from 'element-ui';
import router from '../router';
export function fetch(options) {
return new Promise((resolve, reject) => {
const instance = axios.create({
baseURL: process.env.BASE_API, // 这里我们用了这样一个变量,根据环境选取开发接口还是生产接口
timeout: 20000 // 超时
});
instance(options)
.then(response => {
const res = response.data;
if (res.retCode !== "10000") {
// console.log(options); // for debug
// 40600:Token 过期了 50008:非法的token
if (res.retCode === "40600" || res.retCode === "50008") {
Message({
message: res.msg,
type: 'error',
duration: 5 * 1000
});
router.push({ path: '/login' })
} else {
Message({
message: res.msg,
type: 'error',
duration: 5 * 1000
});
}
reject(res);
} else {
resolve(res);
}
})
.catch(error => {
Message({
message: error,
type: 'error',
duration: 5 * 1000
});
// console.log(error); // for debug
reject(error);
});
});
}
首先声明process.env.BASE_API
的BASE_API
变量在这里是用不到的,因为这里启用了mockjs,不会发生真实的请求,已经被拦截了。不过我们还是分别修改一下./config/dev.env.js
和./config/prod.env.js
文件,为了真实的API接口调用时用到,如下所示:
# ./config/dev.env.js
var merge = require('webpack-merge')
var prodEnv = require('./prod.env')
module.exports = merge(prodEnv, {
NODE_ENV: '"development"',
BASE_API: '"http://52.80.14.58:8030/"' //公有IP,不用翻墙
})
# ./config/prod.env.js
var merge = require('webpack-merge')
var prodEnv = require('./prod.env')
module.exports = {
NODE_ENV: '"production"',
BASE_API: '"http://52.80.14.58:8030/"', //公有IP,不用翻墙
}
然后去./src/mock
文件夹下创建index.js
和login.js
文件,代码分别如下所示:
vue-demo
| -
| - src
| -
| - mock
| - index.js (新增)
| - login.js (新增)
| -
| -
# ./src/mock/index.js
import axios from 'axios';
import MockAdapter from 'axios-mock-adapter';
import loginAPI from './login';
const mock = new MockAdapter(axios);
// 邮箱登录接口
mock.onPost('/login/loginbyemail').reply(loginAPI.loginByEmail);
// 登出接口
mock.onPost('/login/logout').reply(loginAPI.logout);
export default mock;
# ./src/mock/login.js
const userMap = {
admin: {
retCode: "10000",
msg: "成功",
time: "2017-06-27 15:05:06",
data: {
adminInfo: {
adminId: "xxxxxxxxxxxxxx",
email: "admin@fusio.com.cn",
password2: "123456",
adminType: 99,
nickname: "XXXX",
realName: "XXXX",
mobile: "xxxxxxxxxxx",
createTime: "2017-06-27 14:29:51",
isValid: 0,
lastModTime: "2017-06-27 14:29:22",
password: "xxxxxxxxxxxxxxxxxxxxxxxxxxxx",
salt: "xxxxxx",
comment: "xxxx"
},
tokenModel: {
adminId: "xxxxxxxxxxxxxx",
token: "xxxxxxxxxxxxxxxxxxxxxxxxxxxx"
}
}
}
}
export default {
loginByEmail: config => {
const { email } = config.params;
return new Promise((resolve, reject) => {
if (userMap[email.split('@')[0]]) {
setTimeout(() => {
resolve([200,
userMap[email.split('@')[0]]
]);
}, 500);
} else {
reject('账号不正确')
}
})
},
logout: () => new Promise(resolve => {
setTimeout(() => {
resolve([200, {"retCode":"10000","msg":"成功","time":"2017-06-27 15:19:03","data":null}]);
}, 100);
})
};
先去安装一下mock模块,如下:
Yuxinde-MacBook-Pro:vue-demo yuxin$ npm install mockjs --save
npm WARN skippingAction Module is inside a symlinked module: not running update node-pre-gyp@0.6.36 node_modules/fsevents/node_modules/node-pre-gyp
npm WARN skippingAction Module is inside a symlinked module: not running move co@4.6.0 node_modules/ajv-keywords/node_modules/ajv/node_modules/co
npm WARN skippingAction Module is inside a symlinked module: not running move json-stable-stringify@1.0.1 node_modules/ajv-keywords/node_modules/ajv/node_modules/json-stable-stringify
npm WARN skippingAction Module is inside a symlinked module: not running add ajv@4.11.8 node_modules/ajv-keywords/node_modules/ajv
vue-demo@1.0.0 /Users/yuxin/Documents/Season/Project/Vue/vue-demo
└── mockjs@1.0.1-beta3
我们在./src/main.js
中把mock模块引入,代码如下:
# ./src/main.js
...
import './styles/index.scss';
import './mock/index.js'; //新增
...
现在,我们执行npm run dev
命令,看一下是否有错误。果然提示我们漏安装一些模块,这些模块在真实的API也可能需要用到,了解请谷歌。
Yuxinde-MacBook-Pro:vue-demo yuxin$ npm run dev
> vue-demo@1.0.0 dev /Users/yuxin/Documents/Season/Project/Vue/vue-demo
> node build/dev-server.js
> Starting dev server...
ERROR Failed to compile with 2 errors 17:31:46
These dependencies were not found:
* axios in ./src/mock/index.js
* axios-mock-adapter in ./src/mock/index.js
To install them, you can run: npm install --save axios axios-mock-adapter
> Listening at http://localhost:8080
^C
# 停止运行
# 去安装缺失模块
Yuxinde-MacBook-Pro:vue-demo yuxin$ npm install --save axios axios-mock-adapter
npm WARN skippingAction Module is inside a symlinked module: not running update node-pre-gyp@0.6.36 node_modules/fsevents/node_modules/node-pre-gyp
npm WARN skippingAction Module is inside a symlinked module: not running move co@4.6.0 node_modules/ajv-keywords/node_modules/ajv/node_modules/co
npm WARN skippingAction Module is inside a symlinked module: not running move json-stable-stringify@1.0.1 node_modules/ajv-keywords/node_modules/ajv/node_modules/json-stable-stringify
npm WARN skippingAction Module is inside a symlinked module: not running add ajv@4.11.8 node_modules/ajv-keywords/node_modules/ajv
vue-demo@1.0.0 /Users/yuxin/Documents/Season/Project/Vue/vue-demo
├─┬ axios@0.16.2
│ └── follow-redirects@1.2.4
└─┬ axios-mock-adapter@1.9.0
└── deep-equal@1.0.1
# 重新运行
Yuxinde-MacBook-Pro:vue-demo yuxin$ npm run dev
现在没有出现错误,那我们就去修改一下./src/views/login/login.vue
文件,我们将重写handleLogin
方法,如下:
#./src/views/login/login.vue
...
handleLogin() {
// 验证表单
this.$refs.loginForm.validate(valid => {
if (valid) {
// 验证通过
this.loading = true;
loginByEmail(this.loginForm.email, this.loginForm.password).then(response => {
console.log(response); // 这里输出一下,看看是不是我们mock定义的返回
this.loading = false;
this.$router.push({ path: '/' });
}).catch(err => {
this.loading = false;
console.error(err);
});
// if(this.loginForm.email == 'admin@fusio.com.cn' && this.loginForm.password == '123456') {
// // 注意这里有2种方法
// // 注意下不同写法时this的指向问题,用=>可以保持this的固定指向
// // 方法1
// // let that = this;
// // setTimeout(function(){
// // that.loading = false;
// // that.$router.push({ path: '/' });
// // }, 1000);
// // 方法2
// setTimeout(() => {
// this.loading = false;
// this.$router.push({ path: '/' });
// }, 1000);
// }
} else {
// 验证失败
console.error('error submit!!');
return false;
}
});
}
现在访问一下http://localhost:8080/login验证是否能够登录成功,验证可行。
同样的,我们去添加一下登出点击后的请求和处理,修改./src/views/layout/Navbar.vue
文件,如下:
# ./src/views/layout/Navbar.vue
...
<script>
import { logout } from '@/api/login';
export default {
methods: {
logout() {
logout().then(response => {
console.log(response); // 这里输出一下,看看是不是我们mock定义的返回
this.$router.push({ path: '/login' });
}).catch(err => {
console.error(err);
});
}
}
}
</script>
...
那么,“如何使用````mockjs```进行接口假数据返回”到这里就结束啦。
Step6. 调用API接口
因为前面我们已经用mockjs
实现了接口请求,只是返回了假数据。那用真实的接口,只是需要暂停使用mockjs
,并将api指向真实的接口进行调用。
暂停mockjs
的使用,修改./src/main.js
文件,如下:
# ./src/main.js
...
// 注释掉这句
// import './mock/index.js';
...
此时你再去访问http://localhost:8080/login网站,点击登录的话,就报错了。
去修改./src/api/login.js
文件,把假接口指向真实接口,如下:
# ./src/api/login.js
import { fetch } from '@/utils/fetch';
export function loginByEmail(email, password) {
const data = {
email,
password
};
return fetch({
// url: '/login/loginbyemail',
url: '/loginController/login',
method: 'post',
params: data
});
}
export function logout() {
return fetch({
// url: '/login/logout',
url: '/loginController/logout',
method: 'post'
});
}
此时你再去访问http://localhost:8080/login网站,点击登录进行验证,成功。再去验证一下登出,成功。
注意:有时候你先使用
mockjs
用假数据接口完成开发,然后再与后台对接真实接口,这里多数时参数、字段都不一样,所以要注意修改。
这时,我们发现一个问题“应该如何记住登录状态”。这样就能实现进入登陆页
时自动跳转,没登录或登录过期时需要跳入登录页
重新登录。下面就来看“状态管理”这个问题。
Step7. 状态管理(store仓库)
状态管理,我们就要用到vuex
,详见http://vuex.vuejs.org/zh-cn/intro.html。
文档里告诉我们,状态自管理应用包含以下几个部分:
- state,驱动应用的数据源;
- view,以声明方式将state映射到视图;
- actions,响应在view上的用户输入导致的状态变化。
我们在什么情况下应该考虑用到状态管理:
- 多个视图依赖于同一状态。
- 来自不同视图的行为需要变更同一状态。
我们先安装vuex
模块,如下:
Yuxinde-MacBook-Pro:vue-demo yuxin$ npm install vuex --save
npm WARN skippingAction Module is inside a symlinked module: not running update node-pre-gyp@0.6.36 node_modules/fsevents/node_modules/node-pre-gyp
npm WARN skippingAction Module is inside a symlinked module: not running move co@4.6.0 node_modules/ajv-keywords/node_modules/ajv/node_modules/co
npm WARN skippingAction Module is inside a symlinked module: not running move json-stable-stringify@1.0.1 node_modules/ajv-keywords/node_modules/ajv/node_modules/json-stable-stringify
npm WARN skippingAction Module is inside a symlinked module: not running add ajv@4.11.8 node_modules/ajv-keywords/node_modules/ajv
vue-demo@1.0.0 /Users/yuxin/Documents/Season/Project/Vue/vue-demo
└── vuex@2.3.1
去store下面创建一系列文件,代码分别如下:
vue-demo
| -
| - src
| -
| - store
| - modules
| - user.js (新增,state管理)
| - getters.js (新增,用于返回页面使用数据)
| - index.js (新增,引用)
| -
| -
# ./src/store/modules/user.js
import { loginByEmail, logout } from 'api/login';
// 用了storage,就停止了cookie方式
// import Cookies from 'js-cookie';
const user = {
state: {
email: '', // 用户的登录邮箱
uid: localStorage.getItem('uid'), // 用户的唯一ID
auth_type: '', // 用户的类型
status: '', // 用户的状态
token: localStorage.getItem('token'), // 用户登录后的token值,其他接口调用要携带,以便检查登录是否有效
// token: Cookies.get('X-Ivanka-Token'),
roles: [] // 用户角色
},
mutations: {
SET_EMAIL: (state, email) => {
state.email = email;
},
SET_UID: (state, uid) => {
state.uid = uid;
},
SET_AUTH_TYPE: (state, type) => {
state.auth_type = type;
},
SET_STATUS: (state, status) => {
state.status = status;
},
SET_TOKEN: (state, token) => {
state.token = token;
},
SET_ROLES: (state, roles) => {
state.roles = roles;
}
},
actions: {
// 邮箱登录
LoginByEmail({ commit }, userInfo) {
const email = userInfo.email.trim();
return new Promise((resolve, reject) => {
loginByEmail(email, userInfo.password).then(response => {
if(response.retCode==="10000") {
const data = response.data;
localStorage.token = data.tokenModel.adminId+'_'+data.tokenModel.token;
localStorage.uid = data.adminInfo.adminId;
// Cookies.set('X-Ivanka-Token', data.tokenModel.adminId+'_'+data.tokenModel.token);
commit('SET_TOKEN', data.tokenModel.adminId+'_'+data.tokenModel.token);
commit('SET_EMAIL', data.adminInfo.email);
commit('SET_ROLES', ['admin']);
commit('SET_UID', data.adminInfo.adminId);
resolve();
} else {
reject('账号或密码不正确');
}
}).catch(error => {
reject(error);
});
});
},
// 登出
LogOut({ commit, state }) {
return new Promise((resolve, reject) => {
logout().then(response => {
if(response.retCode==="10000") {
commit('SET_TOKEN', '');
commit('SET_ROLES', []);
localStorage.removeItem("token");
localStorage.removeItem("uid");
// Cookies.remove('X-Ivanka-Token');
resolve();
} else {
reject('登出失败');
}
}).catch(error => {
reject(error);
});
});
}
}
};
export default user;
# ./src/store/getters.js
const getters = {
token: state => state.user.token,
uid: state => state.user.uid,
email: state => state.user.email,
auth_type: state => state.user.auth_type,
status: state => state.user.status,
roles: state => state.user.roles
};
export default getters
# ./src/store/index.js
import Vue from 'vue';
import Vuex from 'vuex';
import user from './modules/user';
import getters from './getters';
Vue.use(Vuex);
const store = new Vuex.Store({
modules: {
user
},
getters
});
export default store
接着我们去修改./src/view/login/login.vue
文件,代码如下:
# ./src/view/login/login.vue
...
<script>
// import { loginByEmail } from '@/api/login'; // 注释掉
...
// 重写方法
handleLogin() {
// 验证表单
this.$refs.loginForm.validate(valid => {
if (valid) {
// 验证通过
this.loading = true;
// 使用状态管理
this.$store.dispatch('LoginByEmail', this.loginForm).then(() => {
this.loading = false;
this.$router.push({ path: '/' });
}).catch(err => {
this.loading = false;
this.$message.error(err);
});
// 使用mockjs或真实接口
...
...
</script>
接着我们去修改./src/main.js
文件,把store
引入进来,代码如下:
# ./src/main.js
...
// import './mock/index.js';
import store from './store'; // 新增
...
new Vue({
el: '#app',
router,
store, // 新增
template: '<App/>',
components: { App }
})
此时你再去访问http://localhost:8080/login网站,点击登录进行验证,成功。 调用的时候,去查看Local Storage
留意一下。
同样的,我们去改一下登出,修改./src/views/layout/Navbar.vue
,然后测试一下。
# ./src/views/layout/Navbar.vue
...
<script>
// import { logout } from '@/api/login';
...
logout() {
// 使用状态管理
this.$store.dispatch('LogOut').then(() => {
this.$router.push({ path: '/login' });
}).catch(err => {
this.$message.error(err);
});
// 使用mockjs或真实接口
...
...
测试之后,发现登出也可以了。但是我们发现一个问题,现在如果我们直接访问页面http://localhost:8080/dashboard,我们也可以进入,这是不对的,现在我们来看一下这个问题。
修改./src/main.js
文件,代码如下:
# ./src/main.js
...
// 新增
const whiteList = ['/login'];// 不重定向白名单、登录、重置密码等等
router.beforeEach((to, from, next) => {
document.title = (to.name || '') + '- vue demo' // 设置页面的title
if (store.getters.token) { // 根据有没有token去判断是否登录
if (to.path === '/login') {
next({ path: '/' });
} else {
next();
}
} else {
if (whiteList.indexOf(to.path) !== -1) {
next()
} else {
next('/login')
}
}
});
...
再访问页面http://localhost:8080/dashboard进行测试检查,发现已经可以了。
Step8. 抽离公共方法
由于篇幅有限、时间有限,这里能够给出的demo还是过于简单,并没有什么页面,也没有重复使用的方法。但是这里就提一下吧,多次调用的该抽离的就抽离出去以便可维护,相似的方法集中一个文件也是减少维护成本。
编程思想,我觉得还是很重要的,不单单只是实现页面、实现功能,如何最好的实现,哪种方式、思路更好,这都是慢慢修炼的,哈哈。
Step9. 剥离组件
这个demo也是没有给出复杂页面,实际项目中某些页面是可以有几个功能模块组成的,在这里都没有体现。组件思想在vue算是核心,所以写完一个页面后,就可以开始研究页面的组件化。
我是比较不建议,一个复杂页面上来就开始先做拆分,除非思路很清晰、也没有难点。不过最安全、快捷的方法是先写出来,这样理解已经更透彻,然后才去拆分,我觉得这样是最快的。
(看其他demo吧,或者自己重构一下项目,我可以开放项目接口出来)
Finish. 生成打包
在打包的时候,同事注意到这样一个问题。当我们的命令附带NODE_ENV=production
的时候,是不一样的:
# Mac写法
"build:prod": "NODE_ENV=production node build/build.js",
# Windows写法
"build:prod": "set NODE_ENV=production && node build/build.js",
我在做打包部署的时候,遇到这样一个问题。比如我在本地跑起来一个服务,它的域名先使用自定义的,如vue.demo.192.168.4.24.xip.io
,网站地址为http://vue.demo.192.168.4.24.xip.io/dashboard。当我刷新页面的时候,就会报“Not Found”错误。
现在看一下这样一个问题是如何产生的?
解答:经过研究测试,这一步需要服务器配置的。不知道是否还有其他解决方案。
如果打包部署出去,发现js
,css
找不到的问题,一定是config那里不太对,修改配置文件./connfig/index.js
。
# ./connfig/index.js
// see http://vuejs-templates.github.io/webpack for documentation.
var path = require('path')
module.exports = {
build: {
env: require('./prod.env'),
index: path.resolve(__dirname, '../dist/index.html'),
assetsRoot: path.resolve(__dirname, '../dist'),
assetsSubDirectory: '',
assetsPublicPath: '/',
staticPath:'/',
productionSourceMap: true,
// Gzip off by default as many popular static hosts such as
// Surge or Netlify already gzip all static assets for you.
// Before setting to `true`, make sure to:
// npm install --save-dev compression-webpack-plugin
productionGzip: false,
productionGzipExtensions: ['js', 'css'],
// Run the build command with an extra argument to
// View the bundle analyzer report after build finishes:
// `npm run build --report`
// Set to `true` or `false` to always turn it on or off
bundleAnalyzerReport: process.env.npm_config_report
},
dev: {
env: require('./dev.env'),
port: 8080,
autoOpenBrowser: true,
assetsSubDirectory: 'static',
assetsPublicPath: '/',
staticPath:'/static/',
proxyTable: {},
// CSS Sourcemaps off by default because relative paths are "buggy"
// with this option, according to the CSS-Loader README
// (https://github.com/webpack/css-loader#sourcemaps)
// In our experience, they generally work as expected,
// just be aware of this issue when enabling this option.
cssSourceMap: false
}
}
5.项目部署
由于最后我们打包生成并部署的实际上是一个静态网站,那么我们就来看一下如何在本地部署访问和如何在服务器上部署访问。
a)本地部署
本地的话,就直接使用【MAMP】这个软件吧,按步骤一步步安装之后,运行起来基本就可以用了,不需要配置什么。
在“Hosts”那边新增一个Server Name,右边唯一注意的就是把Name resolution的via Xip.io(LAN only)勾选上,这样你就看到下面输入框有个访问地址。在Document root选择你指向的dist文件夹路径(打包文生成的那个)。运行访问就OK了。
(在Mac,可以直接利用apache搭建一个的服务器,只要在Users/yourname/Sites这个目录下的静态网站,都可以直接访问,具体搭建可以查询类似“在Mac上搭建本地Apache服务器”)
b)服务器部署
另外一种方式,就是找一个服务器进行部署了,比如亚马逊云、阿里云、腾讯云等。我只是玩过ubuntu和centOS,它们在安装nginx后的路径、配置文件的路径有些不一样,只要找对了位置进行配置就好了。
先把部署文件夹dist
丢上服务器,之后再配置nginx的时候指向这个路径就行了。可以通过专门建一个放dist
部署文件夹的git项目,这样方便部署更新。
先看下centOS服务器的:
# centOS上面的安装配置大概就这几行
# 遇到权限问题切换admin安装,也可以谷歌查询解决方案
1、安装nodeJS
curl --silent --location https://rpm.nodesource.com/setup_6.x | bash -
yum -y install nodejs
2、安装nginx
sudo yum install epel-release
sudo yum install nginx
vi /etc/nginx/nginx.conf //编辑配置文件
sudo /etc/init.d/nginx start //启动
sudo /etc/init.d/nginx restart //重启
sudo /etc/init.d/nginx stop //停止
3、配置文件内容
# 修改server那一块就好了
server {
listen 80;
server_name www.ma.h.fusio.net.cn;
index index.html;
root /data/web/apps/ma_front_dev/my-vue-demo-dist/dist; // 这一行可以测试下不写
location / {
root /data/web/apps/ma_front_dev/my-vue-demo-dist/dist;
try_files $uri $uri/ /index.html =404;
}
}
下面则是ubuntu服务器的:
# ubuntu上面的安装配置大概就这几行
# 应该比centOS遇到的问题少一点
1、安装nodeJS
curl -sL https://deb.nodesource.com/setup_6.x | sudo -E bash -
sudo apt-get install -y nodejs
sudo apt-get install -y build-essential
2、安装nginx
sudo apt-get update
sudo apt-get install nginx
sudo vi /etc/nginx/sites-available/default //编辑配置文件
sudo /etc/init.d/nginx start //启动
sudo /etc/init.d/nginx restart //重启
sudo /etc/init.d/nginx stop //停止
3、配置文件内容
(同上)
6.结束
整篇文章的代码放在github
上,可以下载。
代码地址为:https://github.com/YuxinChou/vue-demo-source
Demo地址为:https://yuxinchou.github.io/login
题外话:
我学习vue主要是通过几个demo去开始的,都是从github
上找,对比、最后选择满足最满足自己需求的去研究,并去优化调整结构、代码。
你们如果是从看这篇文档开始学习的话,那之后就要去
github
上找找其他demo,来不断优化这一个框架结构,并去完善内部的各种功能,比如图表、导出等。这里的demo还是太简单了。
我学习时参考了这个项目:
代码地址:https://github.com/PanJiaChen/vue-element-admin
我最近看到它的代码还在更新,赞。
我们现在的demo
很多功能都没有,一般项目还需要哪些功能,可以之后去研究一下:
- 侧边栏菜单的展开收缩
- 增删改查
- 图表
- 权限控制
- 404、500
- ...
大概就是这样了,如果有什么不对的地方请评论指正,谢谢。
接下来,一方面是想知道如何优化架构,另一方面想去研究一下指令方式写组件。哪位大神带带我!跟不上了,求你们别学了。
到这里,就先结束了。
学习是一条漫漫长路,每天不求一大步,进步一点点就是好的。