前端学习第三站——Vue2基础篇
目录
1. 环境准备
1.1安装脚手架
1.2 创建项目
1.3 安装 vue devtools
1.4 运行项目
2 Vue组件
2.1 文本插值
2.2 属性绑定 v-bind
2.3 事件绑定 v-on
2.4 计算属性 computed
2.5 vue 底层展示界面的原理
3. Axios
4. 列表渲染v-for和条件渲染 v-if
1. 环境准备
1.1安装脚手架
npm install -g @vue/cli
-g 参数表示全局安装,这样在任意目录都可以使用 vue 脚本创建项目
1.2 创建项目
进入到你要创建服务器的目录下,打开命令窗口,执行命令
vue ui
这个的意思就是使用图形界面向导来创建vue项目,运行后跳出此界面
选择手动配置项目
添加 vue router 和 vuex
选择版本,创建项目
这样就会在文件夹中自动生成vue项目啦~
1.3 安装 vue devtools
这是一个可以进行调试vue项目的浏览器插件,很好用
如果 谷歌应用商店进不去,可以试试以下方法。
1. 先到一个插件下载网址下载插件
下载成功后并解压后就会有下图的.crx后缀文件 。
2. 打开谷歌浏览器, 点击右上角三个点,更多工具——扩展程序
进入到如下页面,并打开右上角的开发者模式。
然后将下载好的.crx后缀文件拖进此浏览器页面中即可。
1.4 运行项目
进入项目目录,prowershell窗口,执行命令
npm run serve
如果报错,尝试用管理员身份运行prowershell,然后进入到项目目录,在执行上述命令。
修改端口
如果前端服务器默认占用了后端 8080 端口,可以进行修改
打开 vue.config.js 文件添加
const { defineConfig } = require('@vue/cli-service')
module.exports = defineConfig({// ...devServer: {port: 7070}})
添加代理
为了避免前后端服务器联调时, fetch、xhr 请求产生跨域问题,需要配置代理
打开 vue.config.js 文件添加
const { defineConfig } = require('@vue/cli-service')
module.exports = defineConfig({// ...devServer: {port: 7070,proxy: {'/api': {target: 'http://localhost:8080',changeOrigin: true}}}})
vue的项目结构
assets - 静态资源
components - 可重用组件
router - 路由
store - 数据共享
views - 视图组件
以后还会添加
api - 跟后台交互,发送 fetch、xhr 请求,接收响应
plugins - 插件
2 Vue组件
Vue 的组件文件以 .vue 结尾,每个组件由三部分组成
<template></template><script></script><style></style>
template 模板部分,由它生成 html 代码
script 代码部分,控制模板的数据来源和行为
style 样式部分,一般不咋关心
入口组件是 App.vue
先删除原有代码,来个 Hello, World 例子
<template><h1>{{msg}}</h1>
</template><script>
export default {data() {return {msg: "Hello, Vue!"}}
}
</script>
解释
export default 导出组件对象,供 main.js 导入使用
这个对象有一个 data 方法,返回一个对象,给 template 提供数据
{{}}
在 Vue 里称之为插值表达式,用来绑定 data 方法返回的对象属性,绑定的含义是数据发生变化时,页面显示会同步变化
2.1 文本插值
<template><div><h1>{{ name }}</h1><h1>{{ age > 60 ? '老年' : '青年' }}</h1></div>
</template>
<script>
const options = {data: function () {return { name: '张三', age: 70 };}
};
export default options;
</script>
{{}}
里只能绑定一个属性,绑定多个属性需要用多个{{}}
分别绑定template 内只能有一个根元素
插值内可以进行简单的表达式计算
2.2 属性绑定 v-bind
vue中可以将组件和时间进行绑定。如下代码
<template><div><!-- 属性绑定 v-bind --><div><input type="text" v-bind:value="name"/></div><div><input type="date" v-bind:value="birthday"/></div><!-- v-bind简写 v-bind可以省略 --><div><input type="text" :value="age"/></div></div></template>
<script>const options = {data:function(){return {name: '张三',birthday: '1995-01-01',age: 18}}}export default options;
</script>
简写方式:可以省略 v-bind 只保留冒号
2.3 事件绑定 v-on
<!-- 事件绑定 -->
<template><div><div><input type="button" value="点我执行m1" v-on:click="m1"></div><div><input type="button" value="点我执行m2" @click="m2"></div><div>{{count}}</div></div>
</template>
<script>
const options = {data: function () {return { count: 0 };},methods: {m1() {this.count ++;console.log("m1")},m2() {this.count --;console.log("m2")}}
};
export default options;
</script>
简写方式:可以把 v-on: 替换为 @
在 methods 方法中的 this 代表的是 data 函数返回的数据对象
2.4 计算属性 computed
<!-- 计算属性 -->
<template><div><h2>{{fullName}}</h2><h2>{{fullName}}</h2><h2>{{fullName}}</h2></div>
</template>
<script>
const options = {data: function () {return { firstName: '三', lastName: '张' };},/* methods: {fullName() {console.log('进入了 fullName')return this.lastName + this.firstName;}},*/computed: {fullName() {console.log('进入了 fullName')return this.lastName + this.firstName;}}
};
export default options;
普通方法调用必须加 (),没有缓存功能
计算属性使用时就把它当属性来用,不加 (),有缓存功能:
一次计算后,会将结果缓存,下次再计算时,只要数据没有变化,不会重新计算,直接返回缓存结果
2.5 vue 底层展示界面的原理
这里我们那App.vue举例。因为它是vue项目创建出来后自带的
首先,先将App.vue导入到main.js文件中
然后在main.js中执行了new Vue中的render
那么,这个#app的文件又是啥呢,其实在vue项目中已经给我们默认创建出来了
如图:
这就是vue将组件渲染到页面上的原理啦~
3. Axios
axios 它的底层是用了 XMLHttpRequest(xhr)方式发送请求和接收响应,xhr 相对于之前讲过的 fetch api 来说,功能更强大,但由于是比较老的 api,不支持 Promise,axios 对 xhr 进行了封装,使之支持 Promise,并提供了对请求、响应的统一拦截功能
安装
npm install axios -S
导入
import axios from 'axios'
axios 默认导出一个对象,这里的 import 导入的就是它默认导出的对象
方法
请求 | 备注 |
---|---|
axios.get(url[, config]) | ⭐️ |
axios.delete(url[, config]) | |
axios.head(url[, config]) | |
axios.options(url[, config]) | |
axios.post(url[, data[, config]]) | ⭐️ |
axios.put(url[, data[, config]]) | |
axios.patch(url[, data[, config]]) |
config - 选项对象、例如查询参数、请求头...
data - 请求体数据、最常见的是 json 格式数据
get、head 请求无法携带请求体,这应当是浏览器的限制所致(xhr、fetch api 均有限制)
options、delete 请求可以通过 config 中的 data 携带请求体
代码演示(这里包含了 发送get、post请求,发送请求头,发送是携带查询参数,用格式urlencode 请求体发送数据,用multipart格式请求体发送数据,用json格式请求体发送数据)
代码:提示,这里我配置了跨域的问题,/stu 代表localhost:8080,
前端代码:
<template>
<!-- axios --><div>{{data}}<input type="button" value="点击获取数据" @click="sendAsync"></div></template><script>
/* 导入axios */
import axios from '../util/myaxios'const options = {data:function(){return { data:''}},methods: {async sendAsync(){// 发送 get请求// const resp = await axios.get('stu/a1');//发送 post请求,需要携带一个参数对象,这里为空对象// const resp = await axios.post('stu/a2',{});//发送请求头,除了请求地址,参数,还有config对象// const resp = await axios.post('stu/a3',{},{// headers:{// Authorization: 'authorization'// }// });//发送请求时携带查询参数, url?name=xxx&age=xxx/* 第一种方法,拼接字符串 */// const name = encodeURIComponent('&&&');// const age = 18;// const resp = await axios.post(`stu/a4?name=${name}&age=${age}`);/* 只是这种方法对于特殊字符串,需要重新编码 ,例如&&&*//* 第二种方法,就是在config对象中设置param对象 这种方法会自动对特殊字符进行重新编码*/// const resp = await axios.post('stu/a4',{},{// params:{// name: '&&&',// age: 18// }// });//用请求体发送数据,格式为urlencoded// const param = new URLSearchParams();// param.append('name','张三');// param.append('age','18');// const resp = await axios.post('stu/a4',param);//用请求体发送数据,格式为 multipart// const param = new FormData();// param.append('name','李四');// param.append('age','19');// const resp = await axios.post('stu/a4',param);// //用请求体发送数据,格式为json,需在后端加上@RequestBody注解// const resp = await axios.post('stu/a5',{// name: '张三',// age: 18// });this.data = resp.dataconsole.log(resp)},sendSync(){axios.get('stu/student').then(resp =>{console.log(resp)this.data = resp.data})}}}export default options;
</script>
后端:
为了方便,代码都写在可Controller层
package com.hua.controller;import com.hua.domain.A5;
import org.apache.ibatis.annotations.Param;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;import javax.servlet.http.HttpSession;/*** @Author 华子* @Date 2023/1/8 15:51* @Version 1.0*/
@Controller
@RequestMapping("stu")
public class AxiosController {@GetMapping("/a1")@ResponseBodypublic String a1(){return "get request";}@PostMapping("/a2")@ResponseBodypublic String a2(){return "post request";}@PostMapping("/a3")@ResponseBodypublic String a3(@RequestHeader("Authorization") String authorization){System.out.println("Authorization:"+authorization);return "post request";}@PostMapping("/a4")@ResponseBodypublic String a4(String name, Integer age){System.out.println("name:"+name+",age:"+age);return "post request";}@PostMapping("/a5")@ResponseBodypublic String a5(@RequestBody A5 a5){System.out.println("name:"+a5.getName()+",age:"+a5.getAge());return "post request";}@PostMapping("/a6Set")@ResponseBodypublic String a6Set(HttpSession session){System.out.println("==========a6Set==============");System.out.println(session.getId());session.setAttribute("name","张三");return "post request";}@PostMapping("/a6Get")@ResponseBodypublic String a6Get(HttpSession session){System.out.println("==========a6Get==============");System.out.println(session.getId());System.out.println(session.getAttribute("name"));return "post request";}}
axios可以进行默认配置
创建实例
const _axios = axios.create(config);
axios 对象可以直接使用,但使用的是默认的设置
用 axios.create 创建的对象,可以覆盖默认设置,config 见下面说明
常见的 config 项有
名称 | 含义 |
---|---|
baseURL | 将自动加在 url 前面 |
headers | 请求头,类型为简单对象 |
params | 跟在 URL 后的请求参数,类型为简单对象或 URLSearchParams |
data | 请求体,类型有简单对象、FormData、URLSearchParams、File 等 |
withCredentials | 跨域时是否携带 Cookie 等凭证,默认为 false |
responseType | 响应类型,默认为 json |
例
const _axios = axios.create({baseURL: 'http://localhost:8080',withCredentials: true
});
await _axios.post('/api/a6set')
await _axios.post('/api/a6get')
生产环境希望 xhr 请求不走代理,可以用 baseURL 统一修改
希望跨域请求携带 cookie,需要配置 withCredentials: true,服务器也要配置 allowCredentials = true,否则浏览器获取跨域返回的 cookie 时会报错
这里提供一个默认写好的axios配置~
myaxios.js文件 (里头有拦截器,包括请求和响应两种拦截器)
import axios from 'axios'
const _axios = axios.create({// baseURL: 'http://localhost:8080',withCredentials: true
});// 9. 拦截器
_axios.interceptors.request.use(function (config) {// 比如在这里添加统一的 headersconfig.headers = {Authorization: 'aaa.bbb.ccc'}return config;},function (error) {return Promise.reject(error);}
);_axios.interceptors.response.use(function (response) {// 2xx 范围内走这里return response;},function (error) {if (error.response?.status === 400) {console.log('请求参数不正确');return Promise.resolve(400);} else if (error.response?.status === 401) {console.log('跳转至登录页面');return Promise.resolve(401);} else if (error.response?.status === 404) {console.log('资源未找到');return Promise.resolve(404);}// 超出 2xx, 比如 4xx, 5xx 走这里return Promise.reject(error);}
);export default _axios;
我们导入axios就可以这么写
4. 列表渲染v-for和条件渲染 v-if
这里用一个例子来展示
从后端拿去学生数据,展示到前端
<template><div><!-- <input type="button" value="点击获取数据" @click="sendAsync"> --><div class="title">学生列表</div><div class="thead"><div class="row bold"><div class="col">编号</div><div class="col">姓名</div><div class="col">性别</div><div class="col">年龄</div></div></div><div class="tbody"> <!-- 条件渲染v-if:如果读取到学生数据不为空,就展示 --><div v-if="students.length > 0"><!-- 列表渲染v-for,循环得到的学生数据并展示 --><div class="row" v-for="student of students" :keys="student.id"><div class="col">{{student.id}}</div><div class="col">{{student.name}}</div><div class="col">{{student.sex}}</div><div class="col">{{student.age}}</div></div> </div><!-- 如果为空 --><div class="row" v-else>暂无学生数据</div></div></div>
</template>
<script>import axios from '../util/myaxios'const options = {mounted: function(){this.sendAsync();},data: function(){return {students: []}},methods:{async sendAsync(){const resp = await axios.get('stu/student');console.log(resp.data.data)this.students = resp.data.data}}}export default options;
</script><style scoped>div {font-family: 华文行楷;font-size: 20px;}.title {margin-bottom: 10px;font-size: 30px;color: #333;text-align: center;}.row {background-color: #fff;display: flex;justify-content: center;}.col {border: 1px solid #f0f0f0;width: 15%;height: 35px;text-align: center;line-height: 35px;}.bold .col {background-color: #f1f1f1;}
</style>
重用组件:
主要语法就是在components文件夹中定义一个常用组件,也就是子组件
然后导入到父组件中
<script>import MyButton from '../components/MyButton.vue'const options = {components:{MyButton}}export default options;
</script>
在父组件中打上标签即可。
<template>
<!-- 可重用组件 --><div><h1>父组件</h1><div><h2>子组件</h2><my-button>1</my-button></div></div>
</template>
具体代码:
子组件MyButtons:
<template><div class="button" :class="[type,size]"><slot></slot><!-- 加入插槽,可以在父组件中添加按钮名称 --></div>
</template>
<script>
const options = {props:["type","size"]
};
export default options;
</script>
<style scoped>
.button {display: inline-block;text-align: center;border-radius: 30px;margin: 5px;font: bold 12px/25px Arial, sans-serif;padding: 0 2px;text-shadow: 1px 1px 1px rgba(255, 255, 255, .22);box-shadow: 1px 1px 1px rgba(0, 0, 0, .29), inset 1px 1px 1px rgba(255, 255, 255, .44);transition: all 0.15s ease;
}.button:hover {box-shadow: 1px 1px 1px rgba(0, 0, 0, .29), inset 1px 1px 2px rgba(0, 0, 0, .5);
}.button:active {box-shadow: inset 1px 1px 2px rgba(0, 0, 0, .8);
}.primary {background-color: #1d6ef9;color: #b5e3f1;
}.danger {background-color: rgb(196, 50, 50);color: white;
}.success {background-color: #a5cd4e;;color: #3e5706;
}.small {width: 40px;height: 20px;font-size: 10px;line-height: 20px;
}.middle {width: 50px;height: 25px;font-size: 14px;line-height: 25px;
}.large {width: 60px;height: 30px;font-size: 18px;line-height: 30px;
}
</style>
父组件:
<template>
<!-- 可重用组件 --><div><h1>父组件</h1><div><h2>子组件</h2><my-button type="primary" size="small">1</my-button><my-button type="danger" size="middle">2</my-button><my-button type="success" size="large">3</my-button></div></div>
</template>
<script>import MyButton from '../components/MyButton.vue'const options = {components:{MyButton}}export default options;
</script><style scoped>
.button {display: inline-block;text-align: center;border-radius: 30px;margin: 5px;font: bold 12px/25px Arial, sans-serif;padding: 0 2px;text-shadow: 1px 1px 1px rgba(255, 255, 255, .22);box-shadow: 1px 1px 1px rgba(0, 0, 0, .29), inset 1px 1px 1px rgba(255, 255, 255, .44);transition: all 0.15s ease;
}.button:hover {box-shadow: 1px 1px 1px rgba(0, 0, 0, .29), inset 1px 1px 2px rgba(0, 0, 0, .5);
}.button:active {box-shadow: inset 1px 1px 2px rgba(0, 0, 0, .8);
}.primary {background-color: #1d6ef9;color: #b5e3f1;
}.danger {background-color: rgb(196, 50, 50);color: white;
}.success {background-color: #a5cd4e;;color: #3e5706;
}.small {width: 40px;height: 20px;font-size: 10px;line-height: 20px;
}.middle {width: 50px;height: 25px;font-size: 14px;line-height: 25px;
}.large {width: 60px;height: 30px;font-size: 18px;line-height: 30px;
}
</style>
前端学习第三站——Vue2基础篇相关推荐
- Vue2基础篇教程合集
Vue2基础篇教程合集 点击跳转具体教程,该教程基于HTML书写,深度理解Vue如何运行. 一.Vue2基础篇-初识Vue 二.Vue2基础篇-模板语法 三.Vue2基础篇-理解MVVM模型 三.Vu ...
- [Python从零到壹] 三十七.图像处理基础篇之图像融合处理和ROI区域绘制
欢迎大家来到"Python从零到壹",在这里我将分享约200篇Python系列文章,带大家一起去学习和玩耍,看看Python这个有趣的世界.所有文章都将结合案例.代码和作者的经验讲 ...
- [Python从零到壹] 三十三.图像处理基础篇之什么是图像处理和OpenCV配置
欢迎大家来到"Python从零到壹",在这里我将分享约200篇Python系列文章,带大家一起去学习和玩耍,看看Python这个有趣的世界.所有文章都将结合案例.代码和作者的经验讲 ...
- 强化学习笔记(一)基础篇
强化学习笔记(一)基础篇 目录 1.强化学习相关概念 2.强化学习与监督学习和非监督学习的区别 3.强化学习分类 4.三对重要概念 目录 写在前面:本文系小编学习邹伟老师等人编著的<强化学习&g ...
- android前端怎样php后台交互(基础篇)
android前端怎样php后台交互(基础篇) android客户端和php+mysql+apache搭建的服务器之间的简单交互,实现登入功能. 实现原理就是android客户端发送请求,传给服务器登 ...
- J2EE学习笔记三:EJB基础概念和知识 收藏
J2EE学习笔记三:EJB基础概念和知识 收藏 EJB正是J2EE的旗舰技术,因此俺直接跳到这一章来了,前面的几章都是讲Servlet和JSP以及JDBC的,俺都懂一些.那么EJB和通常我们所说的Ja ...
- FPGA系统性学习笔记连载_Day1数字电路基础篇
FPGA系统性学习笔记连载_Day1数字电路基础篇 连载<叁芯智能FPGA设计与研发就业班-第一天> <数字电路基础1> 原创作者:紫枫术河 转载请联系群主授权,否则追究责任 ...
- HFSS学习笔记(一)基础篇 操作界面简介和使用前的准备工作
HFSS学习笔记(一)基础篇 操作界面简介和使用前的准备工作 一.HFSS工作界面简介 各区域的功能: 二.设计的步骤 1.创建工程文件 2.进行设计前的准备工作 一.HFSS工作界面简介 各区域的功 ...
- 学习C++:C++进阶(三)CMake基础篇---用一个小型项目了解CMake及环境构建
V1.1 于2022年7月15日第二次修改:添加了比较多的解释图,解读了各类库的CMakelist.txt文件 目录 第一部分 基础篇(Basics) 1.0 本部分主要学什么(Intro) 1.1 ...
最新文章
- Mol2vec | 一种无监督机器学习方法的分子亚结构向量表示
- 反思快乐:融入 真实 不回忆 聪明应对
- 《重构:改善既有代码的设计》阅读笔记
- Oracle的不完全恢复
- Linux系统的操作命令
- python生成器yield原理_Python generator生成器和yield表达式详解
- python设计模式5-原型模式
- Tomcat控制台乱码
- 系统学习 TypeScript(四)——变量声明的初步学习
- 本周小结!(二叉树系列三)
- 51cto,一个创造能让IT人员成长的论坛
- 计算机控制系统a卷-答案,微型计算机控制技术试卷附标准答案A
- 道指30只成分股的股价及历史股价抓取分析
- Vfed大橙子模板 苹果cms自动采集 的方法
- 【转】艺术设计、数字媒体、环艺、影视动画、摄影、广编专业…等…视频、教程、资讯、图库、作品汇总大全
- 笔记本光驱拆解——让整个世界变得安静
- 整数规划Python
- Heart-Shaped Box
- Ipad电容笔买原装还是平替?高性价比的ipad平替电容笔推荐
- PMBOK(第六版) PMP笔记——《九》第九章(项目资源管理)