1.1 vue项目初始化
1.1.1 安装cnpm
npm install -g cnpm --registry=https://registry.npm.taobao.org
1.1.2 全局安装vue命令
cnpm install -g @vue/cli
1.1.3 创建新项目
vue create study-home
1.1.4 App.vue引入 router-view
<template>
<div id="app">
<router-view/>
</div>
</template>
<script>
export default {
name: 'App',
components: {}
}
</script>
<style>
</style>
1.1.5 重置项目样式
- 安装normalize.css
npm install --save normalize.css
# 或者使用
yarn add normalize.css
yarn install
- main.js方式引入
import 'normalize.css/normalize.css'
import './assets/style.css';
1.2 vue项目相关操作
1.2.1 vue禁用eslint
在项目的根目录下建立 vue.config.js
,添加以下内容:
module.exports = {
lintOnSave: false
}
1.3 整合vue-router
1.3.1 安装 vue-router
npm install vue-router
1.3.2 引入vue-router
在项目的 src 目录下新建 router/index.js
,内容如下:
import Vue from 'vue'
import Router from 'vue-router'
import Home from "../view/Home";
Vue.use(Router)
// 路由配置
let constRouter = [
{
path: '/home',
name: 'Home',
component: Home,
meta: {
title: '首页'
}
},
// 全不匹配的情况下返回主页
{
path: '*',
redirect: '/home'
},
]
let router = new Router({
mode: 'history',
routes: constRouter
})
// 导航守卫
router.beforeEach((to, from, next) => {
document.title = to.meta.title
next()
})
// 路由导航钩子
router.afterEach((to, from, next) => {
window.scrollTo(0, 0)
})
export default router
项目 src 下新建 views 目录,用于存放普通页面,比如 Home.vue 主页
1.3.3 main.js 配置路由
import Vue from 'vue'
import App from './App.vue'
import router from "./router";
Vue.config.productionTip = false
new Vue({
router,
render: h => h(App)
}).$mount('#app')
1.3.4 配置两个字符缩进
在项目根目录下新建 .editorconfig
文件,它帮助开发人员在不同的编辑器和IDE维护一致的编码样式。
root = true
[*]
charset = utf-8
indent_style = space
indent_size = 2
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
1.4 整合vuex
1.4.1 安装vuex
npm install vuex --save
1.4.2 引入vuex
- 在项目的 src 下新建 store目录,并在该目录下新建 index.js,内容如下:
import Vue from 'vue'
import Vuex from 'vuex'
import topic from './modules/topic';
Vue.use(Vuex)
export default new Vuex.Store({
modules: {
topic
}
})
- 在store目录新建 modules/topic.js 结构,topic.js内容如下:
import request from "../../utils/request";
export default {
namespaced: true,
state: {
topicList: [],
},
getters: {},
mutations: {
setTopicList(state, data) {
state.topicList = data
},
},
actions: {
getTopicList(context) {
request.get('/v1/topic/list').then(res => {
if (res.code === 200) {
context.commit('setTopicList', res.data)
} else {
console.log(res.message)
}
})
}
}
}
1.4.3 使用vuex
<div class="panel">
<div class="panel-body">
<a v-for="topic in topicList" :key="topic.id" class="topic-item"
@click="handleTopic(topic.id)">
{{topic.topicName}}
</a>
</div>
</div>
<script>
import diaryApi from '../../api/diary'
import {mapState} from "vuex";
export default {
name: 'DiaryList',
components: {BasicLayout},
data() {
return {
topicId: -1,
};
},
created() {
this.initData()
// 初始化vuex数据
this.$store.dispatch('topic/getTopicList')
},
computed: {
...mapState('topic', ['topicList']),
},
methods: {
// 初始化数据
initData() {
diaryApi.listDiary(this.topicId).then(res => {
this.diaryList = res.data.rows
})
},
// 处理主题
handleTopic(topicId) {
this.topicId = topicId
this.initData()
}
},
}
</script>
1.5 整合axios
1.5.1 安装axios
npm install --save axios
1.5.2 定义request.js
在项目 src 建立 utils/request.js,内容如下:
import axios from 'axios'
import {message, Modal, notification} from 'ant-design-vue'
import moment from 'moment'
moment.locale('zh-cn')
import router from '../router'
// 统一配置
let SERVICE = axios.create({
baseURL: "http://localhost:9050",
responseType: 'json'
})
// 拦截请求
SERVICE.interceptors.request.use((config) => {
// 有 token就带上
/* if (store.state.account.token) {
config.headers.Authentication = store.state.account.token
}*/
return config
}, (error) => {
return Promise.reject(error)
})
// 异常拦截处理器
const errorHandler = (error) => {
if (error.response) {
let errorMessage = error.response.data === null ? '系统内部异常,请联系网站管理员' : error.response.data.message
switch (error.response.status) {
case 404:
router.push('/404')
break
case 403:
router.push('/403')
break
case 500:
router.push('/500')
return
case 401:
notification.warn({
message: '系统提示',
description: '很抱歉,您无法执行该操作,可能是因为没有相应权限或者登录已失效!',
duration: 4
})
break
default:
notification.error({
message: '系统提示',
description: errorMessage,
duration: 4
})
break
}
}
return Promise.reject(error)
}
// 拦截响应
SERVICE.interceptors.response.use((response) => {
return response.data
}, errorHandler)
// 封装请求
const request = {
post (url, params) {
return SERVICE.post(url, params, {
transformRequest: [(params) => {
let result = ''
Object.keys(params).forEach((key) => {
if (!Object.is(params[key], undefined) && !Object.is(params[key], null)) {
result += encodeURIComponent(key) + '=' + encodeURIComponent(params[key]) + '&'
}
})
return result
}],
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
}
})
},
put (url, params) {
return SERVICE.put(url, params, {
transformRequest: [(params) => {
let result = ''
Object.keys(params).forEach((key) => {
if (!Object.is(params[key], undefined) && !Object.is(params[key], null)) {
result += encodeURIComponent(key) + '=' + encodeURIComponent(params[key]) + '&'
}
})
return result
}],
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
}
})
},
get (url, params) {
let _params
if (Object.is(params, undefined)) {
_params = ''
} else {
_params = '?'
for (let key in params) {
if (params.hasOwnProperty(key) && params[key] !== null) {
_params += `${key}=${params[key]}&`
}
}
}
return SERVICE.get(`${url}${_params}`)
},
delete (url, params) {
let _params
if (Object.is(params, undefined)) {
_params = ''
} else {
_params = '?'
for (let key in params) {
if (params.hasOwnProperty(key) && params[key] !== null) {
_params += `${key}=${params[key]}&`
}
}
}
return SERVICE.delete(`${url}${_params}`)
},
upload (url, params) {
return SERVICE.post(url, params, {
headers: {
'Content-Type': 'multipart/form-data'
}
})
}
}
export default request
1.5.3 main.js 全局引入
import Vue from 'vue'
import App from './App.vue'
import router from "./router"
import store from "./store"
import Axios from "axios";
import request from "./utils/request";
// 引入antd
import Antd from 'ant-design-vue';
import 'ant-design-vue/dist/antd.css';
Vue.use(Antd);
// 引入mavonEditor
import mavonEditor from 'mavon-editor'
import 'mavon-editor/dist/css/index.css'
Vue.use(mavonEditor)
import 'normalize.css/normalize.css'
import './assets/style.css';
Vue.config.productionTip = false
Vue.prototype.$get = request.get
Vue.prototype.$post = request.post
Vue.prototype.$put = request.put
Vue.prototype.$delete = request.delete
Vue.prototype.$export = request.export
Vue.prototype.$download = request.download
Vue.prototype.$upload = request.upload
Vue.prototype.$axios = Axios
new Vue({
router,
store,
render: h => h(App)
}).$mount('#app')
1.6 整合antd
1.6.1 安装antd
yarn add ant-design-vue
1.6.2 main.js 引入
// 引入antd
import Antd from 'ant-design-vue';
import 'ant-design-vue/dist/antd.css';
Vue.use(Antd);
1.6.3 定义布局
一般网站页面都有,导航栏,主页面,底部footer所以可以使用插槽其封装成组件,以便以后相似页面使用。
- 在 src 下创建 layout 目录用于存放页面布局文件,新建一个BasicLayout基础布局组件,内容如下:
<template>
<a-layout class="layout">
<a-layout-header class="header">
</a-layout-header>
<a-layout-content class="main">
<div class="w">
<slot name="mainBox"></slot>
</div>
<a-back-top/>
</a-layout-content>
<a-layout-footer style="text-align: center">
<h3>welcome to 欢乐学习谷</h3>
</a-layout-footer>
</a-layout>
</template>
<script>
export default {
name: 'BasicLayout',
components: {},
}
</script>
<style scoped>
.w {
max-width: 1200px;
margin: 0 auto;
}
.main {
margin-top: 15px;
}
</style>
1.6.4 使用布局组件
<template>
<BasicLayout>
<template v-slot:mainBox>
Hello, this is home
</template>
</BasicLayout>
</template>
<script>
import BasicLayout from "../layout/BasicLayout";
export default {
name: "Home",
components: {BasicLayout}
}
</script>
<style scoped>
</style>
1.7 vue 整合 mavon-editor
1.7.1 安装 mavon-editor
npm install mavon-editor --save
1.7.2 main.js 引入
// 全局注册
import Vue from 'vue'
import mavonEditor from 'mavon-editor'
import 'mavon-editor/dist/css/index.css'
// use
Vue.use(mavonEditor)
1.7.3 界面引入
<mavon-editor
class="add-diary-content"
ref=md
v-model="diary.content"
:autofocus="false"
placeholder="输入日记具体内容..."
/>