Vue 学习笔记
本笔记是跟着尚硅谷的课程来的,有些地方可能写的很模糊,router 那部分懒得写了,有问题看官网
注意:本次笔记均为案例笔记且知识点、注意点均用注释写出在附近
Vue 基础
webpack
webpack是一个前端具体化的解决方案
功能:它提供了友好的前端模块化开发得支持,以及代码压缩混淆,处理浏览器JavaScript兼容性,性能优化等强大功能。
好处:让程序员把工作得重心放到具体功能得实现上,提高了前端开发效率和项目得可维护性
注意:目前vue,React等前端项目,基本都是基于webPack进行工程化开发的
vue的初体验
<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>第一天</title>
<!-- 引入Vue.js -->
<script src="../js/vue.js"></script>
</head>
<body>
<div id="root">
<!-- 使用插值语法对内容进行展示 -->
<h1>{{str}}</h1>
</div>
<script>
Vue.config.productionTip = false; //关闭vue的安全提示
new Vue({
el: "#root",
data: {
//data 中用于存储数据,数据提供给el所指定的容器使用
str:"hello,world"
}
})
//一个容器只能对应一个Vue实例
//配置对象
</script>
</body>
</html>
el与data的两种写法
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
<title>el与data的两种写法</title>
<script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
<div id="root">
<h1>你好,{{name}}</h1>
</div>
</body>
<script type="text/javascript">
Vue.config.productionTip = false
//el的两种写法
/*const vm = new Vue({
// el:'#root', //绑定容器的第一种写法
data:{
name:'湖南大学'
}
})
vm.$mount('#root') //绑定容器的第二种写法*/
//data的两种写法
new Vue({
el:'#root',
//data的第一种写法:对象式
/*data:{
name:'湖南大学'
}*/
//data的第二种写法:函数式
//函数式不可写成箭头函数且必须有返回值
//函数式不可写成箭头函数且必须有返回值
//函数式不可写成箭头函数且必须有返回值
data(){
return{
name:'湖南大学'
}
}
})
</script>
</html>
数据绑定
<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>第一天</title>
<script src="../js/vue.js"></script>
</head>
<body>
<div id="root">
<h1>{{name}},{{age}}</h1>
<a v-bind:href="href">aaa</a>
<!-- v-bind:xxx 单向绑定 -->
<input type="text" v-bind:value="name">
<!-- 当修改name的值时 data中name的数据并不改变 -->
<!-- v-model:xxx 双向绑定 -->
<input type="text" v-model:value="name">
<!-- 当修改name的值时 data中name的数据并会跟随着改变 -->
<!-- v-model 需要注意 只能在表单类元素上使用 -->
</div>
<script>
Vue.config.productionTip = false; //关闭vue的安全提示
//创建 vue 实例
new Vue({
el: "#root", //选取元素 通常为css选择字符串
//el:document.getElementById("root")
data: {
//data 中用于存储数据,数据提供给el所指定的容器使用
name: '张三',
age: 18,
href:"https://www.baidu.com",
}
})
//配置对象
</script>
</body>
</html>
数据代理
<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>第一天</title>
<script src="../js/vue.js"></script>
</head>
<body>
<div id="root">
<h1>{{name}},{{age}}</h1>
</div>
<script>
Vue.config.productionTip = false; //关闭vue的安全提示
//创建 vue 实例
const vm = new Vue({
el: "#root", //选取元素 通常为css选择字符串
//el:document.getElementById("root")
data: {
//data 中用于存储数据,数据提供给el所指定的容器使用
name: '张三',
age: 18
}
})
//配置对象
console.log(vm.$data.name)
// 即拿到vm后(vue实例)我们可以利用vue实例拿取数据
</script>
</body>
</html>
<!--
1.Vue中的数据代理:
通过vm对象来代理data对象中属性的操作(读/写)
2.Vue中数据代理的好处:
更加方便的操作data中的数据
3.基本原理:
通过Object.defineProperty()把data对象中所有属性添加到vm上。为每一个添加到vm上的属性,都指定一个getter/setter。在getter/setter内部去操作(读/写)data中对应的属性。
-->
事件处理
点击事件
案例一:
<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>第一天</title>
<script src="../js/vue.js"></script>
</head>
<body>
<div id="root">
<h1>{{name}},{{age}}</h1>
<hr>
<button v-on:click="getYourName">
获取我的名字
</button>
</div>
<script>
Vue.config.productionTip = false; //关闭vue的安全提示
//创建 vue 实例
new Vue({
el: "#root", //选取元素 通常为css选择字符串
//el:document.getElementById("root")
data: {
//data 中用于存储数据,数据提供给el所指定的容器使用
name: '张三',
age: 18
},
methods:{
getYourName(){
console.log("王五")
this.$data.name = "王五"
}
}
})
//配置对象
</script>
</body>
</html>
案例二:
<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>第一天</title>
<script src="../js/vue.js"></script>
</head>
<body>
<div id="root">
<h1>{{name}},{{age}}</h1>
<hr>
<button v-on:click="getYourName">
获取我的名字
</button>
<!-- 当需要给事件处理函数传递参数时 -->
<button v-on:click="getYourAge($event,66)">
获取我的年龄
</button>
</div>
<script>
Vue.config.productionTip = false; //关闭vue的安全提示
//创建 vue 实例
new Vue({
el: "#root", //选取元素 通常为css选择字符串
//el:document.getElementById("root")
data: {
//data 中用于存储数据,数据提供给el所指定的容器使用
name: '张三',
age: 18
},
methods:{
getYourName(){
console.log("王五")
this.$data.name = "王五"
},
getYourAge(event,number){
console.log(event)
console.log(number)
}
}
})
//配置对象
</script>
</body>
</html>
点击事件的事件修饰符
<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>第一天</title>
<script src="../js/vue.js"></script>
<style>
.list{
width:200px;
height: 200px;
background-color: orange;
overflow: auto;
}
li{
height: 100px;
}
</style>
</head>
<body>
<div id="root">
<h1>{{name}},{{age}}</h1>
<hr>
<a href="https://www.baidu.com" v-on:click.prevent="getYourName">去往百度</a>
<div v-on:click.stop="showInfo"><button>你好</button></div>
<button v-on:click.once="showInfo">点我提示信息</button>
<!-- 事件简写 @xxx 即可 -->
<div class="box1" @click.capture="showMsg(1)">
div1
<div class="box2" @click="showMsg(2)">
div2
</div>
</div>
<div class="demo1" style="background:blue; height:50px;" @click.self="showInfo">
<button @click="showInfo">点我提示信息</button>
</div>
<ul class="list" @wheel.passive="demo">
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
</ul>
<!--
事件修饰符
1、阻止默认事件(常用):prevent
2、阻止事件冒泡(常用):stop
3、事件只触发一次(常用):once
4、使用事件的捕获模式:capture
5、只有event.target是当前操作的元素时才触发事件:self
6、事件的默认行为是立即执行,无需等待事件回调执行完毕:passive
-->
<a href="https://www.baidu.com" v-on:click.prevent.once="getYourName">去往百度</a>
<!--
事件修饰符可连续
-->
</div>
<script>
Vue.config.productionTip = false; //关闭vue的安全提示
//创建 vue 实例
new Vue({
el: "#root", //选取元素 通常为css选择字符串
//el:document.getElementById("root")
data: {
//data 中用于存储数据,数据提供给el所指定的容器使用
name: '张三',
age: 18
},
methods:{
getYourName(){
console.log("王五")
this.$data.name = "王五"
},
showInfo(){
alert("你好")
},
showMsg(num){
alert(num)
},
demo(){
for(let i=0;i<100000;i++){
console.log("#")
}
console.log("累坏了")
}
}
})
//配置对象
</script>
</body>
</html>
键盘事件及事件修饰符
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>键盘事件</title>
<!-- 引入Vue -->
<script type="text/javascript" src="../js/vue.js"></script>
<style>
</style>
</head>
<body>
<div id="root">
<h2>欢迎来到{{name}}学习</h2>
<input type="text" placeholder="按下回车提示输入" @keyup.enter="showInfo"><br/>
<input type="text" placeholder="按下CapsLock提示输入" @keyup.caps-lock="showInfo"><br/>
<input type="text" placeholder="按下tab提示输入" @keydown.tab="showInfo"><br/>
<input type="text" placeholder="按下ctrl+任意键,抬起任意键提示输入" @keyup.ctrl="showInfo"><br/>
<input type="text" placeholder="按下ctrl提示输入" @keydown.ctrl="showInfo"><br/>
<input type="text" placeholder="通过键码绑定事件" @keydown.13="showInfo">
<input type="text" placeholder="vue自定义按键别名" @keydown.huiche="showInfo">
<br/>
<br/>
<input type="text" placeholder="按下ctrl+y键触发" @keydown.ctrl.y="showInfo">
</div>
<!--
Vue中常用的按键别名:
回车:enter
删除:delete (捕获“删除”和“退格”键)
退出:esc
空格:space
换行:tap (特殊,必须配合keydown去使用)
上:up
下:down
左:left
右:right
Vue中未提供的别名按键,可以使用按键原始的key值去绑定,但注意要转为kebab-case(短横线命名)。
系统修饰符(用法特殊):ctrl, alt,shift, meta(徽标键)
配合keyup使用:按下修饰符的同时,再按下其他键,随后释放其他键,时间才被触发。
配合keydown使用,正常触发事件。
也可以使用keyCode键码去指定具体的按键(不推荐,因为该特性已从web中移除了,未来可能不再支持)。
Vue.config.keyCode.自定义键名=键码。可以去定制按键别名。(不太推荐,一般默认的也就够用了)
-->
<!--阻止vue在启动时生成生产提示 -->
<script type="text/javascript">
Vue.config.productionTip=false
// vue自定义按键别名
Vue.config.keyCodes.huiche=13
const vm = new Vue({
el: "#root",
data:{
name:"Gitlink",
},
methods:{
showInfo(event){
// 输出按键编码
// console.log(event.keyCode)
// 输出输入框中输入的值
// console.log(event.target.value)
// js写法
// if(event.keyCode !== 13) return
console.log(event.target.value)
// 输出按键的名称以及编码
console.log(event.key)
}
}
})
</script>
</body>
</html>
计算属性
姓名案例一
<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>第一天</title>
<script src="../js/vue.js"></script>
</head>
<body>
<div id="root">
姓:<input type="text" v-model="fristName">
名:<input type="text" v-model="lastName">
姓名:<span>{{fristName}}-{{lastName}}</span>
</div>
<script>
Vue.config.productionTip = false; //关闭vue的安全提示
//创建 vue 实例
new Vue({
el: "#root", //选取元素 通常为css选择字符串
//el:document.getElementById("root")
data: {
//data 中用于存储数据,数据提供给el所指定的容器使用
fristName:"张",
lastName:"山"
}
})
//配置对象
</script>
</body>
</html>
姓名案例二
<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>第一天</title>
<script src="../js/vue.js"></script>
</head>
<body>
<div id="root">
姓:<input type="text" v-model="fristName">
名:<input type="text" v-model="lastName">
姓名:<span>{{fullName}}</span>
<!--
计算属性:
-->
</div>
<script>
Vue.config.productionTip = false; //关闭vue的安全提示
//创建 vue 实例
new Vue({
el: "#root", //选取元素 通常为css选择字符串
//el:document.getElementById("root")
data: {
//data 中用于存储数据,数据提供给el所指定的容器使用
fristName:"张",
lastName:"山"
},
computed:{
fullName(){ //简写
return this.fristName+'-'+this.lastName
}
//完整写法
// fullName:function (val1,val2){
// return this.fristName+'-'+this.lastName
// }
}
})
//配置对象
</script>
</body>
</html>
天气案例
<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>第一天</title>
<script src="../js/vue.js"></script>
</head>
<body>
<div id="root">
<h1>今天天气很{{tq}}</h1>
<button @click="changeHot">
切换天气
</button>
</div>
<script>
Vue.config.productionTip = false; //关闭vue的安全提示
//创建 vue 实例
new Vue({
el: "#root", //选取元素 通常为css选择字符串
//el:document.getElementById("root")
data: {
//data 中用于存储数据,数据提供给el所指定的容器使用
isHot:true
},
methods:{
changeHot(){
this.isHot = !this.isHot
}
},
computed:{
tq(){
return this.isHot ?"炎热":"凉爽"
}
}
})
//配置对象
</script>
</body>
</html>
监视属性
利用监视属性改进天气案例(普通监视)
<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>第一天</title>
<script src="../js/vue.js"></script>
</head>
<body>
<div id="root">
<h1>今天天气很{{info}}</h1>
<button @click="changeHot">
切换天气
</button>
</div>
<script>
Vue.config.productionTip = false; //关闭vue的安全提示
//创建 vue 实例
new Vue({
el: "#root", //选取元素 通常为css选择字符串
//el:document.getElementById("root")
data: {
//data 中用于存储数据,数据提供给el所指定的容器使用
isHot:true
},
computed:{
info:function (){
return this.isHot ? "炎热" : "凉爽"
}
},
methods:{
changeHot:function (){
this.isHot = !this.isHot
}
},
//watch 配置项 配置监视属性
watch:{
// 需要监视的数据
isHot: {
immediate:true, //初始化时调用handler
handler(newValue, oldValue) { //handler 在数据被修改时调用
console.log(newValue, oldValue)
// return newValue ? "炎热":"凉爽"
}
}
}
})
//配置对象
</script>
</body>
</html>
深度监视
<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>第一天</title>
<script src="../js/vue.js"></script>
</head>
<body>
<div id="root">
<h1>今天天气很{{info}}</h1>
<button @click="changeHot">
切换天气
</button>
<hr>
<p>a等于:{{numbers.a}}</p>
<button @click="numbers.a++">a+1</button>
<p>b等于:{{numbers.a}}</p>
<button @click="numbers.b++">b+1</button>
</div>
<script>
Vue.config.productionTip = false; //关闭vue的安全提示
//创建 vue 实例
new Vue({
el: "#root", //选取元素 通常为css选择字符串
//el:document.getElementById("root")
data: {
//data 中用于存储数据,数据提供给el所指定的容器使用
isHot:true,
numbers:{
a:1,
b:1
}
},
computed:{
info:function (){
return this.isHot ? "炎热" : "凉爽"
}
},
methods:{
changeHot:function (){
this.isHot = !this.isHot
}
},
watch:{
isHot: {
immediate:true, //初始化时调用handler
handler(newValue, oldValue) { //handler 在数据被修改时调用
console.log(newValue, oldValue)
// return newValue ? "炎热":"凉爽"
}
},
//独立监视
// 'numbers.a':{
// handler(newValue, oldValue) {
// console.log("a的值已经改变了")
// }
// }
// 深度监视
numbers: {
deep:true,
handler(newValue, oldValue) {
console.log("numbers 发生了改变")
}
}
//需要注意一点 vue自身可以监视到配置对象中数据的改变
//但是watch默认不监视配置对象中的数据变化
//需要手动开启 利用deep 开启深度监视
}
// 计算属性与监视属性的区别
/*
*
监听属性和计算属性的区别主要有下面几点:
1.计算属性性能更优。一个监听属性只能监听一个属性的变化,如果要同时监听多个,就要写多个监听属性,而计算属性可以同时监听多个数据的变化。
2.监听属性可以获取改变之前的属性值。
3.计算属性能做的,watch都能做,反之则不行。
4.能用计算属性尽量用计算属性。
作者:草莓千层蛋糕
链接:https://juejin.cn/post/6888511471404187661
来源:稀土掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
*
*
* */
})
//配置对象
</script>
</body>
</html>
样式绑定
内联样式
<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>第一天</title>
<script src="../js/vue.js"></script>
<style>
*{
margin: 0 0;
padding: 0 0;
}
.box{
height: 100px;
width: 100px;
}
.border{
border: crimson 1px solid;
}
.div1{
background-color: rebeccapurple;
}
.div2{
background-color: royalblue;
}
.div3{
background-color: burlywood;
}
.styleObj{
font-size:15px;
background-color:blue;
font-family:"宋体";
color:red;
}
</style>
</head>
<body>
<div id="root">
<div class="box" :class="classes">123456</div>
<button @click="changeClass">切换颜色</button>
<br>
<!-- 直接引用 -->
<div class="box" :class="arr">123456</div>
<!-- 对象写法 -->
<div class="box" :class="classObj">123456</div>
<br>
<!-- 行内样式 -->
<div :style="{fontSize:15+'px'}">Test</div>
<!-- 对象写法 -->
<div :style="styleObj">Test</div>
<!-- 多样式对象使用 -->
<div :style="[styleObj,styleObj1]">Test</div>
</div>
<script>
Vue.config.productionTip = false; //关闭vue的安全提示
//创建 vue 实例
new Vue({
el: "#root",
data:{
classes:'div1',
arr:['div1','border'],
classObj:{
// fontSize:15,
// backgroundColor:"blue",
// fontFamily:"宋体",
// color:"red"
styleObj:true
},
styleObj:{
backgroundColor:"red",
fontSize:2+'em',
},
styleObj1:{
color:"#ffffff"
}
},
methods:{
changeClass(){
const arr = ['div1','div2','div3']
let index = Math.floor(Math.random()*3);
console.log(index)
this.classes = arr[index]
}
}
})
//配置对象
</script>
</body>
</html>
通过class绑定样式
<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>第一天</title>
<script src="../js/vue.js"></script>
<style>
*{
margin: 0 0;
padding: 0 0;
}
.box{
height: 100px;
width: 100px;
}
.border{
border: crimson 1px solid;
}
.div1{
background-color: rebeccapurple;
}
.div2{
background-color: royalblue;
}
.div3{
background-color: burlywood;
}
.styleObj{
font-size:15px;
background-color:blue;
font-family:"宋体";
color:red;
}
</style>
</head>
<body>
<div id="root">
<div class="box" :class="classes">123456</div>
<button @click="changeClass">切换颜色</button>
<br>
<!-- 直接引用 -->
<div class="box" :class="arr">123456</div>
<!-- 对象写法 -->
<div class="box" :class="classObj">123456</div>
</div>
<script>
Vue.config.productionTip = false; //关闭vue的安全提示
//创建 vue 实例
new Vue({
el: "#root",
data:{
classes:'div1',
arr:['div1','border'],
classObj:{
// fontSize:15,
// backgroundColor:"blue",
// fontFamily:"宋体",
// color:"red"
styleObj:true
}
},
methods:{
changeClass(){
const arr = ['div1','div2','div3']
let index = Math.floor(Math.random()*3);
console.log(index)
this.classes = arr[index]
}
}
})
//配置对象
</script>
</body>
</html>
条件渲染
v-show
<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>第一天</title>
<script src="../js/vue.js"></script>
</head>
<body>
<div id="root">
<h1 v-show="age === 18">{{name}},{{age}}</h1>
<h1 v-show="true">{{name}},{{age}}</h1>
<h1 v-show="false">{{name}},{{age}}</h1>
<!--
v-show 的底层实现是利用display hidden 实现因此被v-show 标记的dom元素在dom树在可见
-->
</div>
<script>
Vue.config.productionTip = false; //关闭vue的安全提示
//创建 vue 实例
new Vue({
el: "#root", //选取元素 通常为css选择字符串
//el:document.getElementById("root")
data: {
//data 中用于存储数据,数据提供给el所指定的容器使用
name: '张三',
age: 18
}
})
//配置对象
</script>
</body>
</html>
v-if
<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>第一天</title>
<script src="../js/vue.js"></script>
</head>
<body>
<div id="root">
<div v-if="state">
<h1>你好</h1>
</div>
<button @click="changeHidden">{{text}}</button>
<!--
v-if 在渲染时
如果表达式为true 就正常渲染
如果表达式为false 则不进行渲染
另外v-if 不渲染时在dom树中此dom元素不可见
-->
<hr>
<div>
<div v-if="state">你好</div>
<div v-else-if="!state">不好</div>
<div v-else-if="state">hello</div>
<div v-else>ohhhhhh</div>
<!--
v-if与JavaScript 中多分支语句一样当条件为真时就运行
-->
</div>
</div>
<script>
Vue.config.productionTip = false; //关闭vue的安全提示
//创建 vue 实例
new Vue({
el: "#root", //选取元素 通常为css选择字符串
//el:document.getElementById("root")
data: {
state:false,
text:"显示"
},
methods:{
changeHidden(){
this.state = !this.state
if(this.state){
this.text = "不显示"
}else {
this.text = "显示"
}
}
}
})
//配置对象
</script>
</body>
</html>
列表渲染
v-for
<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>第一天</title>
<script src="../js/vue.js"></script>
</head>
<body>
<div id="root">
<!-- 数组列表渲染 -->
<ul>
<li v-for="a in array" >{{a}}</li>
</ul>
<ul>
<li v-for="(a,index) in array" :key="index">{{a}}</li>
</ul>
<!-- 对象渲染 -->
<ul>
<li v-for="c in car">
{{c}}
</li>
</ul>
<ul>
<li v-for="(key,name) in car">
{{name}}--{{key}}
</li>
</ul>
<!-- 字符串遍历 -->
<ul>
<li v-for="s in str">
{{s}}
</li>
</ul>
<ul>
<li v-for="(index,value) in str">
{{index}}---{{value}}
</li>
</ul>
</div>
<script>
Vue.config.productionTip = false; //关闭vue的安全提示
//创建 vue 实例
new Vue({
el: "#root", //选取元素 通常为css选择字符串
//el:document.getElementById("root")
data: {
array:["java","javascript","php","dart","go"],
car:{
name:"五零宏光",
price:12+'w',
color:"白色"
},
str:"hello,world"
}
})
//配置对象
</script>
</body>
</html>
vue 中的动态修改数据
vue中动态添加对象属性
<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>第一天</title>
<script src="../js/vue.js"></script>
</head>
<body>
<div id="root">
<h1 v-if="student.sid">{{student.sid}}</h1>
<h1>{{student.name}}</h1>
<h1>{{student.age}}</h1>
<h1>{{student.sex}}</h1>
<button @click="addSid">添加学生学号</button>
</div>
<script>
Vue.config.productionTip = false; //关闭vue的安全提示
//创建 vue 实例
const vm = new Vue({
el: "#root", //选取元素 通常为css选择字符串
//el:document.getElementById("root")
data: {
student:{
name:"张山",
age:25,
sex:'男'
}
},
methods:{
addSid(){
//this.$set(vm.$data.student,"sid","1912021013") //均可实现动态添加对象属性
Vue.set(this.student,"sid","1912021013")
/*
* 此方法的局限性 (对象路径,key,value)
* 1、无法直接对根数据进行修改
* 2、无法对vue实例进行操作
* */
}
}
})
//配置对象
</script>
</body>
</html>
vue中动态添加数组属性
<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>第一天</title>
<script src="../js/vue.js"></script>
</head>
<body>
<div id="root">
<ul>
<li v-for="s in student">
{{s}}
</li>
</ul>
<button @click="updateStudent">修改学生</button>
</div>
<script>
Vue.config.productionTip = false; //关闭vue的安全提示
//创建 vue 实例
const vm = new Vue({
el: "#root", //选取元素 通常为css选择字符串
//el:document.getElementById("root")
data: {
student:['张山','李四','王五','老六']
},
methods:{
updateStudent(){
// 数组中的元素修改 也可使用Vue.set() 进行修改
Vue.set(this.student,3,"李六")
}
}
})
/*
* Vue 将被侦听的数组的变更方法进行了包裹,所以它们也将会触发视图更新。这些被包裹过的方法包括:
push()
pop()
shift()
unshift()
splice()
sort()
reverse()
*在使用这些方法修改数组元素时vue就会监视到数据发生了改变 变会对页面重新渲染
* */
</script>
</body>
</html>
vue中动态改变数据的原理总结
<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>第一天</title>
<script src="../js/vue.js"></script>
</head>
<body>
<div id="root">
<span>学生姓名{{student.name}}</span><button @click="addStudentName">为学生添加姓名</button>
<span>学生姓名{{student.sex}}</span><button @click="addStudentSex">为学生添加性别</button>
<span>学生姓名{{student.age}}</span><button @click="addStudentAge">为学生添加年龄</button>
<span>学生姓名{{student.sid}}</span><button @click="addStudentSid">为学生添加学号</button>
</div>
<script>
Vue.config.productionTip = false; //关闭vue的安全提示
//创建 vue 实例
const vm = new Vue({
el: "#root", //选取元素 通常为css选择字符串
//el:document.getElementById("root")
data: {
student:{
}
},
methods:{
vueSetProp(key,value){
this.$set(this.student,key,value)
},
addStudentName(){
this.vueSetProp("name","张山")
},
addStudentSex(){
this.vueSetProp("sex","男")
},
addStudentAge(){
this.vueSetProp("age",18)
},
addStudentSid(){
this.vueSetProp("sid","19220133201")
}
}
})
</script>
</body>
</html>
v-for 中的key的原理
<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>第一天</title>
<script src="../js/vue.js"></script>
</head>
<body>
<div id="root">
<!-- 数组列表渲染 -->
<ul>
<li v-for="item in array" :key="item.id">{{item}}</li>
<hr>
<li v-for="(item,index) in array" :key="index">{{item.name}}---{{index}}</li>
<hr>
<li v-for="item in array" >{{item.name}}---{{index}}</li>
</ul>
<!--
在v-for 进行渲染时
vue 默认会使用数组中的序号作为key进行渲染
当使用索引作为key使用时如果原数据中的index发生改变时会导致页面效果出问题
key一定要指定为唯一值
-->
<!-- 小案例 -->
<div>
<ul>
<li v-for="(item,index) in array">
{{item}}--{{index}} <input type="text">
</li>
</ul>
<button @click="add">添加</button>
</div>
</div>
<script>
Vue.config.productionTip = false; //关闭vue的安全提示
//创建 vue 实例
new Vue({
el: "#root", //选取元素 通常为css选择字符串
//el:document.getElementById("root")
data: {
array:[
{id:1, name:"java"},
{id:2, name:"php"},
{id:3, name:"javascript"},
{id:4, name:"c#"},
{id:5, name:"dart"},
{id:6, name:"go"},
]
},
methods:{
add(){
// this.array.push( {id:7, name:"c"})
//往数组后推时页面不发生改变,以为数组中的索引未发生改变
this.array.unshift({id:7, name:"c++"})
// 当在数组前进行推进的时候数组的索引值发生改变(当数据改变时vue将会重新渲染页面)
// vue将索引值作为唯一值对页面进行重新渲染,渲染时vue会对新旧元素进行对比
// 当唯一键相同时vue会对元素中的dom进行对比(不管value) dom相同(类型相同)就判断为旧元素 并进行渲染
//当唯一键不相同时将创建新的dom
}
}
})
//配置对象
</script>
</body>
</html>
列表案例-----排序
<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>第一天</title>
<script src="../js/vue.js"></script>
</head>
<body>
<div id="root">
<ul>
<li v-for="item in filterArray" >
{{item.id}}--{{item.name}}
</li>
</ul>
<input type="text" placeholder="请输入" v-model="keyWord">
<button @click="sortType = 2">升序</button>
<button @click="sortType = 1">降序</button>
<button @click="sortType = 0">原顺序</button>
</div>
<script>
Vue.config.productionTip = false; //关闭vue的安全提示
//创建 vue 实例
new Vue({
el: "#root", //选取元素 通常为css选择字符串
//el:document.getElementById("root")
data: {
keyWord:"",
sortType:0, //0代表原顺序 1代表降序 2代表升序
array:[
{id:1, name:"java"},
{id:4, name:"php"},
{id:3, name:"javascript"},
{id:7, name:"c#"},
{id:5, name:"dart"},
{id:2, name:"go"},
]
},
computed:{
filterArray(){
const arr = this.filterArray = this.array.filter((a)=>{
return a.name.indexOf(this.keyWord) !==-1
})
if(this.sortType)
arr.sort((a1,a2)=>{
return this.sortType === 1? a2.id-a1.id :a1.id-a2.id;
})
return arr;
}
}
})
//配置对象
</script>
</body>
</html>
列表案例----更新
<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>第一天</title>
<script src="../js/vue.js"></script>
</head>
<body>
<div id="root">
<button @click="updateJava">更新Java的信息</button>
<ul>
<li v-for="a in array">{{a}}</li>
</ul>
</div>
<script>
Vue.config.productionTip = false; //关闭vue的安全提示
//创建 vue 实例
const vm = new Vue({
el: "#root", //选取元素 通常为css选择字符串
//el:document.getElementById("root")
data: {
array: [{id: 1, name: "java"},
{id: 4, name: "php"},
{id: 3, name: "javascript"},
{id: 7, name: "c#"},
{id: 5, name: "dart"},
{id: 2, name: "go"},
]
},
methods:{
updateJava(){
// this.array[0].name="JAVA" //可行
this.array[0] = {id: 1, name: "JAVA"}
}
}
})
//配置对象
</script>
</body>
</html>
列表案例-----列表过滤 监视属性
<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>第一天</title>
<script src="../js/vue.js"></script>
</head>
<body>
<div id="root">
<ul>
<li v-for="item in filterArray" >
{{item.id}}--{{item.name}}
</li>
</ul>
<input type="text" placeholder="请输入" v-model="keyWord">
</div>
<script>
Vue.config.productionTip = false; //关闭vue的安全提示
//创建 vue 实例
new Vue({
el: "#root", //选取元素 通常为css选择字符串
//el:document.getElementById("root")
data: {
keyWord:"",
array:[
{id:1, name:"java"},
{id:2, name:"php"},
{id:3, name:"javascript"},
{id:4, name:"c#"},
{id:5, name:"dart"},
{id:6, name:"go"},
],
filterArray:[]
}
,watch:{
keyWord: {
immediate:true,
handler(val){
this.filterArray = this.array.filter((a)=>{
return a.name.indexOf(val) !==-1
})
}
}
}
})
//配置对象
</script>
</body>
</html>
列表案例-----列表过滤 计算属性
<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>第一天</title>
<script src="../js/vue.js"></script>
</head>
<body>
<div id="root">
<ul>
<li v-for="item in filterArray" >
{{item.id}}--{{item.name}}
</li>
</ul>
<input type="text" placeholder="请输入" v-model="keyWord">
</div>
<script>
Vue.config.productionTip = false; //关闭vue的安全提示
//创建 vue 实例
new Vue({
el: "#root", //选取元素 通常为css选择字符串
//el:document.getElementById("root")
data: {
keyWord:"",
array:[
{id:1, name:"java"},
{id:2, name:"php"},
{id:3, name:"javascript"},
{id:4, name:"c#"},
{id:5, name:"dart"},
{id:6, name:"go"},
]
},
computed:{
filterArray(){
return this.filterArray = this.array.filter((a)=>{
return a.name.indexOf(this.keyWord) !==-1
})
}
}
})
//配置对象
</script>
</body>
</html>
表单处理
<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>第一天</title>
<script src="../js/vue.js"></script>
</head>
<body>
<div id="root">
<form @submit.prevent="submitLogin">
<!-- 监测提交事件并阻止默认事件 -->
用户名:<input type="text" v-model.trim="userInfo.username"> <br><br>
密码:<input type="password" v-model="userInfo.password"> <br><br>
年龄:<input type="number" v-model.number="userInfo.age"> <br><br>
性别:<br><br>
男<input type="radio" name="sex" value="0" v-model="userInfo.sex">
女<input type="radio" name="sex" value="1" v-model="userInfo.sex">
<br><br>
爱好:<br><br>
<input type="checkbox" name="hobby" value="game" v-model="userInfo.hobby">打游戏
<input type="checkbox" name="hobby" value="code" v-model="userInfo.hobby">打代码
<input type="checkbox" name="hobby" value="eat" v-model="userInfo.hobby">吃饭
<br><br>
<select v-model="userInfo.city">
<option value="km">昆明</option>
<option value="cd">成都</option>
<option value="zt">昭通</option>
</select>
其他信息:<br><br>
<textarea v-model.lazy="userInfo.other">
</textarea>
<br><br>
<input type="checkbox" name="agree" v-model="userInfo.agree">同意我们的协议 <a href="baidu"></a>
<button>提交</button>
</form>
</div>
<script>
/*
* 表单提交的注意点以及知识点
* 在做表单数据交互时使用v-model 进行双向绑定
* 遇到radio单选的时候应该保证name值一样,并且设定好value
* 遇到checkbox时checkbox所双向绑定的数据类型一定得是数组并指定好value
* v-model的标识符为
* lazy 待输入框失去焦点时v-model才会提取数据
* number 定义输入的数据类型为数字型 与input中type=“number”不同
* type=“number” 定义用户输入类型为数字无法输入其他字符 如 abc....无法键入
* v-model.number 定义用户输入的数据类型为数值型 可以输入abc但是vue中不会拿去abc只会拿去数字
* trim 去除用户输入的数据中前后空格
* */
Vue.config.productionTip = false; //关闭vue的安全提示
//创建 vue 实例
new Vue({
el: "#root", //选取元素 通常为css选择字符串
//el:document.getElementById("root")
data: {
userInfo:{
username:"",
password:"",
age:"",
sex:"",
city:"",
hobby:[],
other:"",
agree:""
}
},
methods:{
submitLogin(){
console.log(JSON.stringify(this.userInfo))
}
}
})
</script>
</body>
</html>
过滤器
<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>第一天</title>
<script src="../js/vue.js"></script>
<script src="https://cdn.bootcdn.net/ajax/libs/dayjs/1.11.7/dayjs.min.js"></script>
</head>
<body>
<div id="root">
<h3>当前时间戳:{{timeNow}}</h3>
<h3>当前时间:{{getMethodTime()}}</h3>
<h3>当前时间:{{getComputedTime}}</h3>
<h3>当前时间:{{timeNow | getFilterTime('YYYY年MM月DD日 HH:mm:ss')}}</h3>
<h3>当前时间:{{timeNow | getFilterTime('YYYY年MM月DD日 HH:mm:ss') | mySlice}}</h3>
</div>
<div id="root2">
<h3>{{msg | mySlice}}</h3>
<h3 :x="msg | mySlice">你好,JavaScript</h3>
<!-- <input type="text" v-model="msg | mySlice">-->
<!--
注意过滤器只能使用在v-bind与插值语法中
-->
</div>
<script>
Vue.config.productionTip = false; //关闭vue的安全提示
//配置全局过滤器 全局可用
Vue.filter("mySlice",function(value){
return value.slice(0,5)
})
//创建 vue 实例
new Vue({
el: "#root", //选取元素 通常为css选择字符串
//el:document.getElementById("root")
data: {
timeNow: Date.now()
},
methods: {
getMethodTime(){
return dayjs(this.timeNow).format('YYYY-MM-DD HH:mm:ss');
}
},
computed:{
getComputedTime(){
return dayjs(this.timeNow).format('YYYY-MM-DD HH:mm:ss');
}
},
filters:{
// 当前配置的为局部过滤器 只能当前vm使用
getFilterTime(timeNow,str){
console.log(str)
return dayjs(timeNow).format(str);
},
// 局部过滤器
// mySlice(value){
// return value.slice(0,5)
// }
}
})
new Vue({
el:"#root2",
data:{
msg:"hello,world"
}
})
//配置对象
</script>
</body>
</html>
内置指令
v-text指令
<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>第一天</title>
<script src="../js/vue.js"></script>
</head>
<body>
<div id="root">
<h3>{{msg}},我喜欢你</h3>
<h3>{{content}}</h3>
<h3 v-text="msg">,我喜欢你</h3>
<h3 v-text="content"></h3>
<!--
插值语法比v-text更灵活
v-text 会把容器中的所有对象替换为我们的文本(即使纯在标签也会转义)
-->
</div>
<script>
Vue.config.productionTip = false; //关闭vue的安全提示
//创建 vue 实例
new Vue({
el: "#root", //选取元素 通常为css选择字符串
//el:document.getElementById("root")
data: {
msg:"你好啊,Javascript",
content:"<h3>你好</h3>"
}
})
//配置对象
</script>
</body>
</html>
v-html指令
<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>第一天</title>
<script src="../js/vue.js"></script>
</head>
<body>
<div id="root">
<h3 v-html="content"></h3>
<h3 v-text="msg"></h3>
<!--
v-html 可以把字符转换为dom元素节点
另外在使用v-html的时候需要注意防护xss攻击
-->
</div>
<script>
Vue.config.productionTip = false; //关闭vue的安全提示
//创建 vue 实例
new Vue({
el: "#root", //选取元素 通常为css选择字符串
//el:document.getElementById("root")
data: {
msg:"你好啊,Javascript",
content:"<h3>你好</h3>"
}
})
//配置对象
</script>
</body>
</html>
v-cloak指令
<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>第一天</title>
<style>
[v-cloak]{ display : none}
</style>
<script src="../js/vue.js"></script>
</head>
<!--
当服务器网速过慢时 vue的主要资源可能加载过慢这个时候利用 v-cloak 再配合[v-cloak]{ display : none} style属性来使用
可以达到在vue 未加载完成之前 不显示插值语法
此外需要注意的一点是 当 <script src="vue的资源地址"></script> 存在于head 标签中时 长时间获取不到资源会触发js延迟
js延迟:body标签中的所有节点都不会进行渲染 js代码也不会执行 只有等资源加载完毕后才进入执行
-->
<body>
<div id="root">
<h3 v-cloak>{{msg}}</h3>
<!--
v-html 可以把字符转换为dom元素节点
另外在使用v-html的时候需要注意防护xss攻击
-->
</div>
<script>
Vue.config.productionTip = false; //关闭vue的安全提示
//创建 vue 实例
new Vue({
el: "#root", //选取元素 通常为css选择字符串
//el:document.getElementById("root")
data: {
msg:"你好啊,Javascript",
}
})
//配置对象
</script>
</body>
</html>
v-once指令
<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>第一天</title>
<style>
[v-cloak]{ display : none}
</style>
<script src="../js/vue.js"></script>
</head>
<body>
<div id="root">
<h3 v-once>n的初始值:{{n}}</h3>
<h3>n现在是:{{n}}</h3>
<button @click="n++">n+1</button>
<!--
v-once 指令标注的节点只会被渲染一次 一次过后会被当作静态资源
就算后续数据更新也不会再次渲染
-->
</div>
<script>
Vue.config.productionTip = false; //关闭vue的安全提示
//创建 vue 实例
new Vue({
el: "#root", //选取元素 通常为css选择字符串
//el:document.getElementById("root")
data: {
n:1
}
})
//配置对象
</script>
</body>
</html>
v-pre 指令
<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>第一天</title>
<style>
[v-cloak]{ display : none}
</style>
<script src="../js/vue.js"></script>
</head>
<body>
<div id="root">
<h3 v-pre>n的初始值:{{n}}</h3>
<h3 v-pre>n现在是:{{n}}</h3>
<button @click="n++" v-pre>n+1</button>
<!--
v-pre 指令
v-pre指令标注的节点将不会进行编译
在没有使用插值语法的节点上使用可以优化编译速度
-->
</div>
<script>
Vue.config.productionTip = false; //关闭vue的安全提示
//创建 vue 实例
new Vue({
el: "#root", //选取元素 通常为css选择字符串
//el:document.getElementById("root")
data: {
n:1
}
})
//配置对象
</script>
</body>
</html>
自定义指令
函数式
<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>第一天</title>
<script src="../js/vue.js"></script>
</head>
<body>
<div id="root">
<h3>n的值:{{n}}</h3>
<h3 v-big="n">n放大10倍后</h3>
<button @click="n++">n+1</button>
</div>
<script>
Vue.config.productionTip = false; //关闭vue的安全提示
new Vue({
el: "#root", //选取元素 通常为css选择字符串
data: {
n:1
},
directives:{
/*
* 自定义指令函数式函数被调用的时机
* 1.指令于元素成功绑定时发生调用
* 2.指令所在的模板被出现解析时发生调用
* */
big(element,binding){
// element 是所使用的这个指令的真实dom元素
// binding 传入进来得到参数
element.innerText = binding.value * 10
},
}
})
//配置对象
</script>
</body>
</html>
对象式
<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>第一天</title>
<script src="../js/vue.js"></script>
</head>
<body>
<div id="root">
<h3>n的值:{{n}}</h3>
<h3 v-big="n">n放大10倍后</h3>
<button @click="n++">n+1</button>
<input type="text" v-fbind:value="n">
</div>
<script>
Vue.config.productionTip = false; //关闭vue的安全提示
/*
* 全局指令与全局过滤器一样
* */
// 全局指令的配置方式
Vue.directive('big',function (element,binding){
// element 是所使用的这个指令的真实dom元素
// binding 传入进来得到参数
element.innerText = binding.value * 10
})
Vue.directive('fbind',{
bind(element,binding){
element.value = binding.value * 10
},
inserted(element,binding){
element.focus()
},
update(element,binding){
console.log(binding)
element.value = binding.value * 10
}
})
new Vue({
el: "#root", //选取元素 通常为css选择字符串
data: {
n:1
},
directives:{
/*
* 自定义指令函数式函数被调用的时机
* 1.指令于元素成功绑定时发生调用
* 2.指令所在的模板被出现解析时发生调用
* */
big(element,binding){
// element 是所使用的这个指令的真实dom元素
// binding 传入进来得到参数
element.innerText = binding.value * 10
},
fbind:{
/*
* 对象式指令分为了3个周期:
* bind元素与指令绑定成功之后
* inserted元素插入到页面以后
* update元素所在模板被解析时
* */
bind(element,binding){
element.value = binding.value * 10
},
inserted(element,binding){
element.focus()
},
update(element,binding){
console.log(binding)
element.value = binding.value * 10
}
}
}
})
/*
* 注意点:
* 自定义指令的命名问题
* 自定义指令中 命名应该遵循官方风格 如"v-add-student" 那函数名就应该为 "add-student"function(){}
* 关于所有指令的this 指向问题 所有的指令的this 均为window 不是vm
*以上所配置的指令均为局部指令
* */
</script>
</body>
</html>
生命周期函数
前言
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="root">
<h2 :style="{opacity}">{{msg}}</h2>
</div>
<!--
Vue生命周期是指vue实例对象从创建之初到销毁的过程
vue所有功能的实现都是围绕其生命周期进行的
在生命周期的不同阶段调用对应的钩子函数可以实现组件数据管理和DOM渲染两大重要功能。
生命周期函数中的this 是vm或者是组件对象
-->
<script src="../js/vue.js">
</script>
<script>
new Vue({
el:"#root",
data:{
msg:"你好,vue",
opacity:1
},
//mounted ,数据和DOM都已被渲染出来 后调用的函数
mounted(){
console.log("挂载完毕")
setInterval(()=>{
this.opacity = this.opacity - 0.01
if(this.opacity < 0) this.opacity = 1
},16)
}
})
</script>
</body>
</html>
分析生命周期函数
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="root">
<h2 :style="{opacity}">{{msg}}</h2>
<button @click="xh">销毁vue</button>
</div>
<script src="../js/vue.js">
</script>
<script>
const vm = new Vue({
el: "#root",
data: {
msg: "你好,vue",
opacity: 1
},
methods: {
xh(){
this.$destroy();
}
},
//创建前
beforeCreate() {
console.log("vue 创建前")
},
//创建后
created() {
console.log("vue 创建后")
},
//载入前
beforeMount() {
console.log("vue 载入前")
},
//载入后
mounted() {
console.log("挂载完毕")
setInterval(() => {
this.opacity = this.opacity - 0.01
if (this.opacity < 0) this.opacity = 1
}, 16)
},
//更新前
beforeUpdate() {
// console.log("更新前")
},
//更新后
updated() {
//console.log("更新后")
},
//销毁前
beforeDestroy() {
console.log("销毁前")
},
//销毁后
destroyed() {
console.log("销毁后")
}
})
/*
* 1、创建前(beforeCreate)
对应的钩子函数为beforeCreate。此阶段为实例初始化之后,此时的数据观察和事件机制都未形成,不能获得DOM节点。
2、创建后(created)
对应的钩子函数为created。在这个阶段vue实例已经创建,仍然不能获取DOM元素。
3、载入前(beforeMount)
对应的钩子函数是beforemount,在这一阶段,我们虽然依然得不到具体的DOM元素,但vue挂载的根节点已经创建,下面vue对DOM的操作将围绕这个根元素继续进行;beforeMount这个阶段是过渡性的,一般一个项目只能用到一两次。
4、载入后(mounted)
对应的钩子函数是mounted。mounted是平时我们使用最多的函数了,一般我们的异步请求都写在这里。在这个阶段,数据和DOM都已被渲染出来。
5、更新前(beforeUpdate)
对应的钩子函数是beforeUpdate。在这一阶段,vue遵循数据驱动DOM的原则;beforeUpdate函数在数据更新后虽然没立即更新数据,但是DOM中的数据会改变,这是Vue双向数据绑定的作用。
6、更新后(updated)
对应的钩子函数是updated。在这一阶段DOM会和更改过的内容同步。
7、销毁前(beforeDestroy)
对应的钩子函数是beforeDestroy。在上一阶段vue已经成功的通过数据驱动DOM更新,当我们不在需要vue操纵DOM时,就需要销毁Vue,也就是清除vue实例与DOM的关联,调用destroy方法可以销毁当前组件。在销毁前,会触发beforeDestroy钩子函数。
8、销毁后(destroyed)
对应的钩子函数是destroyed。在销毁后,会触发destroyed钩子函数。
*
* */
</script>
</body>
</html>
组件化编程(Vue高级开发)
<!--组件是什么?-->
<!--组件是可复用的 Vue 实例,-->
<!--把一些公共的模块抽取出来,-->
<!--然后写成单独的的工具组件或者页面,-->
<!--在需要的页面中就直接引入即可那么我们可以将其抽出为一个组件进行复用。-->
<!--例如 页面头部、侧边、内容区,尾部,上传图片,-->
<!--等多个页面要用到一样的就可以做成组件,提高了代码的复用率。-->
<!doctype html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<!--
组件的形式
a.vue
组件包含:
单文件组件
一个文件内只有一个组件
多文件组件
一个文件内又多个组件
-->
</body>
</html>
非单文件组件
VueComponent的构造函数
<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>组件的嵌套</title>
<script src="../../js/vue.js"></script>
</head>
<body>
<div id="root">
<school></school>
</div>
<script>
Vue.config.productionTip = false; //关闭vue的安全提示
/*
* 组件的本质是一个名为VueComponent的构造函数,不是程序员定义的而是由Vue.extend()生成的
*我们只需要使用<school></school> Vue就会帮我们创建<school></school>组件的实例对象
* 即vue 会帮我们执行 new VueComponent()
* 需要注意的是 每次调用ue.extend 返回的都是一个全新的 VueComponent
*
* 关于this指向问题
* 组件配置中
* data函数,methods中的函数,watch,computed,他们中的this 均为VueComponent 的实例对象
* new vue
* data函数,methods中的函数,watch,computed,他们中的this 均为vue的实例对象
* VueComponent 的实例对象均称为vc(组件实例对象)
* vue的实例对象 称vm
* */
const school = Vue.extend({
template: `
<div>
<h3>{{ name }}</h3>
<h3>{{ address }}</h3>
</div>
`,
data() {
return {
name: "小学",
address: "凤凰镇"
}
}
})
new Vue({
el: "#root",
components: {
school
},
})
</script>
</body>
</html>
非单文件组件的使用
<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>组件</title>
<script src="../../js/vue.js"></script>
</head>
<body>
<div id="root">
<!-- 3、使用组件 -->
<hello></hello>
<student></student>
<hr>
<!-- 3、使用组件 -->
<school></school>
<hello></hello>
</div>
<!--
组件注册分为三步
1、创建组件
2、注册组件
1、局部组件
2、全局组件
3、使用组件
-->
<script>
Vue.config.productionTip = false; //关闭vue的安全提示
// 1、创建组件
const student = Vue.extend({
/*
* 组件配置的时候
* 不需要写el配置项 因为组件并不是为单个容器服务
* data 必须为函数式 对象式对各个组件之间相互影响 且vue强制要求为函数式
* 在VM中的配置项 组件中几乎都可以使用
* */
//配置组件结构
/*
* template 模板
* 模板只能纯在一个根节点
* */
template: `
<div>
<h3>{{name}}</h3>
<h3>{{age}}</h3>
</div>
`,
//配置组件数据
data(){
return{
name:"张山",
age:18
}
}
})
// 1、创建组件
const school = Vue.extend({
template:`
<div>
<h3>{{name}}</h3>
<h3>{{address}}</h3>
</div>
`,
data(){
return{
name:"小学",
address:"凤凰镇"
}
}
})
const hello = Vue.extend({
template:`
<div>
<h1>你好啊,Vue</h1>
</div>
`,
})
//配置全局组件
Vue.component('hello',hello)
new Vue({
el: "#root",
// 2、注册组件
// 1、局部组件
components:{
school,
student
}
})
//配置对象
</script>
</body>
</html>
非单文件组件的嵌套组件
<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>组件的嵌套</title>
<script src="../../js/vue.js"></script>
</head>
<body>
<div id="root">
</div>
<script>
Vue.config.productionTip = false; //关闭vue的安全提示
const student = Vue.extend({
template: `
<div>
<h3>{{ name }}</h3>
<h3>{{ age }}</h3>
</div>
`,
data() {
return {
name: "张山",
age: 18
}
}
})
const school = Vue.extend({
template: `
<div>
<h3>{{ name }}</h3>
<h3>{{ address }}</h3>
<student></student>
</div>
`,
data() {
return {
name: "小学",
address: "凤凰镇"
}
},
components: {
student
}
})
const hello = Vue.extend({
template: `
<div>
<h1>你好啊,Vue</h1>
</div>
`,
})
const app = {
template:`
<div>
<school>
</school>
<hello></hello>
</div>
`,
components:{
school,
hello
}
}
Vue.component('hello', hello)
new Vue({
el: "#root",
components: {
app
},
template:`<app></app>`
})
/*
* 组件的嵌套方式
* 先定义组件
* 在父元素中注册子组件
* 在父元素的template 中 写入子组件
*
* 标准化开发中我们通常使用app为组件管理者再将app交由vm管理
* 即 vm -> app -> school->student
* -> hello
* */
</script>
</body>
</html>
一个重要的内置关系
<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>组件的嵌套</title>
<script src="../../js/vue.js"></script>
</head>
<body>
<div id="root">
<school></school>
</div>
<script>
Vue.config.productionTip = false; //关闭vue的安全提示
const school = Vue.extend({
template: `
<div>
<h3>{{ name }}</h3>
<h3>{{ address }}</h3>
</div>
`,
data() {
return {
name: "小学",
address: "凤凰镇"
}
}
})
new Vue({
el: "#root",
components: {
school
},
})
/**
1、school组件本质是一个名为VueComponent的构造函数,且不是程序员定义的,是Vue.extend生成的
2、我们只需要写<school/>或<school</school>,vue解析时会帮我们创建school组件的实例对象;
即Vue帮我们执行的:new VueComponent(options)
3、特别注意:每次调用Vue.extend,返回的都是一个全新的VueComponent
4、关于this指向:
组件配置中:data函数、methods中的函数、watch中的函数、computed中的函数 它们的this均是 VueComponent实例对象
new Vue(options)配置中:data函数、methods中的函数、watch中的函数、computed中的函数 它们的this均是 Vue实例对象
5、VueComponent的实例对象,以后简称vc ---- 组件实例对象
一个重要的内置关系:VueComponent.prototype._proto_===Vue.prototype
为什么要有这个关系:让组件实例对象vc可以访问到Vue原型上的属性、方法
*/
//https://blog.youkuaiyun.com/qq_52764447/article/details/121635167
</script>
</body>
</html>
非单文件组件的注意事项
<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>组件</title>
<script src="../../js/vue.js"></script>
</head>
<body>
<div id="root">
<Hello></Hello>
<student></student>
<my-school></my-school>
</div>
<script>
Vue.config.productionTip = false; //关闭vue的安全提示
const s = Vue.extend({
template: `
<div>
<h3>{{ name }}</h3>
<h3>{{ age }}</h3>
</div>
`,
//配置组件数据
data() {
return {
name: "张山",
age: 18
}
}
})
const school = Vue.extend({
name:"school",//定义组件名字 开发者工具将一直显示为name
template: `
<div>
<h3>{{ name }}</h3>
<h3>{{ address }}</h3>
</div>
`,
//配置组件数据
data() {
return {
name: "凤凰小学",
address: "凤凰小镇"
}
}
})
const h = Vue.extend({
template: `
<div>
<h1>你好啊,Vue</h1>
</div>
`,
})
Vue.component('Hello', h)
new Vue({
el: "#root",
components: {
Student:s,
'my-school':school
}
})
/*
* 在vue中的命名规范
* 1、单个单词为组件名时组件的名字可以全部小写或者首字母大写 例如 hello Hello
* 2、多个单词为组件名时组件的名字应该单词全部小写单词与单词之间写一个- 例如'my-school':school 或者使用大驼峰法(需要在脚手架中才能使用)
* 3、尽可能回避html 中已经存在的元素名称
* 4、标签使用时 可以使用 自闭和 <hello/> (只能在脚手架中使用)
* 5、简写 const h = {template: `<div><h1>你好啊,Vue</h1></div> `}
* */
</script>
</body>
</html>
单文件组件
单文件组件中.vue文件就是一个组件
注意:单文件组件无法直接运行在浏览器上…无法识别import…等关键字和.vue文件
单文件组件中的必要条件:
一个vue单组件程序应该有一个vm管理一个组件(app.vue)
所以应该使用应该app.vue来管理我们的所有vue组件
程序入口
main.js
import App from "./App.vue";
const vm = new Vue({
el:"#root",
template:"<App></App>",
components:{App}
})
程序主要的组件
app.vue
import App from "./App.vue";
const vm = new Vue({
el:"#root",
template:"<App></App>",
components:{App}
})
其它组件
子组件
<template>
<div>
<h3>{{name}}</h3>
<h3>{{age}}</h3>
</div>
</template>
<script>
export default {
name:"School",
data(){
return {
name:"凤凰小学",
age:18
}
}
}
</script>
<style>
</style>
父组件
<template>
<div>
<h3>{{name}}</h3>
<h3>{{address}}</h3>
<student></student>
</div>
</template>
<script>
import Student from "./Student.vue";
export default {
name:"School",
data(){
return {
name:"凤凰小学",
address:"凤凰小镇"
}
},
components:{
Student
}
}
</script>
<style>
</style>
vue的工程化开发
分析脚手架
什么是脚手架?
Vue CLI 是一个基于 Vue.js 进行快速开发的完整系统,提供:
- 通过 @vue/cli 实现的交互式的项目脚手架。
- 通过 @vue/cli + @vue/cli-service-global 实现的零配置原型开发。
- 一个运行时依赖 (@vue/cli-service),该依赖:
-
- 可升级;
-
- 基于 webpack 构建,并带有合理的默认配置;
-
- 可以通过项目内的配置文件进行配置;
-
- 可以通过插件进行扩展。
-
- 一个丰富的官方插件集合,集成了前端生态中最好的工具。
-
- 一套完全图形化的创建和管理 Vue.js 项目的用户界面。
- Vue CLI 致力于将 Vue 生态中的工具基础标准化。它确保了各种构建工具能够基于智能的默认配置即可平稳衔接,这样你可以专注在撰写应用上,而不必花好几天去纠结配置的问题。与此同时,它也为每个工具提供了调整配置的灵活性,无需 eject。
安装
npm install -g @vue/cli@3
创建一个项目
vue create hello-world
官网
https://cli.vuejs.org/zh/
目录结构
文件分析
main.js
// 导入 app 组件模块
import App from "@/App.vue";
// 导入Vue 核心
import Vue from "vue";
// 创建vue 实例
new Vue({
// 指定容器
el:"#app",
/*
* 为什么要使用render()
* 作用:
* Render 函数是 Vue2.x 新增的一个函数
* 主要用来提升节点的性能,它是基于 JavaScript 计算。
* 使用 Render 函数将 Template 里面的节点解析成虚拟的 Dom 。
*
* 为什么:
* 因为脚手架默认导入的js核心 为阉割版核心(即去除了模板解析模块)
* 所以需要使用render()对模板进行解析
* */
render:h=>h(App)
})
app.vue
<!-- 指定模块结构-->
<template>
<div class="demo">
<MySchool/>
<h1 ref="title">你好啊</h1>
<!-- ref 的作用与id的作用一致 是用于拿去这些元素 -->
<button @click="showMsg"></button>
<!-- 使用其他模块 -->
</div>
</template>
<script>
//引入其他模块
import MySchool from "@/components/MySchool.vue";
export default {
name: "App",
components:{
// eslint-disable-next-line vue/no-unused-components
//进行模块注册
MySchool
},
methods:{
showMsg(){
// this.$refs.title 拿取ref=“title”的元素
console.log(this.$refs.title)
//当获取的是组件的时候 我们获取到的是组件的vc对象
}
}
}
</script>
<!--模块样式-->
<style scoped>
.demo{
background-color: orange;
}
</style>
ref属性
<template>
<div class="demo">
<MySchool/>
<h1 ref="title">你好啊</h1>
<!-- ref 的作用与id的作用一致 是用于拿去这些元素 -->
<button @click="showMsg">点我</button>
<!-- 使用其他模块 -->
</div>
</template>
<script>
import MySchool from "@/components/MySchool.vue";
export default {
name: "App",
components:{
// eslint-disable-next-line vue/no-unused-components
MySchool
},
methods:{
showMsg(){
// this.$refs.title 拿取ref=“title”的元素
console.log(this.$refs.title)
}
}
}
</script>
<style scoped>
.demo{
background-color: orange;
}
</style>
props属性
<template>
<div class="demo">
<MyStudent name="张三" sex="男" age="18"/>
<!-- age="18" 18传输过去以后只能是string 而不是number 可以使用 :age 传输后为number -->
</div>
</template>
<script>
import MyStudent from "@/components/MySchool.vue";
export default {
name: "App",
components:{
MyStudent
},
methods:{
}
}
</script>
<style scoped>
.demo{
background-color: orange;
}
</style>
<template>
<div>
<h2>{{msg}}</h2>
<h3>{{name}}</h3>
<h3>{{sex}}</h3>
<h3>{{age}}</h3>
</div>
</template>
<script>
export default {
name: "MyStudent",
data() {
return {
msg:"你好啊 欢迎来到vue"
}
},
//第一种接收方式
//第一种方式 强制性不高 并且呢只做接收
// props:["name","age","sex"]
//第二种方式强制指定数据类型
// props:{
// name:String,
// age:Number,
// sex:String
// }
//第三种限制类型,必要条件,默认值
props:{
name:{
type:String,
required:true,
},
age:{
type:Number,
default:12
},
sex:{
type:String
}
}
/*
* props 的数据优先级比data高的数据集合
* props 中的数据是不可修改的如业务需求确实要改 可以在data中声明一个变量(不能同名)来存储
* */
}
</script>
<style scoped>
</style>
mixin(混入)
所谓混入 就是两个组件使用同一套配置
/*
* 功能:可以配置 所有vc的配置 并把这个配置共有(也就是把配置混入vc中)
* */
const mixin = {
methods: {
showName() {
alert(this.name)
}
}
}
const mixin2 = {
data() {
return {
x:100,
y: 200
}
}
}
export {mixin,mixin2};
使用
import App from "@/App.vue";
import Vue from "vue";
import {mixin,mixin2} from "@/mixin/mixin";
Vue.config.productionTip=false
// 进行全局配置
/*
* 全局配置后所有的vm和vc都会带又mixin
*
* */
Vue.mixin(mixin)
Vue.mixin(mixin2)
new Vue({
el:"#app",
render:h=>h(App)
})
<template>
<div class="demo">
<MyStudent/>
<!-- age="18" 18传输过去以后只能是string 而不是number 可以使用 :age 传输后为number -->
</div>
</template>
<script>
import MyStudent from "@/components/MySchool.vue";
// import {mixin, mixin2} from "@/mixin/mixin";
export default {
name: "App",
components:{
MyStudent
},
// mixins:[mixin,mixin2]
}
</script>
<style scoped>
.demo{
background-color: orange;
}
</style>
<template>
<div>
<h2>{{msg}}</h2>
<h3 @click="showName">{{name}}</h3>
</div>
</template>
<script>
//导入mixin
// import {mixin,mixin2} from "@/mixin/mixin";
export default {
name: "MyStudent",
data() {
return {
msg:"你好啊 欢迎来到vue",
name:"张三",
}
}
// 局部配置mixin
// mixins:[mixin,mixin2]
}
</script>
<style scoped>
</style>
插件
插件是一种能增强Vue全局功能的一种代码
自定义插件
// 插件的声明
export default {
/**
* @Vue Vue的应用实例
* @options 是在插件使用时 传入的参数
* */
install(Vue,options) {
console.log(Vue)
//以下定义的内容为全局定义
Vue.filter("mySlice", function (value) {
return value.slice(0, 5)
})
Vue.directive('fbind', {
bind(element, binding) {
console.log(binding)
element.value = binding.value * 10
},
inserted(element, binding) {
element.focus()
console.log(binding)
},
update(element, binding) {
console.log(binding)
element.value = binding.value * 10
}
})
Vue.mixin({
data() {
return {
x: 100,
y: 200
}
}
})
}
}
/*
* 插件的使用
* */
import App from "@/App.vue";
import Vue from "vue";
// 导入插件
import plugin from "./plugins/overallPlugin"
Vue.config.productionTip=false
// 使用插件并传递参数
Vue.use(plugin,{el:"root"})
new Vue({
el:"#app",
render:h=>h(App)
})
scoped 样式属性
<style scoped>
.demo{
background-color: orange;
}
</style>
加上scoped后可以有效的隔离样式 把样式模块化
todo-list 案例
案例分析-模块课分为5个模块
模块代码
app模块
<template>
<div class="body">
<AddTodo :addTodo="addTodo"/>
<TodoList :List="todoList" :checkTodo="checkTodo" :deleteTodo="deleteTodo" />
<TodoInfo :todoList="todoList" :checkedTodoAll="checkedTodoAll" :clearTodos="clearTodos"/>
</div>
</template>
<script>
import AddTodo from "@/components/AddTodo.vue";
import TodoList from "@/components/TodoList.vue";
import TodoInfo from "@/components/TodoInfo.vue";
export default {
name: "App",
components:{
AddTodo,
TodoList,
TodoInfo
},
data(){
return{
todoList:[
{id:"001",title:"吃饭",done:true},
{id:"002",title:"打代码",done:true},
{id:"003",title:"睡觉",done:false}
]
}
},
methods:{
addTodo(todo){
this.todoList.unshift(todo)
},
checkTodo(id){
console.log(id)
this.todoList.forEach((todo)=>{
if(todo.id === id){
todo.done = !todo.done
}
})
},
deleteTodo(id){
if(confirm("你确定要删除吗?"))
this.todoList = this.todoList.filter((todo)=>{
return todo.id !== id
})
},
checkedTodoAll(done){
this.todoList.forEach((todo)=>{todo.done = done})
},
clearTodos(){
this.todoList = this.todoList.filter((todo)=>{
return todo.done !== true
})
}
},
mounted() {
console.log(this.todoList)
}
}
</script>
<style>
.body{
width: 500px;
height: auto;
background-color: white;
border: gray solid 1px;
margin: 0 auto;
padding: 10px;
border-radius: 10px;
}
</style>
添加模块
<template>
<div class="todo-input">
<input type="text" placeholder="请输入你的任务名称,按回车确认" @keyup.enter="add">
</div>
</template>
<script>
import {nanoid} from "nanoid"
export default {
name: "AddTodo",
methods:{
add(element){
if(element.target.value !== ""){
const todo = {id:nanoid(),title:element.target.value,done:false}
this.addTodo(todo)
element.target.value = ""
}else {
alert("请输入任务内容")
}
}
},
props:["addTodo"]
}
</script>
<style scoped>
.todo-input{
width: 100%;
display: flex;
}
.todo-input input{
width: 80%;
text-align: center;
margin: 0 auto;
height: 30px;
font-size: 15px;
border-radius: 10px;
}
</style>
数据展示模块
<template>
<ul class="list">
<TodoItem v-for="todo in List" :key="todo.id" :todo="todo" :checkTodo="checkTodo" :deleteTodo="deleteTodo"/>
</ul>
</template>
<script>
import TodoItem from "./TodoItem.vue";
export default {
name: "TodoList",
// eslint-disable-next-line vue/no-unused-components
components:{TodoItem},
props:["List","checkTodo","deleteTodo"]
}
</script>
<style scoped>
.list{
list-style: none;
margin: 20px auto;
}
</style>
数据项展示
<template>
<div>
<li class="item">
<!-- 第一种实现 -->
<input type="checkbox" :checked="todo.done" @click="updateTodo(todo)">{{todo.title}}
<!-- 第二种实现 -->
<!-- <input type="checkbox" v-model="todo.done">{{todo.title}} -->
<!--
实现原理:
v-model 主要针对value 的设定
当在checkbox中使用到了v-model 且 value 是布尔值的时候我们可以vue 会帮我们管理涉及的值
但是处于vue的props 原则 不应该采用这种方式
-->
<button class="btn" @click="deleteMyTodo(todo)">删除</button></li>
</div>
</template>
<script>
export default {
name: "TodoItem",
props:["todo","checkTodo","deleteTodo"],
methods:{
updateTodo(todo){
console.log(todo)
this.checkTodo(todo.id)
},
deleteMyTodo(todo){
this.deleteTodo(todo.id)
}
}
}
</script>
<style scoped>
.item{
/*width: 100%;*/
color: gray;
border: gray solid 1px;
padding: 5px;
}
input:checked{
color: #627BF6;
}
.btn{
background-color: #e65b46;
color: white;
border-radius: 5px;
padding: 5px;
border: none;
float:right;
user-select: none;
}
.btn:active{
background-color: #c1442b;
}
</style>
底部展示模块
<template>
<div class="todo-info" v-if="todoList.length">
<!-- 第一种写法 -->
<!-- <input type="checkbox" :checked="isAll" @change="checkedAllTodo"> 已完成 {{todoNumber}} / 全部{{todoList.length}} -->
<!-- 第二种写法 -->
<input type="checkbox" v-model="isAll" > 已完成 {{todoNumber}} / 全部{{todoList.length}}
<button class="btn" @click="clearTodo">清除已完成的任务</button>
</div>
</template>
<script>
export default {
name: "TodoInfo",
data(){
return{
}
},
methods:{
checkedAllTodo(e){
this.checkedTodoAll(e.target.checked)
},
clearTodo(){
this.clearTodos()
}
},
computed:{
todoNumber() {
return this.todoList.filter((todo) => {
return todo.done === true
}).length
},
// isAll(){
// return this.todoNumber === this.todoList.length
// }
isAll:{
get(){
return this.todoNumber === this.todoList.length
},
set(value){
this.checkedTodoAll(value)
}
}
},
props:["todoList","checkedTodoAll","clearTodos"]
}
</script>
<style scoped>
.btn{
background-color: #e65b46;
color: white;
border-radius: 5px;
padding: 5px;
border: none;
float:right;
user-select: none;
}
.btn:active{
background-color: #c1442b;
}
</style>
浏览器本地存储
优化Todos—本地存储
组件的自定义事件
自定义事件改进todolist
全局事件总线
任意组件间的通讯
消息订阅与发布
是一种组件间通讯的方式 适用与任意组件间的通讯
需要使用插件pubsub-js
消息订阅与发布改进todolist
$nextTick
动画过渡
过度效果
多个元素过度
animate.css
配置代理
github 搜索案例
vue-resource
插槽
默认插槽
具名插槽
作用域插槽
vuex
vuex 是vue中实现集中式状态(数据)管理Vue的一个插件
多个组件的共享状态进行集中式的管理(读/写),也是一种组件间的通讯方式
且适用于任意间通信
什么时候用vuex
- 多个组件依赖同一状态
- 不同组件的行为需要变更同一状态
求和案例
vuex 的原理
vuex 的使用
1、安装
2、vue.use()
3、store()
4、vc === store()
vuex 改进 求和案例
vuex 的 getters 配置项
vuex 的 mapState
vuex 的 mapGetters
vuex 的 mapActions
vuex 的 mapMutations
vuex 的 多组件之间共享数据
vuex 的 模块化编码
vuex 的 命名空间
路由
路由的基本使用
安装 vue-router
使用 vue-router
使用route需要注意的事项
多级路由(嵌套路由)
query 参数
params 参数
name 属性
props 参数
replace 参数
编程式路由导航
缓存路由组件
两个新的生命周期钩子
这两个钩子是路由组件独有的
activated() 激活 deactivated 失活
路由守卫
保护路由的权限
前置路由守卫
后置路由后卫
独享路由守卫
组件内置路由
history与hash模式
两种模式:
(1)、hash模式
1、网页地址#后的都被称为hash值
2、所有的hash 值都不会被发给服务器
3、兼容性好
(2)、history
1、网页地址中不在有#
2、兼容性差
打包项目
npm run build
#vue-cli-service build
打包后会出现一个dist文件
在history模式下
项目部署以后在刷新后将会把网址作为请求路径发送给服务器
解决方案
spring boot 下我们可以使用ErrorPageRegistrar 对错误页面进行全局拦截 同一跳转到index
ui组件库(element ui)
移动端组件库:
1、vant
2、cube ui
3、Mint ui
pc端组件库
element ui
Iview ui
element ui 按需引入
看文档
https://element.eleme.cn/#/zh-CN