1、Vue (读音 /vjuː/,类似于 view) 是一套用于构建用户界面的渐进式框架。与其它大型框架不同的是,Vue被设计为可以自底向上逐层应用。
2、Vue 的核心库只关注视图层,不仅易于上手,还便于与第三方库或既有项目整合。另一方面,当与现代化的工具链以及各种支持类库结合使用时,Vue 也完全能够为复杂的单页应用提供驱动。
3、自底向上逐层应用:作为渐进式框架要实现的目标就是方便项目增量开发(即插即用)。
4、官方网址:https://cn.vuejs.org/v2/guide/
1、声明式渲染: 前后端分离是未来趋势
2、渐进式框架: 适用于各种业务需求
3、简单易学: 国人开发,中文文档,不存在语言障碍,易于理解和学习
1、在html页面使用script引入vue.js的库即可使用
远程CDN
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.js">script>
本地
<script src="vue.min.js">script>
2、Vue-CLI脚手架:使用vue.js官方提供的CLI脚本架很方便去创建vue.js工程雏形
创建一个vuetest目录,并且在目录下创建 01_vue入门程序.html 文件。
代码编写步骤:
1、定义html,引入vue.js
2、定义app div,此区域作为vue的接管区域
3、定义Vue实例,接管app区域
4、定义model(数据对象)
5、在app中展示数据
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Documenttitle>
<script src="./js/vue.min.js">script>
head>
<body>
<div id="app">
{{name}}
div>
body>
<script>
// 3.创建Vue实例
var VM = new Vue({
// 定义Vue实例挂载的元素节点,表示vue接管该div
el:"#app",
// Vue中用到的数据,定义在data中,data中可以定义复杂数据
data:{
name:"Hello Vue!!",
},
});
script>
html>
插值表达式的作用?
通常用来获取Vue实例中定义的数据(data)
属性节点中不能够使用插值表达式
1、el的作用 ?
定义 Vue实例挂载的元素节点,表示vue接管该区域
2、Vue的作用范围是什么 ?
Vue会管理el选项命中的元素,及其内部元素
3、el选择挂载点时,是否可以使用其他选择器 ?
可以,但是建议使用 ID选择器
4、是否可以设置其他的DOM元素进行关联 ?
可以但是建议选择DIV,不能使用HTML和Body标签
1、Vue中用到的数据定义在data中
2、data中可以写复杂类型
3、渲染复杂类型数据的时候,遵守js语法
<body>
<div id="app">
{{name}}<br>
{{school.name}} {{school.mobile}}<br>
<ul>
<li>{{names[0]}}li>
<li>{{names[1]}}li>
<li>{{names[2]}}li>
ul>
div>
body>
<script>
// 3.创建Vue实例
var VM = new Vue({
// 定义Vue实例挂载的元素节点,表示vue接管该div
el:"#app",
// Vue中用到的数据,定义在data中,data中可以定义复杂数据
data:{
name:"Hello Vue!!",
// 对象类型
school:{
name:"拉勾教育",
mobile:"1001001",
},
// 数组类型
names:["尼古拉斯","赵四","凯撒"]
},
});
script>
Vue中的声明式渲染,简单理解就是我们声明数据,Vue帮我们将数据渲染到HTML
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Documenttitle>
head>
<body>
<div id="app">
<h2>{{name}}h2>
div>
body>
<script src="js/vue.min.js">script>
<script>
var VM = new Vue({
el:"#app", // 挂载点
data:{
name:"Hello World! !"
},
});
script>
html>
根据官网的介绍,指令是带有 v- 前缀的特殊属性。通过指令来操作DOM元素
作用: 获取data数据,设置标签的内容
注意: 默认写法会替换全部内容,使用插值表达式{{}}可以替换指定内容
代码示例
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Documenttitle>
head>
<body>
<div id="app">
<h2>{{message}}高薪训练营h2>
<h2 v-text="message">高薪训练营h2>
<h2 v-text="message+1">h2>
<h2 v-text="message+'abc'">h2>
div>
body>
<script src="js/vue.min.js">script>
<script>
var VM = new Vue({
el:"#app",
data:{
message:"Java程序员"
}
});
script>
html>
作用: 设置元素的 innerHTML (可以向元素中写入新的标签)
代码示例
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Documenttitle>
<style>
/*
v-html指令:设置元素的innerHTML,向元素中写入标签
*/
style>
head>
<body>
<div id="app">
{{message}}
<h2 v-text="message">h2>
<h2 v-html="message">h2>
<h2 v-html="url">h2>
<h2 v-text="url">h2>
div>
body>
<script src="js/vue.min.js">script>
<script>
var VM = new Vue({
el:"#app",
data:{
message:"Java程序员",
url:"百度一下"
}
});
script>
html>
作用:为元素绑定事件,比如: v-on:click,可以简写为 @click=“方法”
绑定的方法定义在 VUE实例的method属性中
语法格式
<div id="app">
<input type="button" value="点击按钮" v-on:click="方法名">
<input type="button" value="点击按钮" @click="show">
div>
var VM = new Vue({
el:"#app",
data:{},
// 通过method 专门存放vue的方法
methods: {
show:function(){
alert("程序员在加班!!");
},
},
});
代码示例
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Documenttitle>
<style>
/*
v-on指令:作业是为元素绑定事件
*/
style>
head>
<body>
<div id="app">
<input type="button" value="点击按钮" v-on:click="show">
<input type="button" value="点击按钮" @click="show">
<input type="button" value="双击按钮" @dblclick="show">
<h2 @click="changeFood">{{food}}h2>
div>
body>
<script src="js/vue.min.js">script>
<script>
var VM = new Vue({
el:"#app",
data:{
food:"麻辣小龙虾"
},
// 通过method 专门存放vue的方法
methods: {
show:function(){
alert("程序员在加班!!");
},
changeFood:function(){
console.log(this.food);
// 使用this获取data中的数据
// 在vue中 不需要考虑如何更改DOM,重点放在修改数据上就可以,数据更新后 使用数据的那个元素会同步更新
this.food+= "真好吃";
},
},
});
script>
html>
<body>
<div id="app">
<div>
<input type="button" class="btn btn_plus">
<span>{{num}}span>
<input type="button" class="btn btn_minus">
div>
div>
body>
<script src="./js/vue.min.js">script>
<script>
var VM = new Vue({
el:"#app",
data:{
num:1,
}
});
script>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Documenttitle>
<link rel="stylesheet" href="./css/inputNum.css">
head>
<body>
<div id="app">
<div>
<input type="button" class="btn btn_plus" v-on:click="add">
<span>{{num}}span>
<input type="button" class="btn btn_minus" v-on:click="sub">
div>
div>
body>
<script src="./js/vue.min.js">script>
<script>
var VM = new Vue({
el:"#app",
data:{
num:1,
},
methods: {
add:function(){
if(this.num < 10){
this.num++;
}else{
alert("别点了!最大了!");
}
},
sub:function(){
if(this.num > 0){
this.num--;
}else{
alert("别点了!最小了!");
}
}
},
});
script>
<script>
// 案例总结
// 1.创建Vue实例时:el(挂载点),data(数据),methods(方法)
// 2.v-on 指令 作用是绑定事件,可以简写为@事件名
// 3.方法中,使用this关键字获取data中的数据
// 4.v-text 和 {{}} 都可以获取data中的数据,设置到元素中
script>
html>
1、创建VUE实例时: el(挂载点),data(数据),methods(方法)
2、v-on指令的作用是绑定事件,简写为@
3、方法中使用this关键字,获取data中的数据
4、v-text与**{{}}**的作用都是用来设置元素的文本值
作用: v-show指令, 根据真假值,切换元素的显示状态
页面准备
<body>
<div id="app">
<img src="./img/car.gif">
div>
body>
<script src="js/vue.min.js">script>
<script>
var VM = new Vue({
el:"#app"
})
script>
代码示例
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Documenttitle>
<style>
/*
v-show: 根据真假值,切换元素的显示状态
*/
style>
head>
<body>
<div id="app">
<input type="button" value="切换状态" @click="changeShow">
<img v-show="isShow" src="./img/car.gif">
div>
body>
<script src="js/vue.min.js">script>
<script>
var VM = new Vue({
el:"#app",
data:{
isShow:true,
age:19
},
methods: {
changeShow:function(){
// 触发方法,对isShow进行取反
this.isShow = !this.isShow;
},
},
});
script>
html>
v-show 指令总结
1、原理是修改元素的display,实现显示或者隐藏
2、指令后面的内容,最终会解析为布尔值
3、值为true 显示,为false 则隐藏
4、数据改变之后,显示的状态会同步更新
作用:根据表达值的真假,切换元素的显示和隐藏( 操纵dom 元素 )
代码示例
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Documenttitle>
<style>
/*
v-if指令: 根据表达式的真假,切换元素的显示和隐藏(操作的是DOM)
频繁切换就是用 v-show,反之就使用 v-if
本质上是通过操作DOM元素来切换状态
*/
style>
head>
<body>
<div id="app">
<input type="button" value="切换状态" @click="changeShow">
<img v-if="isShow" src="img/car.gif">
div>
body>
<script src="js/vue.min.js">script>
<script>
var VM = new Vue({
el:"#app",
data:{
isShow:false
},
methods: {
changeShow:function(){
this.isShow = !this.isShow;
}
},
})
script>
html>
v-if 指令总结
1、v-if 指令的作用:根据表达式的真假切换元素的显示状态
2、本质是通过操作dom元素,来切换显示状态
3、表达式为true 元素存在与dom树,为false从dom树中移除
4、频繁切换使用 v-show,反之使用v-if
作用:设置元素的属性(比如:src,title,class)
语法格式:v-bind:属性名=表达式
varVM=newVue({
el:"#app",
data:{
imgSrc:"图片地址"
}
})
v-bind可以省略,简写为冒号:
<img :src="imgSrc">
代码示例
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Documenttitle>
<style>
/*
v-bind : 设置元素的属性 src class
语法: v-bind:属性名=表达式
作用:为元素绑定属性
完整写法:v-bind:属性名 = 表达式,简写::属性=表达式
*/
style>
head>
<body>
<div id="app">
<img src="img/lagou.jpg">
<img v-bind:src="imgSrc">
<img v-bind:src="imgSrc" :title="imgTitle">
<div :style="{ fontSize: size+'px' }">v-bind指令div>
div>
body>
<script src="js/vue.min.js">script>
<script>
var VM = new Vue({
el:"#app",
data:{
imgSrc:"img/lagou.jpg",
imgTitle:"拉勾教育",
size:50
},
});
script>
html>
v-bind指令总结
v-bind 指令的作用是:为元素绑定属性
完整写法v-bind:属性名=表达式,可以简写为 :属性名=表达式
作用:根据数据生成列表结构
语法结构
<div id="app">
<ul>
<li v-for="item in arr">li>
ul>
div>
var VM = new Vue({
el:"#app",
data:{
arr:[1,2,3,4,5],
objArr:[
{name:"tom"},
{name:"jack"}
]
}
});
代码示例
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Documenttitle>
<style>
/*
v-for指令:根据数据生成列表结构
1.数组经常和v-for结合使用
2.语法格式:(item,index) in 数据
3.数组的长度变化,会同步更新到页面上,响应式的
*/
style>
head>
<body>
<div id="app">
<input type="button" value="添加数据" @click="add">
<input type="button" value="移除数据" @click="remove">
<ul>
<li v-for="(item,index) in arr">
{{index+1}}城市:{{item}}
li>
ul>
<h2 v-for="p in persons">
{{p.name}}
h2>
div>
body>
<script src="js/vue.min.js">script>
<script>
var VM = new Vue({
el:"#app",
data:{
// 数组
arr:["上海","北京","广东","深圳"],
// 对象数组
persons:[
{name:"尼古拉斯.赵四"},
{name:"莱昂纳多.小沈阳"},
{name:"多利安.刘能"},
]
},
methods: {
add:function(){
// 向数组添加元素 push
this.persons.push({name:"小斌"});
},
remove:function(){
// 移除数据
this.persons.shift();
}
},
});
script>
html>
v-for指令总结
1、v-for 指令的作用: 根据数据生成列表结构
2、数组经常和 v-for结合使用,数组有两个常用方法:
push() 向数组末尾添加一个或多个元素
shift() 把数组中的第一个元素删除
3、语法是: (item,index) in 数据
item和index 可以结合其他指令一起使用
4、数组的长度变化,会同步更新到页面上,是响应式的
代码示例
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Documenttitle>
<style>
/*
1.函数调用传参
事件绑定方法后,可以传递参数
定义方法时,需要定义形参,来接收参数
2.事件修饰符
作用:可以对事件尽心限制,.修饰符
.enter 可以限制触发的方式为 回车
*/
style>
head>
<body>
<div id="app">
<input type="button" value="礼物刷起来" @click="showTime(666,'爱你老铁!')">
<input type="text" @keyup.enter="hi">
div>
body>
<script src="js/vue.min.js">script>
<script>
var VM = new Vue({
el:"#app",
data:{},
methods:{
showTime:function(p1,p2){
console.log(p1);
console.log(p2);
},
hi:function(){
alert("你好吗?");
}
},
});
script>
html>
总结
1、事件绑定方法,可以传入自定义参数
定义方法时,需要定义形参,来接收实际的参数
2、事件的后面跟上 .修饰符可以对事件进行限制
.enter 可以限制触发的按键为回车
3、事件修饰符有许多使用时可以查询文档
MVVM 是Model-View-ViewModel 的缩写,它是一种基于前端开发的架构模式
MVVM模式将页面,分层了 M 、V、和VM,解释为:
Model: 负责数据存储
View: 负责页面展示
View Model: 负责业务逻辑处理(比如Ajax请求等),对数据进行加工后交给视图展示
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Documenttitle>
<style>
/*
MVVM:前端的架构模式
M:model 负责存储数据
V:View 负责页面的展示
VM:ViewModel 负责业务处理(MVVM模式的核心)
*/
style>
head>
<body>
<div id="app">
<h2>{{name}}h2>
div>
body>
<script src="js/vue.min.js">script>
<script>
// 创建的vue实例,就是VM ViewModel
var VM = new Vue({
el:"#app",
// data就是MVVM模式中的 model
data:{
name:"hello"
}
});
script>
html>
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-enQbVOMp-1627033941601)(E:\MarkDown\拉勾笔记\View Model)]
首先,我们将上图中的DOM Listeners和Data Bindings看作两个工具,它们是实现双向绑定的关键。
从View侧看,ViewModel中的DOM Listeners工具会帮我们监测页面上DOM元素的变化,如果有变化,则更改Model中的数据;
从Model侧看,当我们更新Model中的数据时,Data Bindings工具会帮我们更新页面中的DOM元素。
MVVM的思想,主要是为了让我们的开发更加的方便,因为MVVM提供了数据的双向绑定
作用: 获取和设置表单元素的值(实现双向数据绑定)
双向数据绑定
单向绑定:就是把Model绑定到View,当我们用JavaScript代码更新Model时,View就会自动更新。
双向绑定:用户更新了View,Model的数据也自动被更新了,这种情况就是双向绑定。
什么情况下用户可以更新View呢?
填写表单就是一个最直接的例子。当用户填写表单时,View的状态就被更新了,如果此时MVVM框架可以自动更新Model的状态,那就相当于我们把Model和View做了双向绑定:
代码示例
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Documenttitle>
<style>
/*
v-model:实现哈桑想数据绑定
单项数据绑定:将model绑定到view上,当model发生班花时,view会随之变化
双向数据绑定:view视图发生变化时,model也会随之改变
*/
style>
head>
<body>
<div id="app">
<input type="button" value="修改message" @click="update">
<input type="text" v-model="message">
<input type="text" v-model="password">
<h2>{{message}}h2>
div>
body>
<script src="js/vue.min.js">script>
<script>
// VM 业务逻辑控制
var VM = new Vue({
el:"#app",
// Model 数据存储
data:{
message:"拉勾教育训练营",
password:123
},
methods: {
update:function(){
this.message = "拉钩";
}
},
});
script>
html>
v-model指令总结
1、v-model 指令的作用是便捷的设置和获取表单元素的值
2、绑定的数据会和表单元素值相关联
3、双向数据绑定
1、功能介绍
2、新增内容
步骤
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8" />
<title>小黑记事本title>
<meta http-equiv="content-type" content="text/html; charset=UTF-8" />
<meta name="robots" content="noindex, nofollow" />
<meta name="googlebot" content="noindex, nofollow" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="stylesheet" href="../css/index.css">
head>
<body>
<section id="app">
<header class="header">
<h1>VUE记事本h1>
<input
autofocus="autofocus"
autocomplete="off"
placeholder="输入日程"
class="new-todo"
v-model="inputValue"
@keyup.enter="add"
/>
header>
<section class="main">
<ul class="listview">
<li class="todo" v-for="(item,index) in list">
<div class="view">
<span class="index">{{index+1}}span> <label>{{item}}label>
<button class="destroy">button>
div>
li>
ul>
section>
<footer class="footer">
<span class="todo-count"> <strong>1strong> items left span>
<button class="clear-completed">
Clear
button>
footer>
section>
body>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js">script>
<script>
var VM = new Vue({
el:"#app",
data:{
list:["写代码","吃饭","睡觉","打豆豆"],
inputValue:"996还是997"
},
methods: {
// 新增日程方法
add:function(){
// 将用户输入的内容添加到list
this.list.push(this.inputValue);
}
},
});
script>
html>
3、删除内容
步骤
<section class="main">
<ul class="listview">
<li class="todo" v-for="(item,index) in list">
<div class="view">
<span class="index">{{index+1}}span> <label>{{item}}label>
<button class="destroy" @click="remove(index)">button>
div>
li>
ul>
section>
4、统计操作
步骤
<footer class="footer">
<span class="todo-count"> <strong>{{list.length}}strong> items left span>
<button class="clear-completed" @click="clear()">
Clear
button>
footer>
总结:
5、清空数据
步骤:
Clearbutton>
//清空数组元素
clear:function(){
this.list=[];
}
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8" />
<title>小黑记事本title>
<meta http-equiv="content-type" content="text/html; charset=UTF-8" />
<meta name="robots" content="noindex, nofollow" />
<meta name="googlebot" content="noindex, nofollow" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="stylesheet" href="../vue_test/css/index.css">
head>
<body>
<section id="app">
<header class="header">
<h1>VUE记事本h1>
<input
autofocus="autofocus"
autocomplete="off"
placeholder="输入日程"
class="new-todo"
v-model="inputValue"
@keyup.enter="add"
/>
header>
<section class="main">
<ul class="listview">
<li class="todo" v-for="(item,index) in list">
<div class="view">
<span class="index">{{index+1}}span> <label>{{item}}label>
<button class="destroy" @click="remove(index)">button>
div>
li>
ul>
section>
<footer class="footer">
<span class="todo-count"> <strong>{{list.length}}strong> items left span>
<button class="clear-completed" @click="clear()">
Clear
button>
footer>
section>
body>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js">script>
<script>
var VM = new Vue({
el:"#app",
data:{
list:["写代码","吃饭","睡觉","打豆豆"],
inputValue:"996还是997"
},
methods: {
// 新增日程方法
add:function(){
// 将用户输入的内容添加到list
this.list.push(this.inputValue);
},
remove:function(index){
console.log(index);
// 使用 splice(元素的索引,删除几个)
this.list.splice(index,1);
},
// 清空操作
clear:function(){
this.list = [];
}
},
});
script>
html>
Ajax 是指一种创建交互式网页应用的开发技术。Ajax = 异步 JavaScript 和 XML。
Ajax 可以使网页实现异步更新。这意味着可以在不重新加载整个网页的情况下,对网页的某部分进行更新(局部更新)。传统的网页如果需要更新内容,必须重载整个网页页面。
简单记:Ajax 是一种在无需重新加载整个网页的情况下,能够更新部分网页的技术,维护用户体验性,进行网页的局部刷新
浏览器访问服务器的方式
同步访问: 客户端必须等待服务器端响应,在等待过程中不能进行其他操作
异步访问: 客户端不需要等待服务响应,等待期间,浏览器可以进行其他操作
ajax.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
Title
servlet
@WebServlet("/ajax")
public class AjaxServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 1.获取请求数据
String username = req.getParameter("name");
// 模拟业务操作
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
// 2.打印username
System.out.println(username);
resp.getWriter().write("hello hello");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doGet(req, resp);
}
}
VUE中结合网络数据进行应用的开发
目前十分流行网络请求库,专门用来发送请求,其内部还是ajax,进行封装之后使用更加方便
axios作用: 在浏览器中可以帮助我们完成 ajax异步请求的发送
Vue2.0之后,尤雨溪推荐大家用axios替换JQuery ajax
使用步骤:
1、导包
script>
2、请求方式,以GET和POST举例
GET
axios.get(地址?key=value&key2=value2).then(function(response){},function(error){});
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-b152Uy9y-1627033941606)(E:\MarkDown\拉勾笔记\axious GET)]
POST
axios.post(地址,{key:value,key2:value2}).then(function(response){},function(error){})
3、根据接口文档,访问测试接口,进行测试
接口1:随机笑话
请求地址:https://autumnfish.cn/api/joke/list
请求方法:get
请求参数:num(笑话条数,数字)
响应内容:随机笑话
接口2:用户注册
请求地址:https://autumnfish.cn/api/user/reg
请求方法:post
请求参数:username:"用户名"
响应内容:注册成功或失败
代码示例
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Documenttitle>
<style>
/*
axios总结
1.axios必须要导包
2.使用get或者post方式发送请求
3.then方法 中的回调函数,会在请求成功或者失败的时候被触发
4.通过回调函数的形参,可以获取响应的内容,或者错误信息
*/
style>
head>
<body>
<input type="button" value="get请求" id="get">
<input type="button" value="post请求" id="post">
body>
<script src="js/axios.min.js">script>
<script>
/*
随机笑话接口测试
请求地址:https://autumnfish.cn/api/joke/list
请求方法:get
请求参数:num(笑话条数,数字)
响应内容:随机笑话
*/
document.getElementById("get").onclick=function(){
axios.get("https://autumnfish.cn/api/joke/list?num=1").then(
function(resp){
// 调用成功
console.log(resp);
},
function(err){
// 调用失败
console.log(err);
}
);
}
/*
用户注册
请求地址:https://autumnfish.cn/api/user/reg
请求方法:post
请求参数:username:"用户名"
响应内容:注册成功或失败
*/
document.getElementById("post").onclick=function(){
axios.post("https://autumnfish.cn/api/user/reg",{username:"张飞"}).then(
function(resp){
console.log(resp);
},
function(error){
console.log(error);
}
);
}
script>
html>
通过vue+axios 完成一个获取笑话的案例
接口: 随机获取一条笑话
请求地址:https://autumnfish.cn/api/joke
请求方法:get
请求参数:无
响应内容:随机笑话
代码示例
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>vue+axios获取笑话title>
<style>
/*
1.axios回调函数中,this指向已经改变,无法访问data中的数据
2.解决方案:将this进行保存,回调函数中直接使用保存的this即可
*/
style>
head>
<body>
<div id="app">
<input type="button" value="点击获取一个笑话" @click="getJoke">
<p>{{joke}}p>
div>
body>
<script src="../js/vue.min.js">script>
<script src="../js/axios.min.js">script>
<script>
/*
请求地址:https://autumnfish.cn/api/joke
请求方法:get
请求参数:无
响应内容:随机笑话
*/
var VM = new Vue({
el:"#app",
data:{
joke:"笑口常开"
},
methods: {
getJoke:function(){
// 把this进行保存
var that = this;
// 异步访问
axios.get("https://autumnfish.cn/api/joke").then(
function(resp){
console.log(resp.data);
// 在回调函数内部,this无法正常使用,需要提前保存起来
console.log(that.joke); // undefined
that.joke = resp.data;
},
function(error){
}
);
}
},
});
script>
html>
案例总结
1.axios回调函数中this指向已经改变,无法访问data中的数据
2.解决方案:将this进行保存,回调函数中直接使用保存的this即可
功能分析: 回车查询
1.输入内容,点击回车 (v-on.enter)
2.访问接口,查询数据 (axios v-model)
3.返回数据,渲染数据
请求地址:http://wthrcdn.etouch.cn/weather_mini
请求方法:get
请求参数:city(要查询的城市名称)
响应内容:天气信息
自定义JS文件
作为一个标准应用程序,我们将创建VUE实例的代码,抽取到main.js 文件中
main.js
/**
* 请求地址:http://wthrcdn.etouch.cn/weather_mini
请求方法:get
请求参数:city(要查询的城市名称)
响应内容:天气信息
*/
var VM = new Vue({
el:"#app",
data:{
city:'',
// 定义数组保存天气信息
weatherList:[]
},
// 编写查询天气的方法
methods: {
searchWeather:function(){
console.log("天气查询");
console.log(this.city);
var that = this;
// 调用接口
axios.get("http://wthrcdn.etouch.cn/weather_mini?city=" + this.city).then(
function(resp){
console.log(resp.data.data.forecast);
// 获取天气信息 保存到weatherList
that.weatherList = resp.data.data.forecast;
},
function(error){
}
);
}
},
})
<html lang="en">
<head>
<meta charset="UTF-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<meta http-equiv="X-UA-Compatible" content="ie=edge"/>
<title>天气查询title>
<link rel="stylesheet" href="css/reset.css"/>
<link rel="stylesheet" href="css/index.css"/>
<style>
/*
1.应用的逻辑代码 建议与页面进行分离,适用于单独的JS编写
2.axios中 回调函数中的this 需要先保存 再使用
3.服务器返回的数据比较复杂,获取数据的时候 要注意层级结构
*/
style>
head>
<body>
<div class="wrap" id="app">
<div class="search_form">
<div class="logo">天气查询div>
<div class="form_group">
<button class="input_sub">回车查询button>
div>
div>
<ul class="weather_list">
<li v-for="item in weatherList">
<div class="info_type"><span class="iconfont">{{item.type}}span>div>
<div class="info_temp">
<b>{{item.low}}b>
~
<b>{{item.high}}b>
div>
<div class="info_date"><span>{{item.date}}span>div>
li>
ul>
div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js">script>
<script src="https://unpkg.com/axios/dist/axios.min.js">script>
<script src="js/main.js">script>
body>
html>
我们发现访问天气预报案例页面时,使用插值表达式的地方出现了闪烁问题,如何解决呢?
v-cloak指令
作用:解决插值表达式闪烁问题
当网络较慢,网页还在加载 Vue.js,而导致 Vue 来不及渲染,这时页面就会显示出 Vue 源代码。我们可以使用 v-cloak 指令来解决这一问题。
<style>
/*通过属性选择器,设置添加了v-cloak*/
[v-cloak]{
display:none;
}
style>
computed 计算属性
什么是计算属性
在Vue应用中,在模板中双向绑定一些数据或者表达式,但是表达式如果过长,或者逻辑更为复杂时,就会变得臃肿甚至难以维护和阅读,比如下面的代码:
<div>
写在双括号中的表达式太长了,不利于阅读
{{text.split(',').reverse().join(',')}}
div>
将这段操作text.split(',').reverse().join(',')放到计算属性中,最终返回一个结果值就可以
computed的作用:减少运算次数,缓存运算结果。运用于重复相同的计算。
代码示例
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Documenttitle>
<style>
/*
1.计算属性可以 减少运算次数,用于重复相同的计算
2.定义函数也可以实现与计算属性相同的效果,但是计算属性可以简化运算
*/
style>
head>
<body>
<div id="app">
<h1>{{res2}}h1>
<h1>{{res2}}h1>
div>
body>
<script src="js/vue.min.js">script>
<script>
var VM = new Vue({
el:"#app",
data:{
a:10,
b:20,
},
methods: {
res:function(){
console.log("res方法执行了!!");
return this.a + this.b;
}
},
// 使用计算属性 进行优化,减少运算次数,用于重复的运算
computed:{
res2:function(){
console.log("res方法执行了!!");
return this.a + this.b;
}
}
});
script>
html>
computed总结
- 定义函数也可以实现与计算属性相同的效果,都可以简化运算
- 定义函数也可以实现与计算属性相同的效果,但是计算属性可以简化运算
- 不同的是计算属性是基于它们的响应式依赖进行缓存的。只在相关响应式依赖发生改变时它们才会重新求值
filter 过滤器
什么是过滤器
过滤器是对即将显示的数据做进一步的筛选处理,然后进行显示,值得注意的是过滤器并没有改变原来的数据,只是在原数据的基础上产生新的数据。
数据加工车间,对值进行筛选加工。
过滤器使用位置
1、双括号插值内
{{ msg | filterA }} msg是需要处理的数据,filterA是过滤器,| 这个竖线是管道,通过这个管道将数据传输给过滤器进行过滤 加工操作
2、v-bind绑定的值的地方
<h1 v-bind:id=" msg | filterA ">{{msg}}h1>
过滤器
1、局部过滤器
需求:通过过滤器给电脑价格前面添加一个符号¥
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Documenttitle>
head>
<body>
<div id="app">
<p>电脑价格:{{price | addIcon}}p>
div>
body>
<script src="js/vue.min.js">script>
<script>
// 局部过滤器 在vue实例的内部创建filter
var VM = new Vue({
el:"#app", // 挂载点
data:{
// model
price:200
},
methods: { // 方法
},
computed:{ // 计算属性
},
// 局部过滤器
filters:{
// 定义处理函数 value = price
addIcon(value){
return "$" + value;
}
}
})
script>
html>
2、全局过滤器
需求:将用户名开头字母大写
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Documenttitle>
/*
需求:将用户名开头字母大写
总结:
1.过滤器经常被用来处理文本格式化操作
2.过滤器使用的两个位置:{{}} 插值表达式中,v-bind表达式中
3.过滤器是通过管道传输数据的 |
*/
head>
<body>
<div id="app">
<p>{{user.name | changeName}}p>
div>
body>
<script src="js/vue.min.js">script>
<script>
// 在创建vue实例之前,创建全局过滤器
Vue.filter("changeName",function(value){
// 将姓名的开头字母大写
return value.charAt(0).toUpperCase() + value.slice(1);
});
var VM = new Vue({
el:"#app",
data:{
user:{name:"jack"},
}
});
script>
html>
总结
- 过滤器常用来处理文本格式化的操作。过滤器可以用在两个地方:双花括号插值表达式和 v-bind 表达式
- 过滤器应该被添加在 JavaScript 表达式的尾部,由“管道” | 符号指示
watch 侦听器
什么是侦听器
Vue.js 提供了一个方法 watch,它用于观察Vue实例上的数据变动。
作用: 当你有一些数据需要随着其它数据变动而变动时,可以使用侦听属性
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Documenttitle>
head>
<body>
<div id="app">
<h2>计数器:{{count}}h2>
<input type="button" @click="count++" value="点我+1">
div>
body>
<script src="js/vue.min.js">script>
<script>
var VM = new Vue({
el:"#app",
data:{
count:1
},
watch:{
// 监测属性值的变化
count:function(nval,oval){
// 参数1:原来的值 参数2:新的值
alert("计数器发生变化:" + oval + " 变化为 " + nval);
}
}
});
script>
html>
案例演示
需求: 监听姓名变化,实时显示
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Documenttitle>
head>
<body>
<div id="app">
<label>名:<input type="text" v-model="firstName">label>
<label>姓:<input type="text" v-model="lastName">label>
{{fullName}}
div>
body>
<script src="js/vue.min.js">script>
<script>
var VM = new Vue({
el:"#app",
data:{
firstName:"",
lastName:"",
fullName:""
},
// 侦听器
watch:{
firstName:function(nval,oval){ // 参数 1.新值,2.旧值
this.fullName = nval + " "+this.lastName;
},
lastName:function(nval,oval){
this.fullName = this.firstName + " " + nval;
}
}
});
script>
html>
Component 组件
组件介绍
组件(Component)是自定义封装的功能。在前端开发过程中,经常出现多个网页的功能是重复的,而且很多不同的页面之间,也存在同样的功能。
我们将相同的功能进行抽取,封装为组件,这样,前端人员就可以在组件化开发时,只需要书写一次代码,随处引入即可使用。
组件系统让我们可以用独立可复用的小组件来构建大型应用,几乎任意类型的应用的界面都可以抽象为一个组件树
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-t6IqwyBg-1627033941619)(E:\MarkDown\拉勾笔记\Component 组件)]
vue的组件有两种: 全局组件 和局部组件
全局组件
语法格式:
Vue.component("组件名称",{
template:"html代码", // 组件的HTML结构代码
data(){ // 组件数据
return{}
},
methods:{ // 组件的相关的js方法
方法名(){
// 逻辑代码
}
}
})
注意:
- 组件名以小写开头,采用短横线分割命名: 例如hello-Word
- 组件中的data 必须是一个函数,注意与Vue实例中的data区分
- 在template模板中,只能有一个根元素
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Documenttitle>
head>
<body>
<div id="app">
<lagou-header>lagou-header>
div>
body>
<script src="js/vue.min.js">script>
<script>
// 定义全局组件
// 组件的命名规则:一般用短横线进行连接,左边是公司名 右边是组件的作用名称
Vue.component("lagou-header",{
template:"HTML {{msg}}
", // template模板中 只能有一个根元素
// 组件中的data是一个函数
data() {
return {
msg:"这是lagou-header组件中的数据部分"
};
},
methods: {
hello(){
alert("你好");
}
},
});
var VM = new Vue({
el:"#app",
data:{},
methods:{},
});
script>
html>
局部组件
相比起全局组件,局部组件只能在同一个实例内才能被调用。局部组件的写法和全局组件差不多。唯一不同就是:局部组件要写在Vue实例里面
newVue({
el:"#app",
components:{
组件名:{
//组件结构
template:"HTML代码",
//data数据
data(){return{msg:"xxxx"};},
},
},
});
注意:
创建局部组件,注意 components,注意末尾有 ‘s’,而全局组件是不用+ ‘s’ 的。这意味着,components 里可以创建多个组件。
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Documenttitle>
head>
<body>
<div id="app">
<web-msg>web-msg>
div>
body>
<script src="js/vue.min.js">script>
<script>
// 创建局部组件
var VM = new Vue({
el:"#app",
components:{
// 组件名
"web-msg":{
template:" {{msg1}}
{{msg2}}
",
data() {
return {
msg1:"开发ing...",
msg2:"开发完成!"
}
},
}
}
});
script>
html>
组件与模板分离
由于把html语言写在组件里面很不方便,也不太好看所以将它们分开写。
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Documenttitle>
head>
<body>
<div id="app">
<web-msg>web-msg>
div>
<template id="t1">
<div>
<button @click="show">{{msg}}button>
div>
template>
body>
<script src="js/vue.min.js">script>
<script>
var VM= new Vue({
el:"#app",
components:{
"web-msg":{
template:"#t1",
data() {
return {
msg:"点击查询"
}
},
methods: {
show(){
alert("正在查询,请稍后...");
}
},
}
}
});
script>
html>
总结:
- 上面这种写法,浏览器会把 html 里的 template 标签过滤掉。所以 template 标签的内容是不会在页面中展示的。直到它被 JS 中的 Vue 调用。
- 在 html 中,template 标签一定要有一个 id,因为通过 id 是最直接被选中的。 data 和 methods等参数,全部都要放到 Vue 实例里面写
Vue生命周期
生命周期图示
每个Vue实例在被创建之前都要经过一系列的初始化过程,这个过程就是vue的生命周期
了解生命周期的好处:
- 找错误
- 解决需求
下图展示了实例的生命周期。你不需要立马弄明白所有的东西,不过随着你的不断学习和使用,它的参考价值会越来越高。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6a4GzIfY-1627033941624)(E:\MarkDown\拉勾笔记\Vue生命周期)]
钩子函数介绍
生命周期中的钩子函数
钩子函数:钩子函数是在一个事件触发的时候,在系统级捕获到了他,然后做一些操作
函数
说明
beforeCreate()
在创建Vue实例之前,可以执行这个方法,例如加载动画操作
created()
实例创建完成,属性绑定好了,但是DOM还没有生成
beforeMount()
模板已经在内存中编辑完成了,尚未被渲染到页面中
mounted()
内存中的模板已经渲染到页面,用户已经可以看见内容
beforeUpdate()
数据更新的前一刻,组件在发生更新之前,调用的函数
updated()
updated执行时,内存中的数据已更新,并且页面已经被渲染
beforeDestory()
钩子函数在实例销毁之前调用
destoryed()
钩子函数在Vue 实例销毁后调用
案例演示
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Documenttitle>
head>
<body>
<div id="app">
<h2 id="msg">{{message}}h2>
<button @click="next">获取下一句button>
div>
body>
<script src="js/vue.min.js">script>
<script>
var VM = new Vue({
el:"#app",
data:{
message:"想当年,金戈铁马"
},
methods: {
show(){
alert("show方法执行了!");
},
next(){
this.message="气吞万里如虎!"
}
},
// beforeCreate() {
// alert("1.beforeCreate函数,在Vue对象实例化之前执行");
// console.log(this.message);
// this.show();
// },
// created() {
// alert("2.created函数执行时,组件的实例化完成,但是DOM 页面还未生成");
// console.log(this.message);
// this.show();
// },
// beforeMount() {
// alert("3.beforeMount函数执行时,模板已经在内存中编辑完成了,但是还没有被渲染到页面中");
// console.log("页面显示的内容:" + document.getElementById("msg").innerText);
// console.log("data中的数据:" + this.message);
// },
// mounted() {
// alert("4.mounted函数执行时,模板已经被渲染到页面,执行完就会显示页面");
// console.log("页面显示的内容:" + document.getElementById("msg").innerText);
// },
// beforeUpdate() {
// alert("5.beforeUpdate执行时,内存中的数据已经更新,但是还没有渲染到页面");
// console.log("页面显示的内容:" + document.getElementById("msg").innerText);
// console.log("data中的数据:" + this.message);
// },
updated() {
alert("6.updated执行时,内存中的数据已经更新了,此方法执行完显示页面");
console.log("页面显示的内容:" + document.getElementById("msg").innerText);
console.log("data中的数据:" + this.message);
},
});
script>
html>
Vue Router 路由
什么是路由?
在Web开发中,路由是指根据URL分配到对应的处理程序。路由允许我们通过不同的 URL 访问不同的内容。
通过 Vue.js 可以实现多视图单页面web应用(single page web application,SPA)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZpYTunuX-1627033941627)(E:\MarkDown\拉勾笔记\什么是路由?)]
什么是SPA ?
单页面Web应用(single page web application,SPA),就是只有一张Web页面的应用,是加载单个HTML 页面并在用户与应用程序交互时动态更新该页面的Web应用程序。
单页应用不存在页面跳转,它本身只有一个HTML页面。我们传统意义上的页面跳转在单页应用的概念下转变为了body内某些元素的替换和更新,举个例子:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PClWN1he-1627033941628)(E:\MarkDown\拉勾笔记\什么是SPA?)]
整个body的内容从登录组件变成了欢迎页组件,从视觉上感受页面已经进行了跳转。但实际上,页面只是随着用户操作,实现了局部内容更新,依然还是在index.html 页面中。
单页面应用的好处:
- 用户操作体验好,用户不用刷新页面,整个交互过程都是通过Ajax来操作。
- 适合前后端分离开发,服务端提供http接口,前端请求http接口获取数据,使用JS进行客户端渲染。
路由相关的概念
router :
是Vue.js官方的路由管理器。它和Vue.js的核心深度集成,让构建单页面应用(SPA)变得易如反掌,router就相当于一个管理者,它来管理路由。
route:
ruter相当于路由器,route就相当于一条路由。比如: Home按钮 => home内容,这是一条route,news按钮 => news内容,这是另一条路由。
routes :
是一组路由,把上面的每一条路由组合起来,形成一个数组。[{home 按钮 =>home内容 }, {about按钮 => about 内容}]
router-link组件:
router-link 是一个组件,是对标签的一个封装。该组件用于设置一个导航链接,切换不同 HTML内容。to属性为目标地址,即要显示的内容
router-view 组件:
路由导航到指定组件后,进行渲染显示页面
使用路由
- Vue.js 路由需要载入 vue-router 库
//方式1:本地导入
<script src="vue-router.min.js">script>
//方式2:CDN
<script src="https://unpkg.com/vue-router/dist/vue-router.js">script>
- 使用步骤
- 定义路由所需的组件
- 定义路由每个路由都由两部分 path (路径) 和component (组件)
- 创建router路由器实例,管理路由
- 创建Vue实例,注入路由对象,使用$mount() 指定挂载点
Vue的$mount()为手动挂载,在项目中可用于延时挂载(例如在挂载之前要进行一些其他操作、判断等),之后要手动挂载上。newVue时,el和$mount并没有本质上的不同。
- HTM代码
<body>
<div id="app">
<h1>渣浪.comh1>
<p>
<router-link to="/home">go to homerouter-link>
<router-link to="/news">go to newsrouter-link>
p>
<router-view>router-view>
div>
body>
- JS代码
<!-- 导入vue 与 router库 -->
<script src="js/vue.min.js"></script>
<script src="js/vue-router.min.js"></script>
<script>
// 1.定义路由所需的组件
const home = {template:"首页 花边新闻"};
const news = {template:"新闻 新闻联播"};
// 2.定义路由 每个路由有两部分 path(路径),component(组件)
const routes = [
{path:"/home",component:home},
{path:"/news",component:news}
];
// 3.创建路由管理器实例
const router = new VueRouter({
routes:routes
});
// 4.创建Vue实例,将router注入 vue实例中,让整个应用都拥有路由的功能
var VM = new Vue({
router
}).$mount("#app"); // 代替el挂载点
</script>
</html>
路由总结
- router是Vue中的路由管理器对象,用来管理路由
- route是路由对象,一个路由就对应一条访问路径,一组路由用routes表示
- 每个路由对象都有两部分 path(路径)和component (组件)
- router-link 是对a标签的封装,通过to属性指定连接
- router-view 路由访问到指定组件后,进行页面展示
Vue总结
Vue基础
vue简介:
1、前端JavaScript框架
2、特点:渐进式框架,实现即插即用
3、适合前后端分离,国人开发,中文文档
vue.js的使用:
1、引入vue:本地引入、远程引入
2、定义div,指定id
3、创建vue实例:{{}}插值表达式、el:挂载点、data:数据对象
4、渲染数据:vue中的声明式渲染,即我们声明数据,vue帮我们将数据渲染到html
vue指令:
1、v-text指令:获取data数据,设置标签内容
2、v-html指令:设置元素的innerHTML(可以向元素中写入新的标签)
3、v-on指令:Wie元素绑定事件
4、v-show指令:根据真假值,切换元素的显示状态
5、v-if指令:根据表达值的真假,切换元素的显示和隐藏(操纵DOM元素)
6、v-bind指令:设置元素的属性(比如:src,title,class)
7、v-for指令:根据数据生成列表结构
8、v-on补充指令:1)传递自定义参数:函数调用传参;2)事件修饰符:对事件触发的方式进行限制
MVVM模式:
1、model:负责存储数据
2、view:负责页面展示
3、view model:负责业务逻辑处理(比如ajax请求等),对数据进行加工后交给视图展示
v-model指令实现双向数据绑定:
1、单项绑定:把model绑定到view,当我们用JavaScript代码更新model时,view就会自动更新
2、双向绑定:用户更新了view,model的数据也自动被更新了,这种情况就是双向绑定
Vue进阶
axios:
1、作用:axios作用:在浏览器中可以帮助我们完成ajax异步请求的发送
2、先导入后使用
computed 计算属性:
1、作用:减少运算次数,缓存运算结果,应用于重复相同的计算
filter过滤器:
1、作用:过滤器是对即将显示的数据做进一步的筛选处理,然后进行显示
watch侦听器:
1、作用:当你想要监听某一个数据,然后执行一些操作时可以使用侦听器
component组件化开发:
1、组件(component)是自定义封装功能
2、在前端开发过程中,经常出现多个网页的功能是重复的,而且很多不同的页面之间,也存在同样的功能。我们将相同的功能进行抽取,封装为组件,这样,前端人员就可以在组件化开发时,只需要书写一次代码,随处引入即可使用。
vue生命周期:
1、每个Vue实例在被创建之前都要经过一系列的初始化过程,这个过程就是vue的生命周期
2、钩子函数
vue router路由:
1、在Web开发中,路由是指根据URL分配到对应的处理程序
2、单页应用:就是只有一张Web页面的应用,vue中使用路由完成单页面应用的开发
3、使用路由步骤:
- 定义路由所需的组件
- 定义路由每个路由都由两部分 path (路径) 和component (组件)
- 创建router路由器实例,由路由对象routes管理路由
- 创建Vue实例,注入路由对象,使用$mount() 指定挂载点
Vue-cli&ElementUI
Vue-cli
什么是Vue-cli
1、Vue cli是基于Vue的应用开发提供的一个标准的脚手架工具。为应用搭建基础的框架结构,提供插件、开发服务、Preset、构建打包功能
2、Vue cli 背后集成了现代化开发的诸多功能,通过简单的命令就可以完成 "零配置"的项目环境搭建
安装Vue-cli步骤
在安装vue-cli前,要确认自己的电脑是否安装了nodejs和npm。
安装Node.js
安装了node.js才能使用npm ,才能安装vue-cli
什么是node.js
1、node.js是一个基于Chrome V8引擎的JavaScript运行环境,使用了一个事件驱动、非阻塞式I/O模型。
2、JavaScript 运行在服务端的开发平台,它让JavaScript成为与PHP、Python、Perl、Ruby等服务端语言平起平坐的脚本语言。
安装node.js
- 下载对应你系统的Node.js版本:https://nodejs.org/en/download/
我们统一安装: node-v12.18.1-x64.msi
-
选安装目录进行安装
-
测试:在命令提示符下输入命令
node -v // 会显示当前node的版本
安装NPM
npm全称Node Package Manager,他是node包管理和分发的工具,使用NPM可以对应用的依赖进行管理,NPM 的功能和服务端项目构建工具maven的依赖管理功能差不多,我们通过npm 可以很方便地下载js库,打包js文件。
自动安装NPM
node.js已经集成了npm工具
在命令提示符输入 npm -v 可查看当前npm版本
npm -v
查看包管理路径
包路径就是npm从远程下载的js包所存放的路径。使用 npm config ls 查询NPM管理包路径(NPM下载的依赖包所存放的路径)。
npm config ls
我们发现NPM默认的管理包路径在:
C:\Users\Administrator\npm
设置包管理路径
依赖包放在C盘不太合适,为了方便对依赖包管理,我们将管理包的路径设置在单独的地方:
- 我们选择一个路径,专门存放这些依赖包。我选择创建一个目录:D:\MySoftware\nodejs_package
- 在D:\MySoftware\nodejs_package下再创建npm_modules文件夹和npm_cache文件夹:
npm config set prefix "D:\MySoftware\nodejs_package\npm_modules"
npm config set cache "D:\MySoftware\nodejs_package\npm_cache"
- 此时再使用npm config ls查询NPM管理包路径发现路径已更改
NPM环境变量配置
- 查看npm的全局路径是什么
npm config get prefix
- 配置PATH环境变量
添加新的系统变量: key=NODE_HOME , value= D:\MySoftware\nodejs_package
path中添加 %NODE_HOME%\npm_modules
安装cnpm
npm默认会去国外的镜像去下载js包,在开发中通常我们使用国内镜像,这里我们使用淘宝镜像
下边我们来安装cnpm:有时我们使用npm下载资源会很慢,所以我们可以安装一个cnmp(淘宝镜像)来加快下载速度。
- 联网情况下, 输入命令,进行全局安装淘宝镜像:
// 安装
npm install -g cnpm --registry=https://registry.npm.taobao.org
// 查看cnpm的版本
cnpm -v
安装vue-cli
目前主流版本是 2.x 和 3.x 版本,安装3.x 以上的版本是因为该版本既可以创建2.x项目与3.x 项目
注意:以管理员身份打开命令行
- 安装命令
npm install -g @vue/cli
- 输入 vue命令
vue
- 输入 vue -V 查看版本
vue -V
快速构建Vue项目
步骤说明
1、创建一个空的文件夹vuecli_work
2、以管理员身份运行cmd,进入到vuecli_work文件夹
3、执行下面的命令
1.基于交互式命令方式,创建项目
//文件名不支持驼峰(含大写字母)使用短横线方式
vue create my-project
4、选择自定义安装,点击回车
5、 在这列表中,选择我们要安装的组件,使用空格键选择,选好后回车
6、按回车之后,提示选择什么模式的路由,我们输入 n (表示选择hash模式)
7、选择项目配置文件单独存放
8、是否保存模板,选择n不创建
9、安装完成,提示输入执行下面这两个命令
10、首先进入项目目录:cd my-project
11、启动项目:npm run serve
12、访问项目: http://localhost:8080/
13、停止项目只要关闭命令行窗口就可以
导入Vue项目到VSCode
1、VSCode中右键选择打开文件夹
2、选择创建的项目
3、打开项目,可以看到如下项目结构
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LXb4rbaP-1627033941632)(E:\MarkDown\拉勾笔记\VueCLi项目目录结构)]
项目结构介绍
|---my-project 项目名称
|---node_modules 存放依赖包的目录
|---public 静态资源管理目录
|---src 组件源码目录(我们写的代码)
|---assets 存放静态图片资源(CSS也可以放在这里)
|---components 存放各种组件(一个页面可以看做一个组件),各个组件联系在一起组成一个完整的项目
|---router 存放了项目路由文件
|---views 放置的为公共组件(主要还是各个主要页面)
|---App.vue 可以当做是网站首页,是一个vue项目的主组件,项目页面入口文件
|---main.js 打包运行的入口文件,引入了vue模块和app.vue组件以及路由route
|---babel.config.jsbabel 配置文件,对源代码进行转码(把es6=>es5)
|---package.json 项目及工具的依赖配置文件
|---paxkage-lock.json 依赖配置文件
|---README.md 项目说明
Vue脚手架自定义配置
package.js 介绍
每个项目的根目录下面,一般都有一个package.json文件,定义了这个项目所需要的各种模块,以及项目的配置信息(比如名称、版本、许可证等元数据)。npm install命令根据这个配置文件,自动下载所需的模块,也就是配置项目所需的运行和开发环境。
{
// 1.项目基本信息
"name": "my-project",
"version": "0.1.0",
"private": true,
// 2.指定的运行脚本的命令
"scripts": {
"serve": "vue-cli-service serve",
"build": "vue-cli-service build"
},
// 3.生产环境所依赖的 模块版本
"dependencies": {
"core-js": "^3.6.5",
"vue": "^3.0.0",
"vue-router": "^4.0.0-0"
},
// 4.本地开发环境使用的依赖版本
"devDependencies": {
"@vue/cli-plugin-babel": "~4.5.0",
"@vue/cli-plugin-router": "~4.5.0",
"@vue/cli-service": "~4.5.0",
"@vue/compiler-sfc": "^3.0.0"
}
// 自定义配置
}
npm install
通过package.json 配置项目
配置内容采用JSON格式所有的内容都用双引号包裹
1、打开package.json,再最末端添加如下配置:
"vue":{
"devServer":{
"port":"8888",
"open":true
}
}
2、配置说明:该配置设置打包时服务器相关的信息
port : 访问端口
open true: 打包完成自动打开浏览器
3、启动项目
1)在VSCode中选择项目,右键在终端打开
2) 输入命令:npm run serve
3)运行后发现端口号改为 8888,并且在打包完成后自动打开浏览器
注意: 不推荐这种方式,因为package.json主要是用来管理包的配置信息。为了方便维护,我们将Vue脚手架相关的配置单独定义到vue.config.js配置文件中
单独的配置文件配置项目
1、在项目的根目录创建文件vue.config.js
2、删除掉package中新添加的配置项
3、在vue.config.js 文件中进行相关配置
module.exports = {
devServer:{
open:true,
port:8088
}
}
Vue 组件化开发
组件化开发
组件化是Vue的精髓,Vue项目就是由一个一个的组件构成的。我们主要的工作就是开发的组件
组件介绍
- 我们用 vue-cli 脚手架搭建的项目,里面有很多,如index.vue或者App.vue这一类的文件。
每一个***.vue 文件都是一个组件,是一个自定义的文件类型**,比如App.vue就是整个项目的根组件。
- 常见的组件:
页面级别的组件
页面级别的组件,通常是views目录下的.vue组件,是组成整个项目的各个主要页面
业务上可复用的基础组件
这一类组件通常是在业务中被各个页面复用的组件,这一类组件通常都写到components目录下,然后通过import在各个页面中使用
- 组件的组成部分
template: 组件的HTML部分
script: 组件的JS脚本 (使用ES6语法编写)
style: 组件的CSS样式
<template>
<div>
测试页面...
div>
template>
<script>
//可以导入其组件
// import Header from '../components/header.vue'
//默认写法, 输出该组件
export default {
name:"Home", // 组件名称,用于以后路由跳转
data() { // 当前组件中需要使用的数据
return {}
},
methods: {}
}
script>
<style scoped>
/* 页面样式 加上scoped 表示样式就只在当前组件有效*/
style>
项目运行流程
main.js
1、项目运行会加载入口文件main.js
// 在vue中使用 import 变量名 from 文件路径
import { createApp } from 'vue'
import App from './App.vue' // 主组件
import router from './router' // 路由
// 关闭启动提示
Vue.config.productionTip = false
// 创建Vue实例
new Vue({
router, // 为整个项目添加路由
render: h => h(App) // 这是一个函数ES6语法,作用是生成模板: App = App.vue
}).$mount('#app') // 挂载的是App.vue组件中的id为app的区域
App.vue
2、App.vue 是vue项目的主组件,是页面入口文件,所有页面都是在App.vue下进行切换的
App.vue 中的模板(HTML代码)
<template>
<div id="app"> 挂载的区域
<div id="nav">
// 是路由的导航链接
// 1.to="/" 是项目的根路径,是跳转的首页
<router-link to="/">Homerouter-link> |
// 2.to="/about" 单击跳转到 about组件
<router-link to="/about">Aboutrouter-link>
div>
<router-view/>
div>
template>
<style>style>
router 路由
3、找到路由文件,来看一下具体的路由配置
// 引入所需文件
import Vue from 'vue'
import VueRouter from 'vue-router'
// 引入了 Home.vue
import Home from '../views/Home.vue'
// 使用了路由功能
Vue.use(VueRouter)
// 创建路由集合,元素就是一个一个路由规则
const routes = [
{
path: '/', // 路径
name: 'Home', // 路由名称
component: Home // Home = Home.vue,表示路由导航到的组件
},
{
path: '/about', // 路径
name: 'About',
// route level code-splitting
// this generates a separate chunk (about.[hash].js) for this route
// which is lazy-loaded when the route is visited.
component: () => // 指向了 About.vue组件
import(/* webpackChunkName: "about" */ '../views/About.vue')
}
]
// 创建路由管理器对象
const router = new VueRouter({
routes
})
// export 用来表示导出模块
export default router
Home.vue组件
4、默认访问的是Home.vue首页
// 视图部分
<template>
<div class="home">
<img alt="Vue logo" src="../assets/logo.png">
<HelloWorld msg="Welcome to Your Vue.js App"/>
div>
template>
// JS部分
<script>
// @ is an alias to /src
// @符号表示 src这个目录
import HelloWorld from '@/components/HelloWorld.vue'
// 导出
export default {
name: 'Home',
components: {
HelloWorld
}
}
script>
组件的使用案例
创建Header.vue组件
1、在components目录下创建Header.vue
2、编写Header.vue
<template>
<div class="header">{{msg}}div>
template>
<script>
// JS部分
export default {
name:"Header", // 组件的名称
data() { // 这是data函数
return {
msg:"这是一个Header组件"
}
},
}
script>
// scoped 表示当前的样式,只作用于当前组件中的 template 视图
<style scoped>
.header{
height: 100px;
line-height: 100px;
background-color: #eee;
text-align: center;
color: blue;
}
style>
引入 Header组件
修改Home.vue
<template>
<div class="home">
<img alt="Vue logo" src="../assets/logo.png">
<Header/>
div>
template>
<script>
// @ is an alias to /src
import HelloWorld from '@/components/HelloWorld.vue'
import Header from '@/components/Header.vue';
export default {
name: 'Home',
components: {
// HelloWorld
Header
}
}
script>
组件的传参
props : 是组件中的属性,表示组件可以接受参数
<template>
<div class="header">{{msg}}div>
template>
<script>
// JS部分
export default {
name:"Header", // 组件的名称
// 参数传递
props:['msg']
}
script>
// scoped 表示当前的样式,只作用于当前组件中的 template 视图
<style scoped>
.header{
height: 100px;
line-height: 100px;
background-color: #eee;
text-align: center;
color: blue;
}
style>
Element-UI
Element-UI介绍
element-ui是饿了么前端出品的基于Vue.js的后台组件库,方便程序员进行页面快速布局和构建
Element-UI官方站点:https://element.eleme.cn/#/zh-CN
Element-UI使用
命令行方式安装
1、创建一个新的项目
2、当前项目下打开终端,安装依赖包,执行下面的命令
npm i element-ui -S
3、打开 main.js,导入Element-UI 相关资源
main.js是工程的入口文件,在此文件中加载了很多第三方组件,如:Element-UI、Base64、VueRouter等
// 导入elementUI组件库
import ElementUI from 'element-ui'
// 导入组件相关样式
import 'element-ui/lib/theme-chalk/index.css'
// 配置EL到vue上
Vue.use(ElementUI)
4、复制Element按钮样式到app.vue文件的template下
<template>
<div id="app">
<div id="nav">
<el-row>
<el-button disabled>默认按钮el-button>
<el-button type="primary" disabled>主要按钮el-button>
<el-button type="success" disabled>成功按钮el-button>
<el-button type="info" disabled>信息按钮el-button>
<el-button type="warning" disabled>警告按钮el-button>
<el-button type="danger" disabled>危险按钮el-button>
el-row>
<router-link to="/">Homerouter-link> |
<router-link to="/about">Aboutrouter-link>
div>
<router-view/>
div>
template>
5、启动项目 npm run serve,查看页面
Vue-CLI工程改造
1、删除components目录下的HelloWord.vue组件
2、删除App.vue中的部分内容,只保留如下部分
<template>
<div id="app">div>
template>
<style>
style>
3、删除router文件下的路由文件index.js部分内容,只保留如下部分
import Vue from 'vue'
import VueRouter from 'vue-router'
Vue.use(VueRouter)
const routes = []
const router = new VueRouter({
routes
})
export default router
4、删除views目录下的About.vue与Home.vue
安装axios
1、npm安装:使用npm下载axios包
npm i axios
2、在main.js文件中导入axios相关资源
//引入axios
import axios from 'axios'
//Vue对象使用axios
Vue.prototype.axios = axios;
用户登录界面制作
Dialog对话框组件
我们可以用Dialog制作一个登陆弹窗,选择自定义内容
<el-dialog title="收货地址" :visible.sync="dialogFormVisible">
<el-form :model="form">
<el-form-item label="活动名称" :label-width="formLabelWidth">
<el-input v-model="form.name" autocomplete="off">el-input>
el-form-item>
<el-form-item label="活动区域" :label-width="formLabelWidth">
<el-select v-model="form.region" placeholder="请选择活动区域">
<el-option label="区域一" value="shanghai">el-option>
<el-option label="区域二" value="beijing">el-option>
el-select>
el-form-item>
el-form>
<div slot="footer" class="dialog-footer">
<el-button @click="dialogFormVisible = false">取 消el-button>
<el-button type="primary" @click="dialogFormVisible = false">确 定el-button>
div>
el-dialog>
创建login.vue 组件
1、在components下创建Login.vue
2、将Diglog组件的内容,拷贝到Login.vue,进行修改:
<template>
<el-dialog title="用户登录" :visible.sync="dialogFormVisible">
<el-form>
<el-form-item label="用户名称" :label-width="formLabelWidth">
<el-input autocomplete="off">el-input>
el-form-item>
<el-form-item label="用户密码" :label-width="formLabelWidth">
<el-input autocomplete="off">el-input>
el-form-item>
el-form>
<div slot="footer" class="dialog-footer">
<el-button type="primary" @click="dialogFormVisible = false">登 录el-button>
div>
el-dialog>
template>
<script>
export default {
data() {
return {
dialogFormVisible: true,
formLabelWidth: '120px'
}
},
}
script>
<style scoped>
style>
配置路由
import Vue from 'vue'
import VueRouter from 'vue-router'
// 导入Login.vue组件
import Login from "@/components/Login"
Vue.use(VueRouter)
const routes = [
// 登录路由
{
path:"/login",
name:"login",
component:Login
}
];
const router = new VueRouter({
routes
})
export default router
修改App.vue
<template>
<div id="app">
<router-view>router-view>
div>
template>
<style>
style>
编写登录功能
1、去掉关闭按钮,添加一个属性:show-close="false"
2、修改登陆触发事件
登录el-button>
3、双向数据绑定
data中定义数据
data() {
return {
dialogFormVisible: true, // 宽度
formLabelWidth: '120px', // 是否关闭对话框
user:{username:"",password:""} // 登录数据
}
},
使用 v-model,将视图与模型进行绑定
<el-form>
<el-form-item label="用户名称" :label-width="formLabelWidth">
<el-input v-model="user.username" autocomplete="off">el-input>
el-form-item>
<el-form-item label="用户密码" :label-width="formLabelWidth">
<el-input v-model="user.password" autocomplete="off">el-input>
el-form-item>
el-form>
4、编写login方法
methods: {
// 登录的方法
login(){
// 定义常量保存url
const url = "";
// 发送请求
this.axios(url,{
// 携带的参数
param:{
username:this.user.username,
password:this.user.password
}
}).then(function(resp){
console.log(resp);
alert("登录成功");
}).catch(
// function (error) {}
error => {}
);
}
},
Postman搭建mock server
Mock server就是模拟一个服务器,我们使用Mock server可以模拟后台接口,对请求进行响应。
在前后端分离的开发中前端利用mockeserver模拟出对应接口,拿到返回数据来调试,无需等后端开发人员完成工作。
postman模拟出一个server 步骤:
1、使用postman模拟出一个server
2、打开如下窗体,创建一个伪服务
1)第一步
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FuxC9kQG-1627033941633)(E:\MarkDown\拉勾笔记\Postman搭建mock server01)]
2)第二步
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-V3pshQtZ-1627033941635)(E:\MarkDown\拉勾笔记\Postman搭建mock server02)]
3)第三步
4)第四步 修改请求的URL
const url = "复制上面的地址/login";
登录成功后跳转
在js中设置跳转,常用的一种方法是this.$router.push
methods: {
// 登录的方法
login(){
// 定义常量保存url
const url = "https://8fdd2435-45d6-4f80-9677-cdf1b03d5608.mock.pstmn.io/login";
// var that = this;
// 发送请求
this.axios(url,{
// 携带的参数
param:{
username:this.user.username,
password:this.user.password
}
}).then((resp) => {
console.log(resp);
alert("登录成功");
// 成功 关闭对话框
this.dialogFormVisible = false;
// 进行页面跳转,跳转到首页,在前端进行页面跳转 必须使用路由
this.$router.push('index');
}).catch(
// function (error) {}
error => {
// 登录失败 提供消息提示
this.$message.error('对不起!登录失败!');
}
);
}
},
首页布局页面制作
创建index.vue
<template>
<el-button type="danger">布局页面el-button>
template>
<script>
export default {}
script>
<style scoped>
style>
配置路由
router目录下的index.js路由文件
// 导入布局组件
import Index from "@/components/Index"
const routes = [
// 布局路由
{
path:"/index",
name:"index",
component:Index
}
];
布局容器
Container布局容器,是用于布局的容器组件,方便快速搭建页面的基本结构:
1、在官方文档中找到布局的容器代码,复制到Index.vue
<el-container>
<el-header>Headerel-header>
<el-container>
<el-aside width="200px">Asideel-aside>
<el-main>Mainel-main>
el-container>
el-container>
<style scoped>
.el-container{
height: 570px;
}
.el-header, .el-footer {
background-color: #B3C0D1;
color: #333;
text-align: center;
line-height: 60px;
}
.el-aside {
background-color: #D3DCE6;
color: #333;
text-align: center;
line-height: 200px;
}
.el-main {
background-color: #E9EEF3;
color: #333;
text-align: center;
line-height: 160px;
}
style>
2、拷贝布局容器中的导航菜单代码,进行修改,代码如下
<template>
<div>
<el-container>
<el-header>后台管理el-header>
<el-container>
<el-aside width="200px">
<el-menu
default-active="2"
class="el-menu-vertical-demo"
background-color="#D3DCE6"
>
<el-submenu index="1">
<template slot="title">
<i class="el-icon-location">i>
<span>导航菜单span>
template>
<el-menu-item-group>
<el-menu-item index="1-1"><i class="el-icon-menu">i>课程管理el-menu-item>
el-menu-item-group>
el-submenu>
el-menu>
el-aside>
<el-main>Mainel-main>
el-container>
el-container>
div>
template>
<script>
export default {}
script>
<style scoped>
.el-container{
height: 570px;
}
.el-header, .el-footer {
background-color: #B3C0D1;
color: #333;
text-align: center;
line-height: 60px;
}
.el-aside {
background-color: #D3DCE6;
color: #333;
text-align: center;
line-height: 200px;
}
.el-main {
background-color: #E9EEF3;
color: #333;
text-align: center;
line-height: 160px;
}
style>
课程列表组件制作
当我们点击导航菜单中的课程管理时,要显示课程信息
编写 Course.vue
<template>
<el-button type="danger">课程信息el-button>
template>
<script>
export default {}
script>
<style scoped>
style>
配置路由
1、在index.js路由文件中,为布局路由添加children属性表示子路由
// 导入课程组件
import Course from "@/components/Course";
// 布局路由
{
path:"/index",
name:"index",
component:Index,
// 添加子路由,使用children属性 来表示子路由
children:[
// 课程信息子路由
{
path:"/course",
name:"course",
component:Course
}
]
},
2、修改Index.vue组件中的导航菜单属性
router表示是否使用vue-router的模式,启用该模式会在激活导航时以index作为path进行路由跳转
el-menu中添加一个router属性
<el-menu
default-active="2"
class="el-menu-vertical-demo"
backgroundcolor="#D3DCE6"
router
>
3、为index属性指定路由
<el-menu-item-group>
<el-menu-item index="/course"><i class="el-icon-menu">i>课程管理el-menu-item>
el-menu-item-group>
4、设置路由的出口,将课程信息展示再main
<el-main>
<router-view>router-view>
el-main>
Table表格组件
我们通过table组件来实现一个课程页面展示的功能,通过查看Element-UI库,我们需要Table 表格.进入Element-UI官方,找到Table组件,拷贝源代码到vue页面中。
添加表格组件
复制表格组件相关的代码到Course.vue中
<template>
<el-table :data="tableData" stripe style="width: 100%">
<el-table-column prop="date" label="日期" width="180">el-table-column>
<el-table-column prop="name" label="姓名" width="180">el-table-column>
<el-table-column prop="address" label="地址">el-table-column>
el-table>
template>
<script>
export default {
data() {
return {
tableData: [
{
date: '2016-05-02',
name: '王小虎',
address: '上海市普陀区金沙江路 1518 弄'
}]
};
}
}
script>
表格组件说明
我们查看一下,ElementUI的表格的代码,分析一下表格数据是如何显示的
//视图部分 进行页面展示
<template>
//el-table组件 绑定了tableData数据
<el-table :data="tableData" style="width: 100%">
//el-table-column 表示表格的每列,prop属性与模型数据中的key对应 ,label 列名
<el-table-column prop="date" label="日期" width="180">el-table-column>
<el-table-column prop="name" label="姓名" width="180">el-table-column>
<el-table-column prop="address" label="地址">el-table-column>
el-table>
template>
<script>
//export default 相当于提供一个接口给外界,让其他文件通过 import 来引入使用。
export default {
//data() 函数
data() {
return {
//数据部分
tableData: [
{
date: "2016-05-02",
name: "王小虎",
address: "上海市普陀区金沙江路 1518 弄"
}
]
};
}
};
script>
课程内容展示
修改Course.vue
1、编写template,复制ElementUI的示例代码,进行改动
<template>
<el-table v-loading="loading" element-loading-text="拼命加载中" :data="courseList" stripe style="width: 100%">
<el-table-column prop="id" label="ID">el-table-column>
<el-table-column prop="course_name" label="课程名称">el-table-column>
<el-table-column prop="price" label="价格">el-table-column>
<el-table-column prop="sort_num" label="排序">el-table-column>
<el-table-column prop="status" label="状态">el-table-column>
el-table>
template>
2、编写VM部分代码
<script>
export default {
data() {
return {
loading:true,
courseList: []
};
},
// 钩子函数created,在DOM页面生成之前执行
created() {
// 在页面生成之前,调用 loadCourse()
this.loadCourse();
},
methods: {
// 方法1:获取课程信息
loadCourse(){
alert("loadCourse方法执行了");
// 发送请求获取课程数据
const url = "http://localhost:8080/lagou_edu_home/course";
return this.axios.get(url,{
params:{
methodName:"findCourseList"
}
}).then((res) => {
console.log(res.data);
// 将获取到的数据 赋值给
this.courseList = res.data;
// 取消加载动画
this.loading=false;
}).catch((error) => {
this.$message.error("获取数据失败!");
});
}
},
}
</script>
跨域问题解决
出现跨域问题
当我们在前端项目中,向后端发送请求的获取课程数据的时候,出现了跨域问题:
已被CORS策略阻止:请求的资源上没有’ Access-Control-Allow-Origin’标头(跨域请求失败)
Access to XMLHttpRequest at 'http://localhost:8080/lagou_edu_home/course?methodName=findCourseList' from origin 'http://localhost:8088' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
什么是跨域
跨域是指通过JS在不同的域之间进行数据传输或通信,比如用ajax向一个不同的域请求数据,只要协议、域名、端口有任何一个不同,都被当作是不同的域,浏览器就不允许跨域请求。
跨域的几种常见情况
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-arwPqKU8-1627033941636)(E:\MarkDown\拉勾笔记\跨域的几种情况)]
解决跨域问题
跨域的允许主要由服务器端控制。服务器端通过在响应的 header 中设置Access-Control-Allow-Origin及相关一系列参数,提供跨域访问的允许策略。
设置响应头中的参数来允许跨域域请求:
Access-Control-Allow-Credentials
Access-Control-Allow-Origin 标识允许跨域的请求有哪些
1、在POM文件中引入依赖
<dependency>
<groupId>com.thetransactioncompanygroupId>
<artifactId>cors-filterartifactId>
<version>2.5version>
dependency>
2、在web.xml中配置跨域filter
<filter>
<filter-name>corsFilterfilter-name>
<filter-class>com.thetransactioncompany.cors.CORSFilterfilter-class>
filter>
<filter-mapping>
<filter-name>corsFilterfilter-name>
<url-pattern>/*url-pattern>
filter-mapping>
再次查询
解决跨域问题之后,页面显示数据
条件查询
ElementUI输入框组件
Input 输入框通过鼠标或键盘输入字符
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-m67D0VG7-1627033941638)(E:\MarkDown\拉勾笔记\Input输入框)]
Course.vue添加输入框
<div>
<el-input placeholder="请输入课程名称"><i slot="prefix" class="el-input__icon el-icon-search">i>
el-input>
div>
Layout 布局
通过基础的 24 分栏,迅速简便地创建布局。
通过 row 和 col 组件,并通过 col 组件的span属性我们就可以自由地组合布局。
1、Row 组件提供gutter属性来指定每一栏之间的间隔,默认间隔为0。
<el-row :gutter="20">
<el-col :span="6"><div class="grid-content bg-purple">div>el-col>
el-row>
2、使用分隔,分隔查询条件
<el-row :gutter="20">
<el-col :span="6">
<el-input prefix-icon="el-icon-search" placeholder="课程名称" v-model="input" clearable>el-input>
el-col>
el-row>
3、添加一个按钮
<el-row :gutter="20">
<el-col :span="6">
<el-input prefix-icon="el-icon-search" placeholder="课程名称" v-model="input" clearable>el-input>
el-col>
<el-col span="1">
<el-button type="primary">点击查询el-button>
el-col>
el-row>
完成根据课程名查询
1、双向数据绑定
Model 模型
data() {
return {
loading:true,
courseList: [],
filter:{course_name:""}
};
},
View 视图
<el-input prefix-icon="el-icon-search" placeholder="课程名称" v-model="filter.course_name" clearable>el-input>
2、设置点击事件
<el-button type="primary" @click="search">点击查询el-button>
3、methods中添加方法
// 根据课程名查询
search(){
// 开启加载提示
this.loading=true;
// 发送请求
const url = "http://localhost:8080/lagou_edu_home/course";
return this.axios.get(url,{
// 携带参数
params:{
methodName:"findByCourseNameAndStatus",
course_name:this.filter.course_name
}
}).then((res) => {
console.log(res.data);
this.courseList = res.data;
// 关闭加载
this.loading=false;
}).catch((error) => {
this.$message.error("获取数据失败");
})
},
小结
VUE-CLI脚手架
什么是vue-cli
1、基于vue的应用开发提供的一个标准的脚手架工具
2、通过简单的命令就可以完成“零配置”的项目环境搭建
安装vue-cli
1、安装node.js:JavaScript运行环境
2、安npm:
1)包管理和分发的工具
2)设置包管理路径:放在c盘不太合适;创建目录,专门存放这些依赖包
3)配置path环境变量
4)安装cnpm
3、安装3.x版本的vue-cli:
npm install -g @vue/cli
cli构建项目
1、创建一个空文件夹
2、以管理员身份运行cmd,进入到文件夹
3、执行命令:
1)vue create my-project
2)文件名不支持驼峰命名(含大写字母)使用短横线方式
4、按步骤完成配置
5、将项目导入 VS Code
cli项目结构介绍
vue脚手架自定义配置
1、package.js:定义了这个项目所需要的各种模块,以及项目的配置信息等数据
2、vue.config.js:将vue脚手架相关的配置单独定义到vue.config.js配置文件中
vue组件化开发
1、介绍
组件化是vue的精髓,vue项目就是由一个一个的组件构成的,我们主要的工作就是开发组件
2、组件分类
1)页面级别的组件
2)业务上可复用的基础组件
3、组件的组成部分
1)template:组件的HTML部分
2)script:组件的js脚本(使用es6语法编写)
3)style:组件的css样式
项目运行流程
1、main.js:项目运行会加载入口文件 main.js
2、app.vue:vue项目的主组件,是页面的入口,所有页面都是在app.vue下进行切换的
3、router路由:进行页面的跳转
4、home.vue组件:
1)首页
2)内引入了helloworld.vue组件
ELEMENT-UI
element-ui介绍
1、element-ui是饿了么前端出品的基于vue.js的后台组件库
element-ui安装
1、创建项目,在终端打开
2、执行命令:npm i element-ui -S
3、main.js中引入:
1)导入组件库:import elementui from ‘element-ui’
2)导入组件相关样式:import ‘element-ui/lib/theme-chalk/index.css’
3)配置vue插件,将el安装到vue上:vue.use(elementui);
vue-cli工程改造
1、删除项目构建时生成的一些页面
安装axios
1、执行命令:npm i axios
2、main.js引入
element-ui案例
1、用户登录页面制作:
1)dialog对话框组件
2)创建login.vue组件
3)配置路由
4)完成登录功能
5)postman搭建mock server
6)登录跳转
2、首页布局页面制作
1)创建index.vue
2)配置路由
3)布局容器container
3、导航菜单的路由设置
1)编写course.vue
2)配置路由
4、table表格组件
1)通过table组件来实现一个课程页面展示的功能,通过查看element-ui库,我们需要table表格
5、课程内容展示
1)请求后台,获取课程数据
2)跨域问题:指通过js在不同的域之间进行数据传输或通信,比如用ajax向一个不同的域请求数据,只要协议、域名、端口有任何一个不同,都被当做是不同的域,浏览器就不允许跨域请求
3)解决跨域问题:后台解决,设置response响应头数据即可;引入了解决跨域的依赖
6、条件查询
1)elementui输入框组件
2)layout布局
3)完成根据课程名查询
前后端项目接口联调
联调准备
运行后台项目
1、clean清空项目的编译文件
2、compile重新编译项目
3、将项目部署到 tomcat
项目名为: lagou_edu_home
端口号: 8080
4、部署图片上传路径为 webapps目录下的 upload目录
运行前端项目
1、首先导入前端项目到 VSCode
2、运行项目
课程管理首页
获取课程列表
JS部分
<script>
//引入axios
import { axios } from "../utils";
export default {
name: "Courses",
title: "课程管理",
//定义数据部分
data() {
return {
filter: { course_name: "", status: "" }, //查询对象
courses: [], //课程信息集合
loading: false //是否弹出加载
};
},
//钩子函数
created() {
this.loadCourses();
},
methods: {
//方法1: 获取课程列表
loadCourses() {
this.loading=true;
// 请求后台查询课程列表接口
return axios.get("/course",{
params:{
methodName: "findCourseList"
}
}).then(resp => {
console.log(resp);
this.courses = resp.data;
this.loading=false;
}).catch((error) => {
this.$message.error("数据获取失败!!!");
})
},
}
};
</script>
条件查询课程信息
JS部分
//方法2: 条件查询课程信息
filterQuery() {
this.loading = true;
// 请求后台条件查询接口
return axios.get("/course",{
// 准备参数
params:{
methodName:"findByCourseNameAndStatus",
course_name:this.filter.course_name,
status:this.filter.status
}
}).then(resp => {
this.loading = false;
this.courses = resp.data;
}).catch((error) => {
this.$message.error("数据获取失败!!!");
})
},
跳转到添加课程
JS部分
//方法3: 添加课程跳转方法
addCourse() {
// 路由跳转到CourseItem.vue
this.$router.push({
name:"CourseItem",params:{courseID:"new"}
});
},
修改课程状态
JS部分
//方法4: 修改课程状态
updateStatus(item) {
// item表示选中的数据 = Course对象
axios.get("/course",{
params:{
methodName:"updateCourseStatus",
id:item.id
}
}).then(resp => {
// 将返回的状态字段数据,封装到item对象中
Object.assign(item,resp.data);
// 重新加载页面
window.location.reload;
}).catch(error => {
this.$message.error("修改课程状态失败!!!");
})
},
跳转课程营销或内容管理
JS部分
//方法5: 根据路由名称, 导航到对应组件
handleNavigate(name, id) {
// 根据参数 使用对应的路由 导航到指定的组件
this.$router.push({name,params:{courseId:id}});
},
新建&修改课程
Course组件中的跳转方法
<el-button size="mini" @click="handleNavigate('CourseItem', scope.row.id)">营销信息el-button>
//方法3: 添加课程跳转方法
addCourse() {
// 路由跳转到CourseItem.vue
this.$router.push({
name:"CourseItem",params:{courseId:"new"}
});
},
router.js 路由
找到name为: CourseItem的路由
//添加课程的路由
{
path: "/courses/:courseId", //路径,携带参数: 课程ID
name: "CourseItem",
component: () =>
//路由导航到的组件
import(/* webpackChunkName: 'courses' */ "../views/CourseItem.vue")
},
CourseItem组件
JS部分
//数据部分
return {
rules, //规则
course: {}, //课程
loading: false,
params: {}
};
},
//钩子函数
created() {
//1.显示当前页面在网站中的位置
this.$breadcrumbs = [
{ name: "Courses", text: "课程管理" },
{ text: "营销信息" }
];
// 1.获取路由传递的参数
const id = this.$route.params.courseId;
// 2.判断id是否有值,没有值就跳转到 错误页面
if(!id) return this.redirectToError();
// 3.有id中值,判断是new,还是具体的课程id
if(id === "new"){
// new 代表是新增操作
this.course.title = "新增课程";
}else{
// 否则就是修改操作
// alert("修改操作ID = "+id);
// 根据id查询课程信息,进行回显
this.loadCourse(id);
}
},
图片上传分析
页面部分
<el-form-item label="分享小图" prop="share_image_title">
<el-input v-model="course.share_image_title" type="text">
<el-upload
slot="prepend"
:auto-upload="false"
:on-change="onchange"
action
:limit="1">
<el-button size="small" type="primary">点击上传el-button>
el-upload>
el-input>
el-form-item>
JS部分
FormData的主要用途有两个
1、将form表单元素的name与value进行组合,实现表单数据的序列化,从而减少表单元素的拼接,提高工作效率。
2、异步上传文件
3、创建FormData对象
data中创建FormData
// 4.在钩子函数中创建FormDate对象,将图片与表单其他内容 一通上传
this.params = new FormData();
methods添加方法
//文件上传
onchange(file) {
if(file != null){
// 将文件信息,保存到 FormDate对象中
// 参数1:表示文件上传项 参数2:文件上传的二进制数据 参数3:文件名
this.params.append("file",file.raw,file.name);
}
},
新建课程信息
JS 部分
//方法1: 保存和修改课程信息
handleSave() {
// 1.校验表单是否正确
this.$refs.form.validate(valid => {
// 判断校验是否通过
if(!valid) return false;
// 1.设置Content-Type类型为:多部件上传
let config = {
headers:{
"Content-type":"multipart/form-data"
}
}
// 2.获取到表单数据,保存到params中(params就是FormDate对象)
for(let key in this.course){
// debugger
console.log(key + " = " + this.course[key]);
this.params.append(key,this.course[key]);
}
// 3.请求后台接口 保存课程信息
axios.post("/courseSalesInfo",this.params,config).then(resp => {
if(resp.data.status == 0){
// 保存成功,跳转回首页
this.$router.back();
}else if(resp.data.status == 1){
// 保存失败
this.$message.error(resp.data.msg);
}
}).catch(error => {
this.$message.error("保存课程信息失败!!!");
});
})
},
修改课程信息
//方法2: 根据ID 回显课程信
loadCourse(id) {
this.loading = true;
axios.get("/course",{
params:{
methodName:"findCourseById",
id:id
}
}).then(resp => {
this.loading = false;
this.course = resp.data;
}).catch(error => {
this.$message.error("回显数据失败!!");
});
},
内容管理
Course组件中的跳转方法
<el-button size="mini" @click="handleNavigate('CourseTasks', scope.row.id)">内容管理el-button>
//方法5: 根据路由名称, 导航到对应组件
handleNavigate(name, id) {
// 根据参数 使用对应的路由 导航到指定的组件
this.$router.push({name,params:{courseId:id}});
},
router.js 路由
//内容管理的路由
{
path: "/courses/:courseId/tasks",
name: "CourseTasks",
meta: { requireAuth: true },
component: () =>
import(/* webpackChunkName: 'courses' */ "../views/CourseTasks.vue")
}
CourseTasks组件
树形控件测试
1、 打开我们之前编写的VueCLI项目
2、在component目录下,添加一个组件,TestTree.vue
<template>
template>
<script>
export default {
}
script>
<style scoped>
style>
3、在Index.vue组件中的导航菜单位置添加一个 树形控件导航
注意:要设置index的路径为 /tree
<el-submenu index="1">
<template slot="title">
<i class="el-icon-location">i>
<span>导航菜单span>
template>
<el-menu-item-group>
<el-menu-item index="/course"><i class="el-icon-menu">i>课程管理el-menu-item>
<el-menu-item index="/tree"><i class="el-icon-menu">i>树形控件el-menu-item>
el-menu-item-group>
el-submenu>
4、 在index.js 路由文件中进行配置,在布局路由中再添加一个子路由
import Tree from "@/components/TestTree"
// 布局路由
{
path:"/index",
name:"index",
component:Index,
// 添加子路由,使用children属性 来表示子路由
children:[
// 课程信息子路由
{
path:"/course",
name:"course",
component:Course
},
{
path:"/tree",
name:"tree",
component:Tree
}
]
},
5、在ElementUI官网中查找树形控件
6、先来查看基础用法,复制代码到 TestTree.vue
<template>
<el-tree :data="data" :props="defaultProps">el-tree>
template>
<script>
export default {
data() {
return {
data: [{
label: '一级 1',
children: [{
label: '二级 1-1',
children: [{
label: '三级 1-1-1'
}]
}]
}, {
label: '一级 2',
children: [{
label: '二级 2-1',
children: [{
label: '三级 2-1-1'
}]
}, {
label: '二级 2-2',
children: [{
label: '三级 2-2-1'
}]
}]
}, {
label: '一级 3',
children: [{
label: '二级 3-1',
children: [{
label: '三级 3-1-1'
}]
}, {
label: '二级 3-2',
children: [{
label: '三级 3-2-1'
}]
}]
}],
defaultProps: {
children: 'children',
label: 'label'
}
};
},
methods: {
handleNodeClick(data) {
console.log(data);
}
}
}
script>
<style scoped>
style>
7、 Tree组件属性分析
**data:**展示数据
**props:**配置树形结构
label : 设置节点名称
children: 指定生成子树的属性名称
8、自定义树节点内容:
data:数据对象
node:节点对象
<el-tree :data="data" :props="defaultProps">
<span class="custom-tree-node" slot-scope="{ node, data }">
<span>{{data.label}}span>
<span>级别:{{node.level}}span>
span>
el-tree>
9、 展示树形结构章节与课时
<template>
<el-tree :data="data" :props="defaultProps">
<span class="custom-tree-node" slot-scope="{ node, data }">
<span>{{data.section_name || data.theme}}span>
span>
el-tree>
template>
<script>
export default {
data() {
return {
data: [
{
id: 5,
course_id: 10,
section_name: "麻式太极",
description: "麻式太极拳,你动我试试",
orderNum: 0,
status: 2,
create_time: "2019-07-11 10:55:10.0",
update_time: "2019-10-09 12:43:01.0",
isDel: 0,
lessonList: [
{
id: 32,
course_id: 10,
section_id: 5,
theme: "第一讲:如何给自己洗脑",
duration: 10,
is_free: 1,
order_num: 1,
status: 2,
create_time: "2019-01-23 20:37:02.0",
update_time: "2020-02-24 18:37:34.0",
isDel: 0
},
{
id: 33,
course_id: 10,
section_id: 5,
theme: "第二讲:如何给别人洗脑",
duration: 10,
is_free: 1,
order_num: 1,
status: 2,
create_time: "2019-01-23 20:37:02.0",
update_time: "2020-02-24 18:37:34.0",
isDel: 0
}],
}],
// 树形结构的展示
defaultProps: {
children: 'lessonList',
label: item => {
return item.section_name || item.theme
}
}
};
},
methods: {
handleNodeClick(data) {
console.log(data);
}
}
}
script>
<style scoped>
style>
显示当前课程的名称
1、显示当前课程名称
<el-page-header @back="() => this.$router.back()" :content="addSectionForm.course_name" />
2、data数据
data() {
//定义章节信息
const addSectionForm = {
course_id: undefined,
course_name: "",
section_name: "",
description: "",
order_num: 0
};
//章节与课时信息,树形结构
const treeProps = {
label: item => {
return item.section_name || item.theme;
},
children: "lessonList"
};
//定义章节状态信息
const statusMapping = {
0: "已隐藏",
1: "待更新",
2: "已更新"
};
const statusForm = {
status: 0
};
return {
addSectionForm,
treeProps,
sections: [],
statusForm, //状态表单
statusMapping,
loading: false, //树形控件
showAddSection: false, //添加或修改章节
showStatusForm: false //状态修改
};
},
3、 加载课程信息
created() {
//1.显示当前页面在网站中的位置
this.$breadcrumbs = [
{ name: "Courses", text: "课程管理" },
{ text: "课程结构" }
];
//2. 从路由中获取传递的参数, 课程id
const id = this.$route.params.courseId;
if (!id) return this.redirectToError();
//3.加载课程信息
this.loadCourse(id);
//4.加载课程对应的章节与课时
this.loadChildren(id);
},
methods: {
//方法1: 加载课程信息
loadCourse(id) {
axios.get("/courseContent",{
params:{
methodName:"findCourseById",
course_id:id
}
}).then(resp => {
// 将数据保存到 表单对象中
this.addSectionForm.course_id = resp.data.id,
this.addSectionForm.course_name = resp.data.course_name;
}).catch(error => {
this.$message.error("数据获取失败!!!");
})
},
},
加载章节与课时信息
JS部分
//方法2: 加载树(章节与课程)
loadChildren(id) {
this.loading = true;
axios.get("/courseContent",{
params:{
methodName:"findSectionAndLessonByCourseId",
course_id:id
}
}).then(resp => {
// 获取数据 保存到 sections
this.sections = resp.data;
this.loading = false;
}).catch(error => {
this.loading = false;
this.$message.error("数据获取失败!!!");
})
},
HTML
el-tree ElementUI树形控件
:data 列表数据
:props 配置选项
<el-tree
:data="sections"
:props="treeProps"
v-loading="loading"
element-loading-text="数据加载中..."
>
<div class="inner" slot-scope="{ data, node }">
<span>{{ data.section_name || data.theme }}span>
:props 配置选项
**label:**指定节点标签为节点对象的某个属性值
**children:**指定子树为节点对象的某个属性值
//章节与课时信息,树形结构
const treeProps = {
label: item => {
return item.section_name || item.theme;
},
children: "lessonList" // 返回的JSON数据中的lessonList集合
};
操作按钮显示
node.level 获取当前节点的级别
@click.stop 事件冒泡,点击哪个元素,就执行哪个元素绑定的事件
<span class="actions">
<el-button v-if="node.level == 1" size="small" @click.stop="handleEditSection(data)">编辑el-button>
<el-button v-if="node.level == 1" size="small" @click.stop="showStatus(data)"
>{{ statusMapping[data.status] }}el-button>
span>
回显信息
HTML
<el-button type="primary" icon="el-icon-plus" @click="handleShowAddSection">添加章节el-button>
JS部分
//方法3: 显示添加章节表单,回显课程信息
handleShowAddSection() {
this.showAddSection = true;
},
添加章节
HTML
<el-button type="primary" @click="handleAddSection">确 定el-button>
JS
//方法4: 添加&修改章节操作
handleAddSection() {
axios.post("/courseContent",{
methodName:"saveOrUpdateSection",
section:this.addSectionForm
}).then(resp => {
debugger;
this.showAddSection = false;
// 重新加载页面
return this.loadChildren(this.addSectionForm.course_id);
}).then(() =>{
// reset 重置表单
this.addSectionForm.section_name = '';
this.addSectionForm.description = '';
this.addSectionForm.order_num = 0;
}).catch(error => {
this.$message.error("操作执行失败!!!");
})
},
后台接口问题解决
BaseServlet中代码修改
if("application/json;charset=utf-8".equals(contentType))
修改为:
if("application/json;charset=utf-8".equalsIgnoreCase(contentType))
CourseContentServlet中的saveOrUpdateSection方法修改
//3.使用BeanUtils的 copyProperties方法,将map中的数据封装到section对象里
//BeanUtils.populate(section,map);
BeanUtils.copyProperties(section,map.get("section"));
修改章节
HTML
<el-button v-if="node.level == 1" size="small" @click.stop="handleEditSection(data)">编辑el-button>
JS回显示方法
//方法5: 修改章节回显方法
handleEditSection(section) {
// 对象拷贝
Object.assign(this.addSectionForm,section);
this.showAddSection = true;
},
事件冒泡:当点击子元素的事件。如果父元素也有同样的事件的话。他就会一并的触发。
解决冒泡事件的方法: @click.stop
<body>
<div id="app" @click="log('div点击事件!!')">
<button @click.stop="log('button的点击事件!!!')">按钮button>
div>
body>
<script src="js/vue.min.js">script>
<script>
var VM = new Vue({
el:"#app",
methods:{
log(t){
alert(t);
}
}
})
script>
章节状态回显
HTML
<el-button v-if="node.level == 1" size="small" @click.stop="showStatus(data)">{{ statusMapping[data.status] }}el-button>
JS
//定义章节状态信息
const statusMapping = {
0: "已隐藏",
1: "待更新",
2: "已更新"
};
//方法6: 显示章节状态
showStatus(data) {
console.log(data);
// 保存状态表单数据
this.statusForm.id = data.id;
this.statusForm.status = data.status.toString();
this.statusForm.data = data;
// 显示表单对话框
this.showStatusForm = true;
},
Select选择器
1、打开我们之前编写的VueCLI项目
2、在component目录下,添加一个组件,TestSelect.vue
<template>
template>
<script>
export default {}
script>
<style scoped>
style>
3、 在Index.vue组件中的导航菜单位置添加一个 Select选择器 导航
注意:要设置index的路径为 /select
<el-menu-item index="/select"><i class="el-icon-menu">i>select选择器el-menu-item>
4、在index.js 路由文件中进行配置,在布局路由中再添加一个子路由
import Select from "@/components/TestSelect"
{
path:"/select",
name:"select",
component:Select
},
5、在ElementUI官网中查找Select选择器
6、查看基础用法,将代码复制到 TestSelect.vue中
<template>
<el-select v-model="value" placeholder="请选择">
<el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value">el-option>
el-select>
template>
<script>
export default {
data() {
return {
options: [{
value: '选项1',
label: '黄金糕'
}, {
value: '选项2',
label: '双皮奶'
}, {
value: '选项3',
label: '蚵仔煎'
}, {
value: '选项4',
label: '龙须面'
}, {
value: '选项5',
label: '北京烤鸭'
}],
value: ''
}
}
}
script>
<style scoped>
style>
7、select 选择器属性分析
**v-model:**的值为当前被选中的el-option的 value 属性值
**el-option:**选项
label 选项的标签名
value 选择的值
8、使用Select选择器展示状态信息
<template>
<el-select v-model="status" placeholder="请选择">
<el-option v-for="item in Object.keys(statusMapping)" :key="item" :label="statusMapping[item]" :value="item">el-option>
el-select>
template>
<script>
export default {
data() {
return {
statusMapping:{
0: "已隐藏",
1: "待更新",
2: "已更新"
},
status:"",
};
}
};
script>
Object.keys()
var obj = { 0: 'a', 1: 'b', 2: 'c' };
console.log(Object.keys(obj)); // console: ['0', '1', '2']
章节状态修改
HTML
<el-button type="primary" @click="handleAddSection">确 定el-button>
JS部分
//方法7: 修改章节状态
updateStatus(statusForm) {
axios.get("/courseContent",{
params:{
methodName:"updateSectionStatus",
id:this.statusForm.id,
status:this.statusForm.status
}
}).then(resp => {
this.statusForm.data.status = this.statusForm.status;
this.statusForm = {};
this.showStatusForm = false;
}).catch(error => {
this.showStatusForm = false;
this.$message.error("修改状态失败!!!");
});
},
v-for里面数据层次太多, 修改过数据变了,页面没有重新渲染,需手动强制刷新。
@change="$forceUpdate()" 强制刷新
项目上线部署发布
前言
服务器与操作系统
1、服务器是计算机的一种,它比普通计算机运行更快、负载更高、价格更贵。
2、服务器从硬件上等同于电脑PC。而服务器跟PC都是由CPU、内存、主板、硬盘、电源等组成;但服务器的性能要远远超过PC,因为它要保证全年无休。
3、操作系统:操作系统是作为应用程序与计算机硬件之间的一个接口
1)没有安装操作系统的计算机,被称为裸机, 如果想在裸机上运行自己的程序,就需要使用机器语言
2)安装操作系统之后,就可以配置一些高级语言的环境,进行高级语言的开发
4、Linux操作系统
1)Linux系统是最具稳定性的系统
2)Linux是天生就比Windows更具安全性
3)免费,Linux服务器在应用开发上更能节约成本
项目的发布部署
项目的开发流程大致要经过一下几个步骤:
1、项目立项
2、需求分析阶段
3、原型图设计阶段
4、开发阶段
5、测试阶段
6、系统上线
后台项目部署
安装虚拟机
在Linux阶段我们已经安装过了虚拟机,使用的是 Linux操作系统 CentOS 7 版本
安装软件环境
以下软件,在Linux阶段都已安装完成。具体操作详见该阶段安装文档。
软件
版本
JDK
11
Tomcat
8.5
MySQL
5.7
1、查看Java版本
java -version
2、查看tomcat是否能够正常启动
# 进入到tomcat目录
cd /usr/tomcat/
# 启动tomcat
./bin/startup.sh
# 关闭tomcat
./bin/shutdown.sh
3、关闭防火墙
#查看已经开放的端口:
firewall-cmd --list-ports
#开启端口
firewall-cmd --zone=public --add-port=8080/tcp --permanent
#命令含义:
–zone #作用域
–add-port=8080/tcp #添加端口,格式为:端口/通讯协议
–permanent #永久生效,没有此参数重启后失效
#重启防火墙
firewall-cmd --reload #重启firewall
#关闭防火墙
systemctl stop firewalld.service #停止firewall
systemctl disable firewalld.service #禁止firewall开机启动
firewall-cmd --state #查看默认防火墙状态(关闭后显示notrunning,开启后显示running)
4、登录MySQL,检查数库连接是否正常
-- 创建用户
CREATE USER 'Weiwei'@'%' IDENTIFIED BY 'Weiwei@666';
-- 授予所有权限
GRANT ALL PRIVILEGES ON *.* TO 'Weiwei'@'%' IDENTIFIED BY 'Weiwei@666';
-- 刷新
FLUSH PRIVILEGES;
5、使用SQLYog连接Linux上的MySQL,导入SQL脚本 创建项目所需的数据库
项目打包 发布
1、修改项目的数据库配置文件,数据库的IP,用户名 密码都要修改。
2、修改 Constants常量类中的项目URL
//生产环境地址
public static final String LOCAL_URL = "http://192.168.44.128:8080";
3、修改后启动项目,测试一下 保证数据库连接没有问题
4、检查POM文件,打包方式必须是war,编译版本为JDK11
<packaging>warpackaging>
<properties>
<project.build.sourceEncoding>UTF-8project.build.sourceEncoding>
<maven.compiler.source>11maven.compiler.source>
<maven.compiler.target>11maven.compiler.target>
properties>
5、执行打包命令
//清除target文件夹
clean
//打包 ,跳过测试
package
6、复制出target目录下的 war包
7、修改一下项目名称
8、上传到tomcat中,启动测试
//访问接口
http://192.168.44.128:8080/lagou_edu_home/course?methodName=findCourseList
前端项目部署
修改配置文件
1、前端项目的配置文件有两个,一个是开发环境的配置文件,一个是生产环境的配置文件。
.env.development // 开发环境
.env.production // 生产环境
2、我们先修改一下开发环境文件的 后端服务器访问地址,然后进行一下测试
.env.development 文件
VUE_APP_API_BASE = http://192.168.44.128:8080/lagou_edu_home
3、修改生产环境的配置文件
//.env.production
VUE_APP_API_BASE = http://192.168.44.128:8080/lagou_edu_home
前端项目打包
1、修改 vue.config.js 配置文件
复制下面内容即可
module.exports = {
// relative path for dev
publicPath: process.env.NODE_ENV === "production" ? "/edu-boss/" : "./",
// for gh-pages
indexPath: "index.html",
assetsDir: "static",
lintOnSave: process.env.NODE_ENV !== "production",
productionSourceMap: false,
css: {
// sourceMap: process.env.NODE_ENV !== 'production'
},
devServer: {
open: true,
port: 8081
}
};
2、执行下面的打包命令
npm run build
3、 在项目下会生成一个 dist 目录
4、在本地tomcat的webapps目录下,创建一个edu-boss文件夹,将dist目录中的文件拷贝到里面
5、启动本地tomcat,访问前端项目 路径为:
http://localhost:8081/edu-boss/
前端项目发布
1、验证没有问题后,将edu-boos项目压缩,上传到tomcat服务器
//复制一份tomcat
cp -r /usr/tomcat/ /usr/tomcat2
//上传 edu-boss.zip ,并解压
unzip edu-boss.zip
//删除edu-boss.zip
rm -rf edu-boss.zip
2、修改tomcat2的server.xml 配置文件,修改3个端口,避免与tomcat1冲突
3、在部署后端项目的tomcat1的 webapps目录下创建一个 upload文件夹,保存图片
4、运行前端项目
//进入tomcat2,启动项目
./bin/startup.sh
//动态查看日志
tail -f logs/catalina.out
5、运行后端项目
//进入tomcat1,启动项目
./bin/startup.sh
//动态查看日志
tail -f logs/catalina.out
6、 前后端都启动后,进行测试