1.环境准备
安装脚手架:全局安装
作用:在任何一个目录下都能通过vue
命令创建项目
注意:低版本的node
执行这行命令可能会报错,需要升级版本
npm install -g @vue/cli
创建项目
在指定的目录下,执行命令
作用:通过网页页面方式创建vue
项目
vue ui
勾选 route
、vuex
点击创建之后,会在后台自动创建依赖
安装devtools
方便调试 vue
项目
注意:有些高版本的 devtools 在vue2里面用不了,需要选择合适的版本
启动项目
npm run serve
修改端口
默认启动端口是8080,自定义修改
配置网址
Configuration | webpackwebpack is a module bundler. Its main purpose is to bundle JavaScript files for usage in a browser, yet it is also capable of transforming, bundling, or packaging just about any resource or asset.https://webpack.js.org/configuration/
添加代理
解决跨域问题,添加代理
2.项目结构
解释:
-
assets:静态资源
-
components:可重用组件
-
router:路由
-
store:数据共享
-
view:视图组件
-
App.vue:最顶层根组件
-
main.js:项目入口
以后还会添加
-
api:跟后台交互,发送 fetch,xhr请求,接收响应
-
plugins:插件
3.入门案例
vue
的组件文件以 .vue
结尾,每个组件由三部分组成
<template></template><script></script><style></style>
解释:
-
template模板部分,由它生成 html 代码
-
script代码部分,控制模板的数据来源和行为
-
style样式部分,一般不怎么关心
代码示例:
<template><h1> {{ msg }}</h1>
</template><script>const options = {data: function() {return {msg: 'Hello Vue2'}}}export default options;
</script>
其中 定义和导出 options 对象是约定好的。
整个流程
4.文本插值 {{}}
代码示例
<template><div><h1>{{ name }}</h1><h2>{{ age > 18 ? '成年' : '未成年'}}</h2></div>
</template><script>const options = {data: function() {return {name : "李嘉图",age : 18}}}export default options;
</script>
5.属性绑定 v-bind
代码示例
<template><div><input type="text" :value="name"><br><input type="text" :value="age"><br><input type="date" :value="brithday"></div>
</template><script>const options = {data: function() {return {name : "李嘉图",brithday : "1999-09-09",age : 18}}}export default options;
</script>
6.事件绑定 v-on
代码示例
<template><div><input type="button" value="点我加一" @click="m1"><input type="button" value="点我减一" @click="m2"></div>
</template><script>const options = {data: function() {return {count : 0}},methods: {m1() {this.count++;console.log(this.count);},m2() {this.count--;console.log(this.count);}}}export default options;
</script>
7.双向绑定 v-model
一般在表单中使用这种双向绑定
代码示例
<template><div><input type="text" v-model="name"><br><input type="text" v-model="age"></div>
</template><script>const options = {data: function() {return {name: "李嘉图",age: 18}},methods: {}}export default options;
</script>
如果F12看不到 vue devtools,把配置打开
8.计算属性 computed
最重要的不同点,computed有缓存,只需要执行一次代码,而方法调用每调用一次需要执行一遍代码。
9.axios
axios
它的底层是用了 XMLHttpRequest(xhr)
方式发送请求和接收响应,xhr
相对于之前讲过的 fetch api
来说,功能更加强大,但由于是比较老的 api
,不支持 promise
,axios
对xhr
进行了封装,使之支持 promise,并提供了对请求、响应的统一拦截。
安装
npm install axios -S
代码示例
<template><div><input type="button" value="获取远程数据" @click="sendReq()"></div>
</template><script>import axios from 'axios';const options = {data: function() {return {}},methods: {async sendReq() {const resp = await axios.get('/api/student')console.log(resp)}}}export default options;
</script>
axios发送请求
请求 | 备注 |
---|---|
axios.get(url[, config]) | 常用 |
axios.delete(url[, config]) | |
axios.head(url[, config]) | |
axios.options(url[, data[,config]]) | |
axios.post(url[, data[,config]]) | 常用 |
axios.put(url[, config]) | |
axios.patch(url[, config]) |
说明
-
config - 选项对象、例如查询参数、请求头...
-
data - 请求体数据、最常见的是 json 格式数据
axios拦截器
自己封装一个自定义的 axios
请求拦截器:在请求发送前,可以在这里添加 token
、调整请求配置等。
响应拦截器:对返回数据进行统一处理,针对不同状态码进行错误处理。
封装方法:如 get
和 post
封装可以简化调用,其他方法可以按需添加。
axiosInstance.js
import axios from 'axios';// 创建 axios 实例
const axiosInstance = axios.create({baseURL: '/api', // 你的基础路径,可以根据需要调整timeout: 5000, // 请求超时时间
});// 请求拦截器
axiosInstance.interceptors.request.use((config) => {// 在发送请求之前做一些处理// 例如:在请求头中添加 tokenconst token = localStorage.getItem('token');if (token) {config.headers['Authorization'] = `Bearer ${token}`;}console.log('请求拦截器配置:', config); // 可用于调试return config;},(error) => {// 处理请求错误console.error('请求错误:', error);return Promise.reject(error);}
);// 响应拦截器
axiosInstance.interceptors.response.use((response) => {// 在接收响应后做一些处理console.log('响应拦截器响应:', response); // 可用于调试return response.data; // 返回实际数据},(error) => {// 处理响应错误if (error.response) {// 根据不同状态码进行处理switch (error.response.status) {case 401:console.error('未授权,请重新登录');// 可以跳转到登录页面break;case 403:console.error('拒绝访问');break;case 404:console.error('请求地址出错');break;case 500:console.error('服务器内部错误');break;default:console.error('其他错误信息');}} else {console.error('网络连接错误或超时');}return Promise.reject(error);}
);// 封装 GET 请求方法
export function get(url, params) {return axiosInstance.get(url, { params });
}// 封装 POST 请求方法
export function post(url, data) {return axiosInstance.post(url, data);
}// 其他请求方法(PUT、DELETE 等)也可以封装
export function put(url, data) {return axiosInstance.put(url, data);
}export function del(url) {return axiosInstance.delete(url);
}// 默认导出 axios 实例
export default axiosInstance;
调用示例
import { get, post } from './axiosInstance';async function fetchData() {try {const response = await get('/student');console.log('数据:', response);} catch (error) {console.error('请求错误:', error);}
}
10.条件渲染 v-if v-else
代码示例
<template><div><input type="button" value="获取远程数据" @click="sendReq()"><h1>学生列表</h1><table><thead><tr><th>编号</th><th>姓名</th><th>年龄</th><th>性别</th></tr></thead><tbody><div v-if="this.students.length > 0">显示学生数据</div><div v-else>不显示学生数据</div></tbody></table></div>
</template><script>import axios from 'axios';const options = {data: function() {return {students: []}},methods: {async sendReq() {const resp = await axios.get('/api/student')console.log(resp.data)this.students = resp.data}}}export default options;
</script><style scoped>table {width: 100%;border-collapse: collapse;}th, td {border: 1px solid #ddd;padding: 8px;}th {background-color: #f2f2f2;text-align: left;}tr:nth-child(even) {background-color: #f9f9f9;}tr:hover {background-color: #f1f1f1;}
</style>
11.列表渲染 v-for
代码示例
<template><div><h1>学生列表</h1><table><thead><tr><th>编号</th><th>姓名</th><th>年龄</th><th>性别</th></tr></thead><tbody v-if="this.students.length > 0"><tr v-for="student in students" :key="student.id"><td>{{ student.id }}</td><td>{{ student.name }}</td><td>{{ student.age }}</td><td>{{ student.gender }}</td></tr></tbody></table></div>
</template><script>import axios from 'axios';const options = {data: function() {return {students: []}},methods: {async sendReq() {const resp = await axios.get('/api/student')console.log(resp.data)this.students = resp.data}},mounted() {this.sendReq()}}export default options;
</script><style scoped>table {width: 100%;border-collapse: collapse;}th, td {border: 1px solid #ddd;padding: 8px;}th {background-color: #f2f2f2;text-align: left;}tr:nth-child(even) {background-color: #f9f9f9;}tr:hover {background-color: #f1f1f1;}
</style>
12.重用组件
AddButton.vue
<template><div class="add-button"><button @click="handleAdd">增加</button></div></template><script>export default {name: 'AddButton',methods: {handleAdd() {this.$emit('add');}}}</script><style scoped>.add-button {display: inline-block;margin: 10px;}.add-button button {background-color: #4caf50; /* 绿色 */border: none;color: white;padding: 10px 20px;text-align: center;text-decoration: none;display: inline-block;font-size: 16px;margin: 4px 2px;cursor: pointer;border-radius: 8px;}.add-button button:hover {background-color: #45a049;}</style>
DeleteButton.vue
<template><div class="delete-button"><button @click="handleDelete" :disabled="!isEnabled">删除</button></div></template><script>export default {name: 'DeleteButton',props: {isEnabled: {type: Boolean,default: true}},methods: {handleDelete() {this.$emit('delete');}}}</script><style scoped>.delete-button {display: inline-block;margin: 10px;}.delete-button button {background-color: #f44336; /* 红色 */border: none;color: white;padding: 10px 20px;text-align: center;text-decoration: none;display: inline-block;font-size: 16px;margin: 4px 2px;cursor: pointer;border-radius: 8px;}.delete-button button:hover {background-color: #da190b;}.delete-button button:disabled {background-color: #ccc;cursor: not-allowed;}</style>
EditButton.vue
<template><div class="edit-button"><button @click="handleEdit">修改</button></div></template><script>export default {name: 'EditButton',methods: {handleEdit() {this.$emit('edit');}}}</script><style scoped>.edit-button {display: inline-block;margin: 10px;}.edit-button button {background-color: #2196f3; /* 蓝色 */border: none;color: white;padding: 10px 20px;text-align: center;text-decoration: none;display: inline-block;font-size: 16px;margin: 4px 2px;cursor: pointer;border-radius: 8px;}.edit-button button:hover {background-color: #0b7dda;}</style>
App.vue
<template><div><add-button @add="handleAdd"></add-button><delete-button @delete="handleDelete"></delete-button><edit-button @edit="handleEdit"></edit-button></div>
</template><script>
import AddButton from "./components/AddButton.vue";
import DeleteButton from "./components/DeleteButton.vue";
import EditButton from "./components/EditButton.vue";const options = {components: {AddButton,DeleteButton,EditButton},data: function() {return {}},methods: {handleAdd() {alert('增加操作');},handleDelete() {alert('删除操作');},handleEdit() {alert('修改操作');}},mounted: function() {}}export default options;
</script><style scoped>table {width: 100%;border-collapse: collapse;}th, td {border: 1px solid #ddd;padding: 8px;}th {background-color: #f2f2f2;text-align: left;}tr:nth-child(even) {background-color: #f9f9f9;}tr:hover {background-color: #f1f1f1;}
</style>