Koa
或者其它Node.js
服务器进行集成mkdir zhufengnextjs
cd zhufengnextjs
npm init -y
yarn add --dev react react-dom next axios redux react-redux express body-parser cors express-session connect-mongo mongoose koa koa-router
mkdir pages
package.json
{
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start"
}
}
_app.js
和 _document.js
pages
组件代码自动分割.next
目录export default function () {
return (
<div>Home</div>
)
}
curl http://localhost:3000/
styled-jsx
来生成独立作用域的 CSS
css
App
组件是每个页面的根组件,页面切换时 App 不会销毁,但是里面的页面组件会销毁,因此可以利用这个来设置全局属性和样式pages_app.js
import App, { Container } from 'next/app';
import Link from 'next/link';
import _appStyle from './_app.module.css';
import '../styles/global.css';
class LayoutApp extends App{
render() {
let { Component } = this.props;
return (
<div>
<style jsx>
{
`li{
display:inline-block;
margin-left:10px;
line-height:31px;
}`
}
</style>
<div>
<header>
<img src="/images/jglogo.png" className={_appStyle.logo}/>
<ul>
<li><Link href="/"><a>首页</a></Link></li>
<li><Link href="/user" ><a>用户管理</a></Link></li>
<li><Link href="/profile"><a>个人中心</a></Link></li>
</ul>
</header>
<Component />
<footer style={{ textAlign: 'center' }} >@copyright 珠峰架构</footer>
</div>
</div>
)
}
}
export default LayoutApp;
pages_app.module.css
.logo{
width: 120px;
height: 31px;
float: left;
}
styles\global.css
html,
body {
padding: 0;
margin: 0;
}
pages\index.js
export default function () {
return (
<div>
<p>Home</p>
</div>
)
}
pages\user.js
import Link from 'next/link'
export default function () {
return (
<div>
<p>User</p>
<Link href="/">首页</Link>
</div>
)
}
pages\profile.js
import router from 'next/router'
export default function () {
return (
<div>
<p>User</p>
<button onClick={() => router.back()}>返回</button>
</div>
)
}
getInitialProps
获取数据pages_app.js
import App from 'next/app';
import Link from 'next/link';
import _appStyle from './_app.module.css';
import '../styles/global.css';
class LayoutApp extends App{
+ static async getInitialProps({ Component, ctx }) {
+ let pageProps = {};
+ if (Component.getInitialProps)
+ pageProps = await Component.getInitialProps(ctx);
+ return { pageProps };
+ }
render() {
+ let { Component,pageProps } = this.props;
return (
<div>
<style jsx>
{
`li{
display:inline-block;
margin-left:10px;
line-height:31px;
}`
}
</style>
<div>
<header>
<img src="/images/jglogo.png" className={_appStyle.logo}/>
<ul>
<li><Link href="/"><a>首页</a></Link></li>
+ <li><Link href="/user/list" ><a>用户管理</a></Link></li>
<li><Link href="/profile"><a>个人中心</a></Link></li>
</ul>
</header>
+ <Component {...pageProps} />
<footer style={{ textAlign: 'center' }} >@copyright 珠峰架构</footer>
</div>
</div>
)
}
}
export default LayoutApp;
pages\user\index.js
import Link from 'next/link';
function UserLayout(props) {
return (
<div>
<div>
<ul>
<li><Link href="/user/list"><a>用户列表</a></Link></li>
<li><Link href="/user/add"><a>添加用户</a></Link></li>
</ul>
<div>
{props.children}
</div>
</div>
</div>
)
}
export default UserLayout;
pages\user\list.js
import Link from 'next/link';
import UserLayout from './';
function UseList(props) {
return (
<UserLayout>
<ul>
{
props.list.map((user)=>(
<li key={user.id}>
<Link href={`/user/detail/${user.id}`}>{user.name}</Link>
</li>
))
}
</ul>
</UserLayout>
)
}
UseList.getInitialProps = async (ctx) => {
let list = [{ id: 1, name: '张三'}, { id: 2, name: '李四'}];
return { list };
}
export default UseList;
pages\user\add.js
import Link from 'next/link';
import UserLayout from './';
import React from 'react';
function UserAdd(props) {
let nameRef = React.useRef();
let passwordRef = React.useRef();
let handleSubmit = (event)=>{
event.preventDefault();
let user = {name:nameRef.current.value,password:passwordRef.current.value};
console.log('添加',user);
}
return (
<UserLayout>
<form onSubmit={handleSubmit}>
用户名:<input ref={nameRef}/>
密码:<input ref={passwordRef}/>
<button type="submit">添加</button>
</form>
</UserLayout>
)
}
export default UserAdd;
pages\user\detail[id].js
import React from 'react';
import UserLayout from '../';
function UserDetail(props) {
return (
<UserLayout>
<p>ID:{props.user.id}</p>
</UserLayout>
)
}
UserDetail.getInitialProps = async (ctx) => {
return { user:{id:ctx.query.id}};
}
export default UserDetail;
getInitialProps
将会把数据序列化,就像JSON.stringify
getInitialProps
返回的是一个普通 JS
对象,而不是Date, Map 或 Set类型getInitialProps
只会加载在服务端。只有当路由跳转(Link组件跳转或 API 方法跳转)时,客户端才会执行getInitialProps
getInitialProps
将不能使用在子组件中。只能使用在pages
页面中utils\axios.js
import axios from 'axios';
axios.defaults.withCredentials = true
const instance = axios.create({
baseURL: 'http://localhost:4000'
})
export default instance;
pages\user\add.js
import Link from 'next/link';
import UserLayout from './';
import React from 'react';
+import axios from '../../utils/axios';
+import router from 'next/router'
function UserAdd() {
let nameRef = React.useRef();
let passwordRef = React.useRef();
let handleSubmit = async (event)=>{
event.preventDefault();
let user = {name:nameRef.current.value,password:passwordRef.current.value};
+ let response = await axios.post('/api/register', user).then(res=>res.data);
+ if (response.success) {
+ router.push('/user/list');
+ } else {
+ alert('添加用户失败');
+ }
}
return (
<UserLayout>
<form onSubmit={handleSubmit}>
用户名:<input ref={nameRef}/>
密码:<input ref={passwordRef}/>
<button type="submit">添加</button>
</form>
</UserLayout>
)
}
export default UserAdd;
pages\user\list.js
import Link from 'next/link';
import UserLayout from './';
+import axios from '../../utils/axios';
function UseList(props) {
return (
<UserLayout>
<ul>
{
props.list.map((user)=>(
<li key={user.id}>
<Link href={`/user/detail/${user.id}`}>{user.name}</Link>
</li>
))
}
</ul>
</UserLayout>
)
}
UseList.getInitialProps = async (ctx) => {
+ let response = await axios({ url: '/api/users', method: 'GET' }).then(res=>res.data);
+ return { list:response.data };
}
export default UseList;
pages\user\detail[id].js
import React from 'react';
import UserLayout from '../';
import axios from '../../../utils/axios';
function UserDetail(props) {
let {user} = props;
return (
<UserLayout>
<p>ID:{user.id}</p>
<p>ID:{user.name}</p>
</UserLayout>
)
}
UserDetail.getInitialProps = async (ctx) => {
let response = await axios({ url: `/api/users/${ctx.query.id}`, method: 'GET' }).then(res=>res.data);
return { user: response.data };
}
export default UserDetail;
pages\user\detail[id].js
import React from 'react';
import UserLayout from '../';
import axios from '../../../utils/axios';
import dynamic from 'next/dynamic';
const UserInfo = dynamic(import('../../../components/UserInfo'))
function UserDetail(props) {
let {user} = props;
let [show, setShow] = React.useState(false);
return (
<UserLayout>
<p>ID:{user.id}</p>
<button onClick={() => setShow(!show)}>显示/隐藏</button>
{
show && <UserInfo user={user} />
}
</UserLayout>
)
}
UserDetail.getInitialProps = async (ctx) => {
let response = await axios({ url: `/api/users/${ctx.query.id}`, method: 'GET' }).then(res=>res.data);
return { user: response.data };
}
export default UserDetail;
components\UserInfo.js
import React from 'react';
function UserInfo(props) {
let {user} = props;
let [created, setCreated] = React.useState(props.user.created);
async function changeFormat() {
let moment = await import('moment');
setCreated(moment.default(user.created).fromNow());
}
return (
<div>
<p>用户名:{user.name}</p>
<p>创建时间:{created}<button onClick={changeFormat}>切换为相对时间</button></p>
</div>
)
}
export default UserInfo;
pages_app.js
<ul>
<li><Link href="/"><a>首页</a></Link></li>
<li><Link href="/user/list" ><a>用户管理</a></Link></li>
<li><Link href="/profile"><a>个人中心</a></Link></li>
+ <li><Link href="/login">登录</Link></li>
</ul>
import React from 'react';
import axios from '../utils/axios';
import router from 'next/router';
import {connect} from 'react-redux';
import * as types from '../store/action-types';
function Login() {
let nameRef = React.useRef();
let passwordRef = React.useRef();
let handleSubmit = async (event)=>{
event.preventDefault();
let user = {name:nameRef.current.value,password:passwordRef.current.value};
let response = await axios.post('/api/login', user).then(res=>res.data);
if (response.success) {
props.dispatch({type:types.SET_USER_INFO,payload:response.data});
router.push('/');
} else {
alert('登录失败');
}
}
return (
<form onSubmit={handleSubmit}>
用户名:<input ref={nameRef}/>
密码:<input ref={passwordRef}/>
<button type="submit">登录</button>
</form>
)
}
export default connect(state=>state)(Login);
yarn add redux react-redux
pages_app.js
import App from 'next/app';
import Link from 'next/link';
import _appStyle from './_app.module.css';
import '../styles/global.css';
+import { Provider } from 'react-redux';
+import axios from '../utils/axios';
+import createStore from '../store';
+import * as types from '../store/action-types';
+function getStore(initialState) {
+ if (typeof window == 'undefined') {
+ return createStore(initialState);//如果是服务器端,每次都返回新的仓库
+ } else {
+ if (!window._REDUX_STORE_) {
+ window._REDUX_STORE_ = createStore(initialState);
+ }
+ return window._REDUX_STORE_;
+ }
+}
+class LayoutApp extends App{
+ constructor(props){
+ super(props);
+ this.store = getStore(props.initialState);//3.后台用新状重新创建新仓库
+ //4.初始状态序列化后发给了客户端,在客户端重新创建新的仓库
+ }
+ static async getInitialProps({ Component, ctx }) {
+ let store = getStore();//1.后台创建新仓库 5.每次切换路由都会执行此方法获取老仓库
+ if (typeof window == 'undefined') {//2.后台获取用户信息
+ let options = { url: '/api/currentUser' };
+ if (ctx.req&&ctx.req.headers.cookie) {
+ options.headers = options.headers || {};
+ options.headers.cookie = ctx.req.headers.cookie;
+ }
+ let response = await axios(options).then(res=>res.data);
+ if (response.success) {
+ store.dispatch({ type: types.SET_USER_INFO, payload: response.data });
+ }
+ }
+ let pageProps = {};
+ if (Component.getInitialProps)
+ pageProps = await Component.getInitialProps(ctx);
+ let props = { pageProps};
+ if (typeof window == 'undefined') {//后台获取用赋值状态
+ props.initialState=store.getState();
+ }
+ return props;
+ }
render() {
let { Component,pageProps} = this.props;
+ let state = this.store.getState();
return (
+ <Provider store={this.store}>
<style jsx>
{
`li{
display:inline-block;
margin-left:10px;
line-height:31px;
}`
}
</style>
<div>
<header>
<img src="/images/jglogo.png" className={_appStyle.logo}/>
<ul>
<li><Link href="/"><a>首页</a></Link></li>
<li><Link href="/user/list" ><a>用户管理</a></Link></li>
<li><Link href="/profile"><a>个人中心</a></Link></li>
+ <li>
+ {
+ state.currentUser ? <span>{state.currentUser.name}</span>:<Link href="/login">登录</Link>
+ }
+ </li>
</ul>
{
}
</header>
<Component {...pageProps} />
<footer style={{ textAlign: 'center' }} >@copyright 珠峰架构</footer>
</div>
+ </Provider>
)
}
}
export default LayoutApp;
store\action-types.js
export const SET_USER_INFO = 'SET_USER_INFO';//设置用户信息
store\reducer.js
import * as types from './action-types';
let initState = {
currentUser: null
}
const reducer = (state = initState, action) => {
switch (action.type) {
case types.SET_USER_INFO:
return { currentUser: action.payload }
default:
return state;
}
}
export default reducer;
store\index.js
import { createStore } from 'redux';
import reducer from './reducer';
export default function (initialState) {
return createStore(reducer, initialState);
}
事件 | 触发时机 |
---|---|
routeChangeStart(url) | 路由开始切换时触发 |
routeChangeComplete(url) | 完成路由切换时触发 |
routeChangeError(err, url) | 路由切换报错时触发 |
beforeHistoryChange(url) | 浏览器 history 模式开始切换时触发 |
hashChangeStart(url) | 开始切换 hash 值但是没有切换页面路由时触发 |
hashChangeComplete(url) | 完成切换 hash 值但是没有切换页面路由时触发 |
import App from 'next/app';
import Link from 'next/link';
import _appStyle from './_app.module.css';
import '../styles/global.css';
import { Provider } from 'react-redux';
import axios from '../utils/axios';
import createStore from '../store';
import * as types from '../store/action-types';
+import router from 'next/router';
function getStore(initialState) {
if (typeof window == 'undefined') {
return createStore(initialState);//如果是服务器端,每次都返回新的仓库
} else {
if (!window._REDUX_STORE_) {
window._REDUX_STORE_ = createStore(initialState);
}
return window._REDUX_STORE_;
}
}
class LayoutApp extends App{
+ state = { loading: false }
constructor(props){
super(props);
this.store = getStore(props.initialState);//3.后台用新状重新创建新仓库
//4.初始状态序列化后发给了客户端,在客户端重新创建新的仓库
}
static async getInitialProps({ Component, ctx }) {
let store = getStore();//1.后台创建新仓库 5.每次切换路由都会执行此方法获取老仓库
if (typeof window == 'undefined') {//2.后台获取用户信息
let options = { url: '/api/currentUser' };
if (ctx.req&&ctx.req.headers.cookie) {
options.headers = options.headers || {};
options.headers.cookie = ctx.req.headers.cookie;
}
let response = await axios(options).then(res=>res.data);
if (response.success) {
store.dispatch({ type: types.SET_USER_INFO, payload: response.data });
}
}
let pageProps = {};
if (Component.getInitialProps)
pageProps = await Component.getInitialProps(ctx);
let props = { pageProps};
if (typeof window == 'undefined') {//后台获取用赋值状态
props.initialState=store.getState();
}
return props;
}
+ componentDidMount() {
+ this.routeChangeStart = (url) => {
+ this.setState({ loading: true });
+ };
+ router.events.on('routeChangeStart', this.routeChangeStart);
+ this.routeChangeComplete = (url) => {
+ this.setState({ loading: false });
+ };
+ router.events.on('routeChangeComplete', this.routeChangeComplete);
+ }
+ componentWillUnmount() {
+ router.events.off('routeChangeStart', this.routeChangeStart)
+ router.events.off('routeChangeStart', this.routeChangeComplete)
+ }
render() {
let { Component,pageProps} = this.props;
let state = this.store.getState();
return (
<Provider store={this.store}>
<style jsx>
{
`li{
display:inline-block;
margin-left:10px;
line-height:31px;
}`
}
</style>
<div>
<header>
<img src="/images/jglogo.png" className={_appStyle.logo}/>
<ul>
<li><Link href="/"><a>首页</a></Link></li>
<li><Link href="/user/list" ><a>用户管理</a></Link></li>
<li><Link href="/profile"><a>个人中心</a></Link></li>
<li>
{
state.currentUser ? <span>{state.currentUser.name}</span>:<Link href="/login">登录</Link>
}
</li>
</ul>
{
}
</header>
+ {
+ this.state.loading ? <div>切换中......</div> : <Component {...pageProps} />
+ }
<footer style={{ textAlign: 'center' }} >@copyright 珠峰架构</footer>
</div>
</Provider>
)
}
}
export default LayoutApp;
pages\profile.js
+import router from 'next/router';
+import { connect } from 'react-redux';
+import axios from '../utils/axios';
+function Profile(props) {
+ let { currentUser } = props;
+ return (
+ <div>
+ <p>当前登录用户:{currentUser.name}</p>
+ <button onClick={() => router.back()}>返回</button>
+ </div>
+ )
+}
+Profile.getInitialProps = async function (ctx) {
+ let options = { url: '/api/currentUser' };
+ if (ctx.req && ctx.req.headers.cookie) {
+ options.headers = options.headers || {};
+ options.headers.cookie = ctx.req.headers.cookie;
+ }
+ let response = await axios(options).then(res=>res.data);
+ if (response.success) {
+ return {currentUser:response.data};
+ } else {
+ if (ctx.req) {
+ ctx.res.writeHead(303, { Location: '/login' })
+ ctx.res.end()
+ } else {
+ router.push('/login');
+ }
+ return {};
+ }
+}
+
+const WrappedProfile = connect(
+ state => state
+)(Profile);
+export default WrappedProfile;
pages_document.js
import Document, { Html, Head, Main, NextScript } from 'next/document';
class CustomDocument extends Document {
static async getInitialProps(ctx) {
const props = await Document.getInitialProps(ctx);
return { ...props };
}
render() {
return (
<Html>
<Head>
<style>
{
`
*{
padding:0;
margin:0;
}
`
}
</style>
</Head>
<body>
<Main />
<NextScript />
</body>
</Html>
)
}
}
export default CustomDocument;
pages\index.js
import Head from 'next/head'
export default function (props) {
return (
<div>
<Head>
<title>首页</title>
<meta name="description" content="这是首页" />
</Head>
<p>Home</p>
</div>
)
}
pages\user.js
import Link from 'next/link';
export default function ({users}) {
return (
<ul>
{
users.map(user=>(
<li key={user.id}><Link href={`/user/detail/${user.id}`}>{user.name}</Link></li>
))
}
</ul>
)
}
//每个请求都会调用
export async function getServerSideProps() {
const res = await fetch('http://localhost:4000/api/users').then(res=>res.json());
return {
props: {
users:res.data
},
}
}
pages\user\list.js
import Link from 'next/link';
export default function ({users}) {
return (
<ul>
{
users.map(user=>(
<li key={user.id}><Link href={`/user/detail/${user.id}`}>{user.name}</Link></li>
))
}
</ul>
)
}
// 这个函数在编译阶段被调用
export async function getStaticProps() {
const res = await fetch('http://localhost:4000/api/users').then(res=>res.json());
return {
props: {
users:res.data
},
}
}
pages\user\detail[id].js
export default function ({user}) {
return (
<div>
<p>ID:{user.id}</p>
<p>name:{user.name}</p>
</div>
)
}
export async function getStaticPaths() {
const res = await fetch('http://localhost:4000/api/users').then(res=>res.json());
const users = res.data;
const paths = users.map(user=>`/user/detail/${user.id}`);
return {paths,fallback:false}
}
export async function getStaticProps({params}) {
console.log('params',params,new Date().toTimeString());
const res = await fetch(`http://localhost:4000/api/users/${params.id}`).then(res=>res.json());
return {
props: {
user:res.data
}
}
}
npm run build
npm run start
npm run build
start.js
const next = require('next');
const app = next({ dev:false });
const handler = app.getRequestHandler();
app.prepare().then(() => {
let express = require("express");
let bodyParser = require("body-parser");
let {UserModel} = require('./model');
let session = require("express-session");
let config = require('./config');
let MongoStore = require('connect-mongo')(session);
let app = express();
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
app.use(
session({
secret: config.secret,
resave: false,
saveUninitialized: true,
store: new MongoStore({
url: config.dbUrl,
mongoOptions: {
useNewUrlParser: true,
useUnifiedTopology: true
}
})
})
);
app.get('/api/users', async (req, res) => {
let users = await UserModel.find();
users = users.map(user=>user.toJSON());
res.send({ success:true, data: users });
});
app.get('/api/users/:id', async (req, res) => {
let user = await UserModel.findById(req.params.id);
res.send({ success:true, data: user.toJSON() });
});
app.post('/api/register', async (req, res) => {
let user = req.body;
user = await UserModel.create(user);
res.send({ success:true, data: user.toJSON() });
});
app.post('/api/login', async (req, res) => {
let user = req.body;
let dbUser = await UserModel.findOne(user);
if (dbUser) {
req.session.currentUser = dbUser.toJSON();
res.send({ success:true, data: dbUser.toJSON() });
} else {
res.send({ success:false, error: '登录失败' });
}
});
app.get('/api/currentUser', async (req, res) => {
let currentUser = req.session.currentUser;
if (currentUser) {
res.send({ success:true, data: currentUser });
} else {
res.send({ success:false, error: '当前用户未登录' });
}
});
app.get('*', async (req, res) => {
await handler(req, res);
})
app.listen(3000, () => {
console.log('服务器在3000端口启动!');
});
});
config.js
module.exports = {
secret: 'zhufeng',
dbUrl: "mongodb://127.0.0.1/zhufengnext2"
}
model.js
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const config = require('./config');
const conn = mongoose.createConnection(config.dbUrl, { useNewUrlParser: true, useUnifiedTopology: true });
const UserModel = conn.model('User', new Schema({
name: { type: String },
password: { type: String },
},{ timestamps: true , toJSON: {
transform: function (_doc, result) {
result.id = result._id;
delete result._id;
return result;
}
}}));
module.exports = {
UserModel
}
yarn add express body-parser cors express-session connect-mongo mongoose
POST /api/register
变量名 | 类型 | 说明 |
---|---|---|
name | 字符串 | 用户名 |
password | 字符串 | 密码 |
变量名 | 类型 | 说明 |
---|---|---|
success | 布尔值 | 是否成功 |
data | 对象 | 注册成功之后的对象 |
示例
{
"success": true,
"data": {
"id": 1,
"name": "张三",
"password": "123456"
}
}
POST /api/login
变量名 | 类型 | 说明 |
---|---|---|
name | 字符串 | 用户名 |
password | 字符串 | 密码 |
变量名 | 类型 | 说明 |
---|---|---|
success | 布尔值 | 是否成功 |
data | 对象 | 登录成功之后的对象 |
示例
{
"success": true,
"data": {
"id": 1,
"name": "张三",
"password": "123456"
}
}
GET /api/currentUser
变量名 | 类型 | 说明 |
---|---|---|
success | 布尔值 | 是否成功 |
data | 对象 | 当前用户对象 |
示例
{
"success": true,
"data": {
"id": 1,
"name": "张三",
"password": "123456"
}
}
GET /api/users
变量名 | 类型 | 说明 |
---|---|---|
success | 布尔值 | 是否成功 |
data | 对象数组 | 用户对象数组 |
示例
{
"success": true,
"data": [
{
"id": 1,
"name": "张三",
"password": "123456"
},
{
"id": 2,
"name": "李四",
"password": "123456"
}
]
}
GET /api/users/:id
变量名 | 类型 | 说明 |
---|---|---|
success | 布尔值 | 是否成功 |
data | 对象 | 用户对象 |
示例
{
"success": true,
"data": {
"id": 1,
"name": "张三",
"password": "123456"
}
}
let express = require("express");
let bodyParser = require("body-parser");
let cors = require("cors");
let {UserModel} = require('./model');
let session = require("express-session");
let config = require('./config');
let MongoStore = require('connect-mongo')(session);
let app = express();
app.use(
cors({
origin: ['http://localhost:3000'],
credentials: true,
allowedHeaders: "Content-Type,Authorization",
methods: "GET,HEAD,PUT,PATCH,POST,DELETE,OPTIONS"
})
);
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
app.use(
session({
secret: config.secret,
resave: false,
saveUninitialized: true,
store: new MongoStore({
url: config.dbUrl,
mongoOptions: {
useNewUrlParser: true,
useUnifiedTopology: true
}
})
})
);
app.get('/api/users', async (req, res) => {
let users = await UserModel.find();
users = users.map(user=>user.toJSON());
res.send({ code: 0, data: users });
});
app.get('/api/users/:id', async (req, res) => {
let user = await UserModel.findById(req.params.id);
res.send({ code: 0, data: user.toJSON() });
});
app.post('/api/register', async (req, res) => {
let user = req.body;
user = await UserModel.create(user);
res.send({ code: 0, data: user.toJSON() });
});
app.post('/api/login', async (req, res) => {
let user = req.body;
let dbUser = await UserModel.findOne(user);
if (dbUser) {
req.session.currentUser = dbUser.toJSON();
res.send({ code: 0, data: dbUser.toJSON() });
} else {
res.send({ code: 1, error: '登录失败' });
}
});
app.get('/api/currentUser', async (req, res) => {
let currentUser = req.session.currentUser;
if (currentUser) {
res.send({ code: 0, data: currentUser });
} else {
res.send({ code: 1, error: '当前用户未登录' });
}
});
app.listen(4000, () => {
console.log('服务器在4000端口启动!');
});
api\config.js
module.exports = {
secret: 'zhufeng',
dbUrl: "mongodb://127.0.0.1/zhufengnext2"
}
server\model.js
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const config = require('./config');
const conn = mongoose.createConnection(config.dbUrl, { useNewUrlParser: true, useUnifiedTopology: true });
const UserModel = conn.model('User', new Schema({
name: { type: String },
password: { type: String }
},{ timestamps: true , toJSON: {
transform: function (_doc, result) {
result.id = result._id;
delete result._id;
return result;
}
}}));
module.exports = {
UserModel
}