使用 Vue CLI 创建项目

  1. $ vue create 项目名称

导入 Bootstrap

  1. 安装
  1. $ npm i bootstrap
  1. src/main.js 中导入
  1. ...
  2. import 'bootstrap/dist/css/bootstrap.css'
  3. ...

VueCLI 自动将该文件内容生成 style 节点插入了页面的 head 中

不需要像以前一样在页面中通过 link 标签去加载这个样式了

一切皆模块!

创建视图组件

列表页 src/views/home.vue

  1. <template>
  2. <div>
  3. <p>Home Component</p>
  4. </div>
  5. </template>
  6. <script>
  7. export default {
  8. data() {
  9. return {};
  10. }
  11. };
  12. </script>
  13. <style scoped></style>

添加页 src/views/add.vue

<template>
  <div>
    <p>Add Component</p>
  </div>
</template>

<script>
  export default {
    data() {
      return {};
    }
  };
</script>

<style scoped></style>

编辑页 src/views/edit.vue

<template>
  <div>
    <p>Edit Component</p>
  </div>
</template>

<script>
  export default {
    data() {
      return {};
    }
  };
</script>

<style scoped></style>

导入并配置 Vue Router

  1. 安装
npm install vue-router
  1. 创建 src/router.js 文件并写入以下内容
import VueRouter from "vue-router";
import Vue from "vue";

Vue.use(VueRouter);

// 等价于 module.exports = new VueRouter({...})
export default new VueRouter({
  routes: []
});
  1. 根据你的需要配置路由表,例如下面分别配置了 Home、Add、Edit 三个路由组件导航规则
import Vue from "vue";
import VueRouter from "vue-router";

import Home from "./views/Home.vue";
import Add from "./views/Add.vue";
import Edit from "./views/Edit.vue";

Vue.use(VueRouter);

export default new VueRouter({
  routes: [
    // 路由表
    {
      // 首页
      path: "/",
      component: Home
    },
    {
      // 添加
      path: "/add",
      component: Add
    },
    {
      // 修改
      path: "/edit",
      component: Edit
    }
  ]
});
  1. src/main.js 中将路由实例配置到 Vue 实例中
...
import router from './router'
...

new Vue({
  render: h => h(App),
  // router: router,
  // es6简写
  router
}).$mount('#app')

键名 router 是 Vue 实例选项成员(就像 data、methods 一样,固定语法),值 router 是我们在 router.js 中 new 出来的 VueRouter 路由实例

  1. 最后,在 src/App.vue 中设置路由的出口
<template>
  <div id="app">
    <!-- 路由出口 -->
    <router-view></router-view>
  </div>
</template>
  1. 回到浏览器中访问不同的路由路径进行测试

接口服务

查看 第4章 和服务端交互/学习准备

功能实现

列表展示和删除

安装 axios

$ npm i axios

代码:

<template>
  <div>
    <div class="header">
      <!-- <button type="button" class="btn btn-primary">Add Hero</button> -->
      <!-- router-link 把 class 传给了自己内部封装的 a 标签了 -->
      <router-link class="btn btn-primary" to="/add">Add Hero</router-link>
    </div>
    <table class="table">
      <thead>
        <tr>
          <th scope="col">ID</th>
          <th scope="col">名称</th>
          <th scope="col">性别</th>
          <th scope="col">定位</th>
          <th scope="col">简介</th>
        </tr>
      </thead>
      <tbody>
        <tr v-for="item in heros">
          <th scope="row">{{ item.id }}</th>
          <td>{{ item.name }}</td>
          <td>{{ item.gender }}</td>
          <td>{{ item.type }}</td>
          <td>{{ item.bio }}</td>
          <td>
            <a href="#" @click.prevent="handleDelete(item)">删除</a>
            <router-link :to="'/edit/' + item.id">修改</router-link>
          </td>
        </tr>
      </tbody>
    </table>
  </div>
</template>

<script>
  // 1. npm install axios
  // 2. 哪里使用 axios,哪里就 import axios from 'axios'
  import axios from "axios";

  export default {
    data() {
      return {
        heros: []
      };
    },
    created() {
      this.loadHeros();
      // axios({
      //   method: 'GET',
      //   url: 'http://localhost:3000/heros'
      // }).then(res => {
      //   this.heros = res.data
      // })
    },

    methods: {
      loadHeros() {
        axios({
          method: "GET",
          url: "http://localhost:3000/heros"
        }).then(res => {
          this.heros = res.data;
        });
      },

      handleDelete(item) {
        if (!window.confirm("Are you sure?")) {
          return;
        }

        axios({
          method: "DELETE",
          url: `http://localhost:3000/heros/${item.id}`
        }).then(res => {
          this.loadHeros();
        });
      }
    }
  };
</script>

<style scoped>
  .header {
    padding: 10px;
  }
</style>

添加

<template>
  <div>
    <form class="form">
      <div class="form-group">
        <label for="exampleInputEmail1">名称</label>
        <input
          type="email"
          class="form-control"
          id="exampleInputEmail1"
          aria-describedby="emailHelp"
          placeholder="Enter email"
          v-model="formData.name"
        />
        <small id="emailHelp" class="form-text text-muted"
          >We'll never share your email with anyone else.</small
        >
      </div>
      <div class="form-group">
        <label for="exampleInputEmail1">性别</label>
        <input type="radio" value="男" v-model="formData.gender" /> 男
        <input type="radio" value="女" v-model="formData.gender" /> 女
      </div>
      <div class="form-group">
        <label for="exampleInputEmail1">定位</label>
        <select v-model="formData.type">
          <option value="刺客">刺客</option>
          <option value="战士">战士</option>
          <option value="辅助">辅助</option>
        </select>
      </div>
      <div class="form-group">
        <label for="exampleInputEmail1">简介</label>
        <textarea cols="30" rows="10" v-model="formData.bio"></textarea>
      </div>
      <button
        type="submit"
        class="btn btn-primary"
        @click.prevent="handleSubmit"
      >
        Submit
      </button>
    </form>
  </div>
</template>

<script>
  import axios from "axios";

  export default {
    data() {
      return {
        formData: {
          name: "",
          gender: "",
          type: "",
          bio: ""
        }
      };
    },

    methods: {
      handleSubmit() {
        axios({
          method: "POST",
          url: "http://localhost:3000/heros",
          data: this.formData
        }).then(res => {
          // 跳转到指令路由路径
          // VueRouter 提供的 API,专门用于 JavaScript 导航
          this.$router.push("/");
        });
      }
    }
  };
</script>

<style scoped>
  .form {
    padding: 10px;
  }
</style>

动态展示编辑页面

  1. 修改路由表编辑页面的导航路径
routes: [
  ...
  {
    path: '/edit/:id',
    component: Edit
  },
  ...
]
  1. 在 Home.vue 中处理修改按钮的导航地址
...
<td>
  <a href="#" @click.prevent="handleDelete(item)">删除</a>
  <router-link :to="'/edit/' + item.id">修改</router-link>
</td>
...
  1. Edit.vue 编辑页面获取动态路径参数,请求加载数据更新视图
<template>
  <div>
    <form class="form">
      <div class="form-group">
        <label for="exampleInputEmail1">名称</label>
        <input
          type="email"
          class="form-control"
          id="exampleInputEmail1"
          aria-describedby="emailHelp"
          placeholder="Enter email"
          v-model="formData.name"
        />
        <small id="emailHelp" class="form-text text-muted"
          >We'll never share your email with anyone else.</small
        >
      </div>
      <div class="form-group">
        <label for="exampleInputEmail1">性别</label>
        <input type="radio" value="男" v-model="formData.gender" /> 男
        <input type="radio" value="女" v-model="formData.gender" /> 女
      </div>
      <div class="form-group">
        <label for="exampleInputEmail1">定位</label>
        <select v-model="formData.type">
          <option value="刺客">刺客</option>
          <option value="战士">战士</option>
          <option value="辅助">辅助</option>
        </select>
      </div>
      <div class="form-group">
        <label for="exampleInputEmail1">简介</label>
        <textarea cols="30" rows="10" v-model="formData.bio"></textarea>
      </div>
      <button type="submit" class="btn btn-primary">Submit</button>
    </form>
  </div>
</template>

<script>
  import axios from "axios";

  export default {
    data() {
      return {
        formData: {
          name: "",
          gender: "",
          type: "",
          bio: ""
        }
      };
    },

    created() {
      // console.log(this.$route.params.id)
      // 不建议在生命周期中写大量的业务代码,最好都封装成 methods 函数
      // 需要的时候直接调用
      this.loadHero();
    },

    methods: {
      loadHero() {
        const id = this.$route.params.id;
        axios({
          method: "GET",
          url: `http://localhost:3000/heros/${id}`
        }).then(res => {
          console.log(res.data);
          this.formData = res.data;
        });
      }
    }
  };
</script>

<style scoped>
  .form {
    padding: 10px;
  }
</style>

提交编辑

<template>
  <div>
    <form class="form">
      <div class="form-group">
        <label for="exampleInputEmail1">名称</label>
        <input
          type="email"
          class="form-control"
          id="exampleInputEmail1"
          aria-describedby="emailHelp"
          placeholder="Enter email"
          v-model="formData.name"
        />
        <small id="emailHelp" class="form-text text-muted"
          >We'll never share your email with anyone else.</small
        >
      </div>
      <div class="form-group">
        <label for="exampleInputEmail1">性别</label>
        <input type="radio" value="男" v-model="formData.gender" /> 男
        <input type="radio" value="女" v-model="formData.gender" /> 女
      </div>
      <div class="form-group">
        <label for="exampleInputEmail1">定位</label>
        <select v-model="formData.type">
          <option value="刺客">刺客</option>
          <option value="战士">战士</option>
          <option value="辅助">辅助</option>
        </select>
      </div>
      <div class="form-group">
        <label for="exampleInputEmail1">简介</label>
        <textarea cols="30" rows="10" v-model="formData.bio"></textarea>
      </div>
      <button
        type="submit"
        class="btn btn-primary"
        @click.prevent="handleSubmit"
      >
        Submit
      </button>
    </form>
  </div>
</template>

<script>
  import axios from "axios";

  export default {
    data() {
      return {
        formData: {
          name: "",
          gender: "",
          type: "",
          bio: ""
        }
      };
    },

    created() {
      // console.log(this.$route.params.id)
      // 不建议在生命周期中写大量的业务代码,最好都封装成 methods 函数
      // 需要的时候直接调用
      this.loadHero();
    },

    methods: {
      loadHero() {
        const id = this.$route.params.id;
        axios({
          method: "GET",
          url: `http://localhost:3000/heros/${id}`
        }).then(res => {
          console.log(res.data);
          this.formData = res.data;
        });
      },
      handleSubmit() {
        const id = this.$route.params.id;
        axios({
          method: "PATCH",
          url: `http://localhost:3000/heros/${id}`,
          data: this.formData
        }).then(res => {
          // 跳转到指令路由路径
          // VueRouter 提供的 API,专门用于 JavaScript 导航
          this.$router.push("/");
        });
      }
    }
  };
</script>

<style scoped>
  .form {
    padding: 10px;
  }
</style>

编译打包

项目开发完成后,面临的就是如何将项目进行打包上线,放到服务器中。

npm run build
  • 打包结果会生成存储到 dist 目录中
  • dist 目录

    • css
    • js
    • img
    • index.html
  • 最后把打包的结果(dist)交给公司负责运维部署人员

    • 运维人员
    • 后端人员
  • 负责部署的人员会把打包结果放到一个 Web 服务器容器中去运行

    • nginx
    • Apache
    • tomcat
    • 等常见服务器软件
  • 我们可以在本地预览一下打包结果

    • 安装一个全局命令行工具,这个工具可以启动一个静态文件服务器 npm install -g serve
    • serve -s dist 启动服务
    • 然后预览打包结果文件
  • 本地预览测试没有问题之后,把 dist 压缩一下发给负责部署的人员

注意:如果打包结果有问题,不要去修改 dist 中的文件,而是修改 src 源码,完了重新打包生成 dist。

路由懒加载

参考文档:官方文档 - 路由懒加载

  • 默认情况下你第 1 次访问这个网站,就会把所有的组件资源都下载好

    • 好处:切换其它组件页面速度非常快
    • 缺点:如果组件页面比较多,会导致第 1 次加载速度慢
  • 如果你想提高第 1 次的加载速度,就是不要让它一次性的下载所有资源,解决方式就是配置路由懒加载

    • 说白了就是我看哪个页面,才下载哪个页面

总结