基于vue.js的通用框架
nuxt安装
npx create-nuxt-app <项目名>
选项
image.png
运行项目:npm run dev
整合axios
安装@nuxt/axios模块
npm install @nuxtjs/axios -S
配置
nuxt.config.js
modules: ["@nuxtjs/axios", "cookie-universal-nuxt"],
axios: {
proxy: true,
},
proxy: {
"/api": "http://localhost:8080",
},
pages/index.vue
配置头
异步数据获取
<template>
<div>
<h2>商品列表</h2>
<ul>
<li v-for="good in goods" :key="good.id">
<nuxt-link :to="`/detail/${good.id}`">
<span>{{good.text}}</span>
<span>¥{{good.price}}</span>
</nuxt-link>
</li>
</ul>
</div>
</template>
<script>
export default {
head() {
return {
title: "课程列表",
meta: [
{ name: "description", hid: "description", content: "set page meta" }
],
link: [{ rel: "favicon", href: "favicon.ico" }]
};
},
async asyncData({ $axios, error }) {
// 页面上下文
const { ok, goods } = await $axios.$get("/api/goods");
if (ok) {
return { goods };
}
// 错误处理
error({ statusCode: 400, message: "数据查询失败" });
}
// data() {
// return { goods: [
// {id:1, text:'Web全栈架构师',price:8999},
// {id:2, text:'Python全栈架构师',price:8999},
// ] }
// }
};
</script>
嵌套路由
pages/detail/_id.vue
_id会被作为参数的名字
<template>
<div>
{{$route.params.id}}
</div>
</template>
<script>
export default {
}
</script>
<style lang="scss" scoped>
</style>
要想做路由嵌套 要创建一个根文件夹一样名字的文件
pages/detail.vue
<template>
<div>
detail page
<nuxt-child></nuxt-child>
</div>
</template>
<script>
export default {
}
</script>
<style lang="scss" scoped>
</style>
layouts/default.vue添加导航
<template>
<div>
<nav>
<nuxt-link to="/">首页</nuxt-link>
<!--别名:n-link,NLink,NuxtLink-->
<NLink to="/admin">管理</NLink>
<n-link to="/cart">购物车</n-link>
</nav>
<nuxt />
</div>
</template>
<style>
html {
font-family: "Source Sans Pro", -apple-system, BlinkMacSystemFont, "Segoe UI",
Roboto, "Helvetica Neue", Arial, sans-serif;
font-size: 16px;
word-spacing: 1px;
-ms-text-size-adjust: 100%;
-webkit-text-size-adjust: 100%;
-moz-osx-font-smoothing: grayscale;
-webkit-font-smoothing: antialiased;
box-sizing: border-box;
}
*,
*:before,
*:after {
box-sizing: border-box;
margin: 0;
}
.button--green {
display: inline-block;
border-radius: 4px;
border: 1px solid #3b8070;
color: #3b8070;
text-decoration: none;
padding: 10px 30px;
}
.button--green:hover {
color: #fff;
background-color: #3b8070;
}
.button--grey {
display: inline-block;
border-radius: 4px;
border: 1px solid #35495e;
color: #35495e;
text-decoration: none;
padding: 10px 30px;
margin-left: 15px;
}
.button--grey:hover {
color: #fff;
background-color: #35495e;
}
</style>
nuxt.config.js可以追加或删除已生成的路由 因为nuxt的路由是自动生成的
router: {
extendRoutes(routes, resolve) {
// routes已经生成的路由
// resolve是获取页面方法
routes.push({
name: "foo",
path: "/foo",
component: resolve(__dirname, "pages/custom.vue"),
});
},
},
pages/cutom.vue
<template>
<div>
custom page
</div>
</template>
<script>
export default {
}
</script>
<style lang="scss" scoped>
</style>
自定义布局 不配置导航头
layouts/blank.vue
<template>
<div>
<nuxt />
</div>
</template>
pages/login.vue
<template>
<div>
<h2>用户登录</h2>
<el-input v-model="user.username"></el-input>
<el-input type="password" v-model="user.password"></el-input>
<el-button @click="onLogin">登录</el-button>
</div>
</template>
<script>
export default {
layout:'blank',
data() {
return {
user: {
username: "",
password: ""
}
};
},
methods: {
onLogin() {
this.$store.dispatch("user/login", this.user).then(ok=>{
if (ok) {
const redirect = this.$route.query.redirect || '/'
this.$router.push(redirect);
}
});
}
}
};
</script>
安装依赖:
npm i koa-router koa-bodyparser -S
模拟接口服务器
根目录server/api.js
cd server
node .\api.js
const Koa = require('koa');
const app = new Koa();
const bodyparser = require("koa-bodyparser");
const router = require("koa-router")({ prefix: "/api" });
// 设置cookie加密秘钥
app.keys = ["some secret", "another secret"];
const goods = [
{ id: 1, text: "Web全栈架构师", price: 1000 },
{ id: 2, text: "Python架构师", price: 1000 }
];
router.get("/goods", ctx => {
ctx.body = {
ok: 1,
goods
};
});
router.get("/detail", ctx => {
ctx.body = {
ok: 1,
data: goods.find(good => good.id == ctx.query.id)
};
});
router.post("/login", ctx => {
const user = ctx.request.body;
if (user.username === "jerry" && user.password === "123") {
// 将token存入cookie
const token = 'a mock token';
ctx.cookies.set('token', token);
ctx.body = { ok: 1, token };
} else {
ctx.body = { ok: 0 };
}
});
// 解析post数据并注册路由
app.use(bodyparser());
app.use(router.routes());
app.listen(8080, () => console.log('api服务已启动'))
中间件 处理路由跳转之前的拦截
middleware/auth.js
// 参数是页面上下文
export default function({ route, redirect, store }) {
// 上下文中通过store访问vuex中的全局状态
// 通过vuex中令牌存在与否判断是否登录
if (!store.state.user.token) {
redirect("/login?redirect=" + route.path);
}
}
pages/admin.vue
全局配置middleware 可以在nuxt.config.js
里面的router里配
<template>
<div>
admin page
</div>
</template>
<script>
export default {
middleware: ['auth']
}
</script>
<style lang="scss" scoped>
</style>
store/user.js
export const state = () => ({
token: "",
});
export const mutations = {
init(state, token) {
state.token = token;
},
};
export const getters = {
isLogin(state) {
return !!state.token;
},
};
export const actions = {
login({ commit, getters }, u) {
return this.$axios.$post("/api/login", u).then(({ token }) => {
if (token) {
commit("init", token);
}
return getters.isLogin;
});
},
};
nuxtServerInit
store/index.js
安装依赖:
npm i -S cookie-universal-nuxt
注册 nuxt.config.js
modules: ["@nuxtjs/axios", "cookie-universal-nuxt"],
export const actions = {
// 参数1:action上下文对象,参数2:nuxt页面上下文
nuxtServerInit({ commit }, { app }) {
const token = app.$cookies.get("token");
if (token) {
console.log("nuxtServerInit: token:"+token);
commit("user/init", token);
}
}
};
发布
npm run build
npm start
网友评论