美文网首页
基于vue-cli实现一个全栈项目

基于vue-cli实现一个全栈项目

作者: 梦想家小洋 | 来源:发表于2019-11-18 16:11 被阅读0次

    使用js实现一个全栈的项目:向我提问,以前使用html静态页面实现的(https://github.com/AprilJoy/bulma),这次使用vue实现前端代码,效果如下

    image.png

    创建vue cli 工程

    vue create example
    

    启动vue 的server

    npm run serve
    

    安装vue 依赖

    npm install axios vue-router vue-axios --save
    
    npm install bootstrap --save
    

    在main.js 里引入bootstrap 4 的css文件

    import Vue from "vue";
    import App from "./App.vue";
    import router from "./router";
    import store from "./store";
    import "bootstrap/dist/css/bootstrap.min.css";
    
    
    Vue.config.productionTip = false;
    
    
    new Vue({
      router,
      store,
      render: h => h(App)
    
    }).$mount("#app");
    

    创建 vue component

    在src > components 文件夹下创建文件

    1. HomeComponent.vue
    2. CreateComponent.vue
    3. EditComponent.vue
    4. IndexComponent.vue

    在 HomeComponent.vue 文件中添加如下代码

    //Home
    <template>
      <div class="row justify-content-center">
        <div class="col-md-8">
          <div class="card card-default">
            <div class="card-header">Home Component</div>
    
    
            <div class="card-body">I'm the Home Component component.</div>
          </div>
        </div>
      </div>
    </template>
    <script>
    export default {};
    

    </script>

    在 App.vue 中引入 HomeComponent.vue 文件

    <template>
      <div id="app">
        <HomeComponent />
      </div>
    </template>
    
    
    <script>
    import HomeComponent from "./components/HomeComponent.vue";
    
    
    export default {
      name: "app",
      components: {
        HomeComponent
      }
    };
    

    </script>

    其他几个component文件类似

    配置 vue-router

    在router.js 文件中添加以下内容

    import Vue from "vue";
    import Router from "vue-router";
    
    
    Vue.use(Router);
    
    
    import HomeComponent from "./components/HomeComponent.vue";
    import CreateComponent from "./components/CreateComponent.vue";
    import IndexComponent from "./components/IndexComponent.vue";
    import EditComponent from "./components/EditComponent.vue";
    
    
    const routes = [
      {
        name: "home",
        path: "/",
        component: HomeComponent
      },
      {
        name: "create",
        path: "/create",
        component: CreateComponent
      },
      {
        name: "posts",
        path: "/posts",
        component: IndexComponent
      },
      {
        name: "edit",
        path: "/edit/:id",
        component: EditComponent
      }
    ];
    
    
    export default new Router({
      mode: "history",
      routes: routes
    

    });

    在App.vue中添加 <router-view></router-view>,这样就回根据路由的地址渲染出对应的component

    <template>
      <div id="app">
        <router-view></router-view>
      </div>
    </template>
    
    
    <script>
    export default {
      name: "app",
      components: {}
    };
    

    </script>

    可以通过下列地址验证一下效果

    1. http://localhost:8080/create
    2. http://localhost:8080/posts
    3. http://localhost:8080/edit/21

    创建导航栏

    在 App.vue 中添加如下代码

    // App.vue
    
    
    <template>
      <div class="container">
        <nav class="navbar navbar-expand-sm bg-dark navbar-dark">
          <ul class="navbar-nav">
            <li class="nav-item">
              <router-link to="/" class="nav-link">Home</router-link>
            </li>
            <li class="nav-item">
              <router-link to="/create" class="nav-link">Create Post</router-link>
            </li>
            <li class="nav-item">
              <router-link to="/posts" class="nav-link">Posts</router-link>
            </li>
          </ul>
        </nav>
        <br />
        <transition name="fade">
          <router-view></router-view>
        </transition>
      </div>
    </template>
    
    
    <style>
    .fade-enter-active,
    .fade-leave-active {
      transition: opacity 0.2s;
    }
    .fade-enter,
    .fade-leave-active {
      opacity: 0;
    }
    </style>
    
    
    <script>
    export default {
      name: "app",
      components: {}
    };
    </script>
    

    创建想我提问的表单

    // CreateComponent.vue
    
    <template>
      <div>
        <h1>Create A Post</h1>
        <form @submit.prevent="addPost">
          <div class="row">
            <div class="col-md-6">
              <div class="form-group">
                <label>Post Title:</label>
                <input type="text" class="form-control" v-model="post.title">
              </div>
            </div>
            </div>
            <div class="row">
              <div class="col-md-6">
                <div class="form-group">
                  <label>Post Body:</label>
                  <textarea class="form-control" v-model="post.body" rows="5"></textarea>
                </div>
              </div>
            </div><br />
            <div class="form-group">
              <button class="btn btn-primary">Create</button>
            </div>
        </form>
      </div>
    </template>
    
    <script>
        export default {
            data(){
            return {
              post:{}
            }
        },
        methods: {
          addPost(){
            console.log(this.post);
          }
        }
      }
    </script>
    

    创建nodejs的后台server

    安装插件

    npm install nodemon --save-dev
    

    body-parser:用于解析数据
    core: 用于解决跨域的问题

    nodemon:实时更新后台server代码,不用每次更改代码后刷新

    在api目录下新建server.js文件

    const express = require('express');
    const app = express();
    const bodyParser = require('body-parser');
    const PORT = 4000;
    const cors = require('cors');
    
    app.use(cors());
    app.use(bodyParser.urlencoded({extended: true}));
    app.use(bodyParser.json());
    
    app.listen(PORT, function(){
      console.log('Server is running on Port:',PORT);
    });
    

    新建mongo数据库并连接

    新建DB.js,存放数据库配置

    module.exports = {
      DB: "mongodb://localhost:8900/test"
    }
    

    server.js文件添加如下内容

    const express = require("express");
    const app = express();
    const bodyParser = require("body-parser");
    const PORT = 4000;
    const cors = require("cors");
    
    
    const mongoose = require("mongoose");
    const config = require("./DB.js");
    
    
    mongoose.Promise = global.Promise;
    mongoose.connect(config.DB, { useNewUrlParser: true }).then(
      () => {
        console.log("Database is connected");
      },
      err => {
        console.log("Can not connect to the database" + err);
      }
    );
    
    
    app.use(cors());
    app.use(bodyParser.urlencoded({ extended: true }));
    app.use(bodyParser.json());
    
    
    app.listen(PORT, function() {
      console.log("Server is running on Port:", PORT);
    });
    

    创建Mongoose的schema

    在文件post.model.js file中新建如下内容,用于定义数据库中的数据结构。这部分定义的Post会在下面的路由文件中用到

    // post.model.js
    
    
    const mongoose = require("mongoose");
    const Schema = mongoose.Schema;
    
    
    // Define collection and schema for Post
    let Post = new Schema(
      {
        title: {
          type: String
        },
        body: {
          type: String
        }
      },
      {
        collection: "posts"
      }
    
     );
    
    
    module.exports = mongoose.model("Post", Post);
    

    定义node server 的路由

    创建CRUD的操作代码在路由文件post.route.js中

    const express = require("express");
    let postRoutes = express.Router();
    
    
    // Require Post model in our routes module
    let Post = require("./post.model");
    
    
    // Defined store route
    postRoutes.post("/add", function(req, res) {
      let post = new Post(req.body);
      console.log(post);
      post
        .save()
        .then(() => {
          res.status(200).json({ business: "business in added successfully" });
        })
        .catch(() => {
          res.status(400).send("unable to save to database");
        });
    });
    
    
    // Defined get data(index or listing) route
    postRoutes.route("/").get(function(req, res) {
      console.log("erro");
      Post.find(function(err, posts) {
        if (err) {
          res.json(err);
        } else {
          res.json(posts);
        }
      });
    });
    
    
    // Defined edit route
    postRoutes.route("/edit/:id").get(function(req, res) {
      let id = req.params.id;
      Post.findById(id, function(err, post) {
        if (err) {
          res.json(err);
        }
        res.json(post);
      });
    });
    
    
    //  Defined update route
    postRoutes.route("/update/:id").post(function(req, res) {
      Post.findById(req.params.id, function(err, post) {
        if (!post) res.status(404).send("data is not found");
        else {
          post.title = req.body.title;
          post.body = req.body.body;
          post
            .save()
            .then(() => {
              res.json("Update complete");
            })
            .catch(() => {
              res.status(400).send("unable to update the database");
            });
        }
      });
    });
    
    
    // Defined delete | remove | destroy route
    postRoutes.route("/delete/:id").delete(function(req, res) {
      Post.findByIdAndRemove({ _id: req.params.id }, function(err) {
        if (err) res.json(err);
        else res.json("Successfully removed");
      });
    });
    
    
    module.exports = postRoutes;
    在文件server.js中添加
    app.use("/posts", postRoute);
    

    至此,server端内容搭建完毕,下面通过引入axios插件,实现前端向后端发起请求的功能

    引入axios发送网络请求

    import VueAxios from 'vue-axios';
    import axios from 'axios';
    
    Vue.use(VueAxios, axios);
    

    现在一共有3个server正在运行

    1. Vue development server
    2. Node.js server
    3. MongoDB server

    现在route.js文件的内容入下

    import Vue from "vue";
    import Router from "vue-router";
    
    
    Vue.use(Router);
    
    
    import VueAxios from "vue-axios";
    import axios from "axios";
    
    
    Vue.use(VueAxios, axios);
    
    
    import HomeComponent from "./components/HomeComponent.vue";
    import CreateComponent from "./components/CreateComponent.vue";
    import IndexComponent from "./components/IndexComponent.vue";
    import EditComponent from "./components/EditComponent.vue";
    
    
    const routes = [
      {
        name: "home",
        path: "/",
        component: HomeComponent
      },
      {
        name: "create",
        path: "/create",
        component: CreateComponent
      },
      {
        name: "posts",
        path: "/posts",
        component: IndexComponent
      },
      {
        name: "edit",
        path: "/edit/:id",
        component: EditComponent
      }
    ];
    
    
    export default new Router({
      mode: "history",
      routes: routes
    });
    

    实现后台数据在前端展示/删除的功能

    在IndexComponent.vue文件中的代码如下

    <template>
      <div>
        <h1>Posts</h1>
        <div class="row">
          <div class="col-md-10"></div>
          <div class="col-md-2">
            <router-link :to="{ name: 'create' }" class="btn btn-primary"
              >Create Post</router-link
            >
          </div>
        </div>
        <br />
    
    
        <table class="table table-hover">
          <thead>
            <tr>
              <th>Title</th>
              <th>Body</th>
              <th>Actions</th>
            </tr>
          </thead>
          <tbody>
            <tr v-for="post in posts" :key="post._id">
              <td>{{ post.title }}</td>
              <td>{{ post.body }}</td>
              <td class="btn-w">
                <router-link
                  :to="{ name: 'edit', params: { id: post._id } }"
                  class="btn btn-primary"
                  >Edit</router-link
                >
              </td>
              <td class="btn-w">
                <button
                  class="btn btn-danger"
                  @click.prevent="deletePost(post._id)"
                >
                  Delete
                </button>
              </td>
            </tr>
          </tbody>
        </table>
      </div>
    </template>
    
    
    <script>
    export default {
      data() {
        return {
          posts: []
        };
      },
      created() {
        let uri = "http://localhost:4000/posts";
        this.axios.get(uri).then(response => {
          this.posts = response.data;
        });
      },
      methods: {
        deletePost(id) {
          let uri = `http://localhost:4000/posts/delete/${id}`;
          /* eslint-disable */
          this.axios.delete(uri).then(response => {
            this.posts.splice(this.posts.indexOf(id), 1);
          });
        }
      }
    };
    </script>
    
    
    <style scoped>
    td {
      width: 50%;
    }
    </style>
    

    相关文章

      网友评论

          本文标题:基于vue-cli实现一个全栈项目

          本文链接:https://www.haomeiwen.com/subject/vjdbictx.html