一、Web前端开发概述
1、什么是 Vue
官方给出的概念:Vue (读音/vjuː/,类似于 view) 是一套用户构建用户界面的前端框架
2、MVVM模式(Model-View-ViewModel)
可以把所有的图形化应用程序粗略地分为两部分:用户界面部分和内部逻辑部分。
MVVM 是 vue 实现数据驱动视图和双向数据绑定的核心原理。
MVVM模式包括3个核心部分:
Model(模型):由核心的业务逻辑产生的数据对象,例如从数据库取出并做特定处理后得到的数据。
View(模型):即用户界面。
ViewModel(视图模型):用于链接匹配模型和视图的专用模型。
二、Vue.js开发基础
1、Vue根实例
1、文本插值
<!DOCTYPE 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>Document</title>
</head>
<body>
<!-- 插值语法/胡子语法
({{}}) -->
<div id="newStudent">
<p>学妹好!</p>
<ul>
<li>姓名: {{ name }}</li>
<li>城市: 甲地</li>
</ul>
</div>
<!-- 引入vue文件 -->
<script src="https://cdn.jsdelivr.net/npm/vue@2.7.10/dist/vue.js"></script>
<script>
var vm = new Vue({
//定义挂载元素
el:'#newStudent',
//定义数据
data:{
name:'三号',
city:'广东'
}
})
</script>
</body>
</html>
2、方法属性
<!DOCTYPE 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>Document</title>
</head>
<body>
<div id="bcc">
<button @click="showInfo">请点击</button>
<p>{{ msg }}</p>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.7.10/dist/vue.js"></script>
<script>
var vm = new Vue({
//定义挂载元素
el:'#bcc',
//定义数据
data:{
msg:''
},
methods:{
showInfo(){
this.msg = '触发点击事件'
}
}
})
</script>
</body>
</html>
3、属性绑定
<!DOCTYPE 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>Document</title>
<style>
.famale{
color: pink;
}
</style>
</head>
<body>
<div id="app">
<!-- -->
<ul v-bind:class="sex">
<li>姓名:李</li>
<li>城市:昌</li>
</ul>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.7.10/dist/vue.js"></script>
<script>
let vm =new Vue({
el:'#app',
data:{
name:'lucy',
city:'nanchange',
sex:'famale'
}
})
</script>
</body>
</html>
4.计时器案例
<!DOCTYPE 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>Document</title>
</head>
<body>
<script src="C:\Users\tt\Desktop\vue\vue .js"></script>
<div id="app">
<input type="button" value="开始计时" @click="timer">
<br>
{{ num }}
<br>
<input type="button" value="暂停计时" @click="stop">
</div>
<script>
var vm = new Vue({
el: "#app",
data: {
num: 0,
},
methods:{
timer(){
//时间函数
time = setInterval(function () {
vm.num++
}, 500)
},
stop() {
//↓清除定时器
clearInterval(time)
}
}
})
</script>
</body>
</html>
2、生命周期
释意: vue从创建到销毁的整个过程就称为vue的生命周期
(1) vue的生命周期钩子是回调函数,
当创建组件实例的过程中会调用相应的钩子方法, 内部会对钩子进行处理, 将钩子函数维护成数组的形式
(2) 每个阶段都有两个生命周期的钩子函数
创建阶段—beforeCreate, created
挂载阶段—beforeMount, mounted
运行阶段—beforeUpdate, updated
销毁阶段—beforeDestroy, destroyed
beforeCreate():这是我们遇到的第一个生命周期函数,表示实例完全被创建出来之前,会执行它…
created(): 在实例创建之后调用,此时尚未开始DOM编译。
beforeMount():这是遇到的第3个生命周期函数,表示 模板已经在内存中编辑完成,但是尚未把模板渲染(挂载)到页面中。在 beforeMount 执行的时候,页面中的元素,还没有被真正替换过来,只是之前写的一些模板字符串。就像{{text}}这样
mounted():这是遇到的第四个生命周期函数,表示内存中的模板,已经真实的挂载到了页面中,用户已经可以看到渲染好的页面了。只要执行完这个生命周期,就表示整个vue实例已经初始化完毕了,此时,组件已经脱离了创建阶段,进入到了运行阶段。
beforeUpdate():这时候表示,我们的界面还没有被更新[但数据已经被更新了页面中显示的数据,还是旧的,此时data数据是最新的。页面尚未和最新的数据保持同步
update() : 这一步执行的是 先根据data中最新的数据,在内存中重新渲染出一份最新的内存dom树,当最新的内存dom树被更新后,会把最新的内存DOM树重新渲染到真实的页面中去,这时候,就完成了数据data(model层)->view(视图层)的更新,页面和data数据已经保持同步了,都是最新的。
beforeDestory :当执行 beforeDestory 钩子函数的时候,Vue实例就已经从运行阶段,进入到销毁阶段, 当执行beforeDestroy的时候,实例身上所有的data和所有的methods以及过滤器、指令...都处于可用状态,此时,还没有真正执行销毁的过程。
destroyed :当执行这个函数的时候,组件已经被完全销毁了,此时,组件中所有的数据,方法,指令,过滤器...都已经不可用了
三、计算属性与侦听器
1、计算属性
(1)、定义计算属性:
<!DOCTYPE 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>Document</title>
</head>
<div id="demo">
原数据 {{ arrange }} <br>
<!-- 通过split方法分割后的数据 {{ reverseMessage}} -->
通过结合方法颠倒的数据{{ reverseMessage }}
</div>
<body>
<!-- 引入vue脚本 -->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
var app = new Vue({
el: '#demo',
data() {
return {
arrange: 'hello'
}
},
//计算属性
computed: {
//定义计算方法
//颠倒-reverse
//分割-splist
reverseMessage() {
return this.arrange.split('').reverse().join(' ')
}
}
})
</script>
</body>
</html>
(2)、计算属性的缓存特性
<!DOCTYPE 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>Document</title>
</head>
<body>
<script> // [计算属性]
// 可以在里面写一些计算逻辑的属性。
// 他不像普通函数那样直接返回结果,而是经过一系列计算之后再返回结果。
// 同时只要在它当中应用了data中的某个属性,当这个属性发生变化时,计算属性可以嗅探到这种变化,并自动执行,
// 定义:要用的属性不存在,通过已有属性计算得来。
// 使用: 在computed对象中定义计算属性,在页面中使用{(方法名}}来显示计算的结果
// [基本结构]
new Vue({
el: '',
// 数据
data: {},
// 方法属性
// 事件绑定,不用return,没有级存
methods: {},
// 侦听器(重视过程)
// 监听一个值的改变,不用返回值。
watch: {
要侦听的数据() {
}
},
// 计算属性(重视结果)
// 必须有return,只求结果,有缓存
computed: {
计算属性名() {
// 经过一系列计算
return 处理操作后结果
}
}
// 计算属性的缓存特性
// 第一次调用计算属性时,会产生一个结果,这个结果会被缓存起来,后面每次用这个属性都是从缓存里取。
// 当它的恢赖项发生改变,会重新计算得到一个结果,再缓存起来。
})
</script>
</html>
2、侦听器
1、侦听器的基本结构
<!DOCTYPE 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>Document</title>
</head>
<body>
<p id="app">
{{ makaba}}
</p>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
new Vue({
el:'#app',
data:{},
methods:{
},
//侦听器
watch:{
//参一:改变后的值
//参二改变前的值
要侦听的数据(newValue,olValue){
}
}
})
</script>
</body>
</html>
2、侦听器的基本使用
<!DOCTYPE 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>Document</title>
</head>
<body>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<div id="add">
{{ makabaka }}
<button @click="changeName">变帅</button>
</div>
<script>
var vm =new Vue({
el:'#add',
data:{
makabaka:'韦小宝'
},
methods:{
changeName() {
this.makabaka='宋'
}
},
watch:{
makabaka:function(newValue,oldValue){
//侦听后弹窗通知
alert('韦成宋')
}
}
})
</script>
</body>
</html>
3、对数组进行侦听
<!DOCTYPE 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>Document</title>
</head>
<body>
<!-- 数组是复杂数据类型,拥有复杂的侦听规则
理论上修改一个数组的内容,如修改元素的值,或者添加新元素,均不会修改数组本身的地址值.
Vus.js对数组进行特殊处理,标准数组操作方法对数组所作修改均可被侦听
1.Vue不能检测以下数组的变动:
a.当你利用索引值直接设置一个数组时,例如: vm.items[index0fItem] = newValue
b.当你修改数组的长度时,例如: vm.items.length = newLength
2.使用标准方法修改数组可以被侦听到
push() 尾部添加
pop() 尾部删除
unshift()头部添加
shift() 头部删除
splice() 删除、添加、替换
sort() 排序
reverse() 逆序
(Vue将被侦听的数组的变更方法进行了包裹,所以它们也将会触发视图更新,以上就是被包裹的方法。)
-->
<div id="app">
<button @click="list.push('蜡笔小旧')">添加一个项</button>
<button @click="list.pop()">删除一个项</button>
<button @click="list.splice(2,0,'天气之子')">第二项添加</button>
<button @click="list.reverse">排序</button>
<ul>
<li v-for="item in list">
{{ item }}
</li>
</ul>
</div>
<script src='https://cdn.jsdelivr.net/npm/vue/dist/vue.js'></script>
<script>
var vm = new Vue({
el: '#app',
data: {
list: ["makabak", 'wuxidixi', '叮叮车']
},
watch: {
list() {
console.log("数组改变了");
alert('数组已改变')
}
}
})
</script>
</body>
</html>
4、深度侦听
//此写法侦听不到对象内部属性变化,
//只能真听到obj对象指针的变化
// Obj:function(newValue,oldValue){
// //侦听后弹窗通知
// alert('修改成功')
// },
// //解决方案:
// //'对象.属性'
// 'Obj.age'(){
// alert('年龄修改')
// },
<!DOCTYPE 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>Document</title>
</head>
<body>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<div id="app">
<p> {{ Obj.name }}--{{Obj.age}}--{{Obj.height}}</p>
<button @click="changeObj">依托答辩</button>
<button @click="changeAge">成长</button>
</div>
<script>
var vm = new Vue({
el:'#app',
data:{
Obj:{
name:'semall',
age:11,
height:115,
}
},
methods:{
changeObj(){
this.Obj={name:'变', age:'变',height:'变'}
},
changeAge(){
this.Obj.age=17;
}
},
watch:{
//深侦,启动 ! ! !
Obj:{
//当对象出现变化时,将会调用此方法
handler(){
alert('Obj里的属性改变了')
},
//开关深侦听
deep:true
}
}
})
</script>
</body>
</html>
四、样式绑定
1、对象内联绑定
<!DOCTYPE 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>Document</title>
<style>
.size{
font-size: 46px;
}
.color{
color:darkcyan;
}
.active{
font-style: italic;
}
</style>
<script src="C:\Users\tt\Desktop\vue\vue.js"></script>
</head>
<body>
<div id="app">
<button @click="qh">切换</button>
<div class="demo" v-bind:class="{size:isSize,color:isColor,active:isActive}">
vue.js样式绑定
</div>
</div>
<script>
const name = new Vue({
el:'#app',
data:{
isSize:true,
isColor:true,
isActive:true
},
methods:{
qh:function(){
this.isActive =! this.isActive;
}
}
})
</script>
</body>
</html>
2、对象非内联绑定
<!DOCTYPE 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>Document</title>
<style>
.size{
font-size: 46px;
}
.color{
color:darkcyan;
}
.active{
font-style: italic;
}
</style>
</head>
<body>
<script src="C:\Users\tt\Desktop\vue\vue.js"></script>
<div id="app">
<button @click="classobject.size=false">切换</button>
<div v-bind:class="classobject">vue.js样式绑定 </div>
</div>
<script>
const name = new Vue({
el:'#app',
data:{
classobject:{
size:true,
color:true,
active:true
}
},
})
</script>
</body>
</html>
五、事件处理
1、事件与事件流
<!DOCTYPE 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>Document</title>
<style>
.outer {
width: 200px;
height: 200px;
background-color: blue;
}
.inner {
width: 100px;
height: 100px;
background-color: red;
}
</style>
</head>
<body>
<script src="../vue.js"></script>
<div id="app">
<div class="outer" @click.capture="outer">
外层盒子
<div class="inner" @click="inner">
内层盒子
</div>
</div>
</div>
<script>
new Vue ({
el: '#app',
methods: {
outer() {
console.log("父节点");
},
inner() {
console.log("子节点");
}
}
})
</script>
</body>
</html>
2、事件修饰符
1、stop修饰符
<!DOCTYPE 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>Document</title>
<style>
.outer {
width: 200px;
height: 200px;
background-color: blue;
}
.inner {
width: 100px;
height: 100px;
background-color: red;
}
</style>
</head>
<body>
<script src="../vue.js"></script>
<div id="app">
<!-- caputer更改事件传送的顺序 -->
<div class="outer" @click.capture="outer">
外层盒子
<!-- stop 阻止子时间默认的冒泡行为 -->
<div class="inner" @click.stop="inner">
内层盒子
</div>
</div>
</div>
<script>
new Vue ({
el: '#app',
methods: {
outer() {
console.log("父节点");
},
inner() {
console.log("子节点");
}
}
})
</script>
</body>
</html>
2、 self修饰符
<!DOCTYPE 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>Document</title>
<style>
.one{
width: 300px;
height: 300px;
background-color: red;
}
.two{
width: 300px;
height: 300px;
background-color: darkblue;
}
.three{
width: 300px;
height: 300px;
background-color: aliceblue;
}
</style>
</head>
<body>
<div id="app">
<a href="https://www.4399.com/">4399</a>
<div class="one"@click="one">
1
<!-- 目标事件为当前元素时触发 -->
<div class="two"@click.self="two">
2
</div>
<div class="three"@click="three">
3
</div>
</div>
</div>
</body>
</html>
keydown:按下键时触发。
keypress:按下有值的键时触发,而当按下Ctrl、Alt、Shift、Meta这样无值的键时,keypress事件不会触发。对于有值的键,按下时先触发keydown事件,再触发keypress事件。
keyup:松开键时触发。
六、表单绑定
实例:
<!DOCTYPE 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>Document</title>
</head>
<body>
<div id="app">
<!-- placeholder 占位符-->
输入账号<input type="text" placeholder="请输入账号"><br>
输入密码<input type="password" placeholder="请输入密码" v-model="abc">
选择文件<input type="file" v-model="file">
提交图片:<input type="image" v-model="image" src=""><br>
选择周:<input type="week" v-model="week"><br>
选择月:<input type="month" v-model="month"><br>
<!-- 多行文本框 -->
<textareacols="30”rows="10”v-model="textarea” placeholder="请输入文本"></textareacols>
<!-- .trim 屏蔽空格-->
<input type="text" V-model.trim="text">
<span>一共{{text.length}}个字符</span>
<script src="../vue(1).js"></script>
</div>
<script src="/vue.js"></script>
<script>
new Vum({
el: '#app',
data: {
abc: '',
text:'',
}
})
</script>
</body>
</html>
七、结构渲染
1、条件渲染指令v-if和条件渲染指令v-show
<!DOCTYPE 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>Document</title>
</head>
<body>
<!--
v-if
-->
<script src="C:\Users\tt\Desktop\vue\vue .js"></script>
<div id="app">
<!--
多分支使用
少切
-->
{{ money }}
<p>根据存款,决定晚上吃什么</p>
<div v-if="money > 10000">请火锅</div>
<div v-else-if="money >5000"> 入麦门</div>
<div v-else-if="money >1000"> 恰拌面</div>
<div v-else-if="money >500"> 甜蜜蜜</div>
<div v-else> 班长已噶,黄天当立</div>
<!--
双分支使用
多切(频繁使用用show)
-->
<div v-show="age>=18">成年了,去网吧偷耳机</div>
<div v-show="age<18">未成年,捡垃圾</div>
<button @click="add">预支生活费</button>
</div>
<script>
const vm = new Vue({
el:'#app',
data:{
money:72,
age:17,
},
methods: {
add(){
vm.money = vm.money+3000
}
}
});
</script>
</body>
</html>
2、列表渲染指令v-for
<!DOCTYPE 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>Document</title>
</head>
<bo>
<script src="C:\Users\tt\Desktop\vue\vue .js"></script>
<div id="app">
<ul>
<li v-for="(item,index) in list">{{ interm }}---{{ index }}</li>
<button @click=""></button>
</ul>
</div>
<script>
new Vue({
el: '#app',
data: {
list: [3, 4, 5, 6, 7]
}
})
</script>