尚硅谷Vue2.0+Vue3.0全套教程丨vue.js从入门到精通

1.Vue核心部分

1.1 Vue简介

1.1.1 Vue是什么?

Vue是一套用于构建用户界面的渐进式JavaScript框架。

  • 渐进式:Vue可以自底向上逐层的应用;
  • 简单应用:只需一个轻量小巧的核心库。
  • 复杂应用:可以引入各式各样的Vue插件。

1.1.2 Vue作者

尤雨溪

1.1.3 Vue的特点

  • 采用组件化模式,提高代码复用率,且让代码更好维护。
  • 声明式编码,让编码人员无需直接操作DOM,提高开发效率。
  • 使用虚拟DOM+优秀的Diff算法,尽量复用DOM节点。

1.1.4 Vue学习的JavaScript前备知识点

  • ES6语法规范
  • ES6模块化
  • 包管理器
  • 原型、原型链
  • 数组常用方法
  • axios
  • promise

1.1.5 Vue使用指南

Vue官网:https://cn.vuejs.org/
官网导航菜单栏中最重要的是教程和API。

1.1.6 搭建Vue开发环境

1.2 初识Vue

1.2.1 Hello小实例
<!--
初识Vue:1. 想让Vue工作,就必须创建一个Vue实例,且要传入一个配置对象;2. root容器里的代码依然符合html规范,只不过混入了一些特殊的Vue语法;3. root容器里的代码被称为【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>初识Vue</title><!-- 引入Vue.js --><script src="../js/vue.js"></script>
</head>
<body><div id="root"><!-- 插值语法插入name=尚硅谷:{{name}} --><h1>Hello,{{name}}</h1></div><script>Vue.config.productionTip = false;   //阻止Vue在启动时生成生产提示//创建Vue实例new Vue({el:'#root', //el用于指定当前Vue实例为那个容器服务,值通常为css选择器字符串。data:{  //data中用于存储数据,数据供el所指定的容器使用,值我们暂时先写成一个对象。name:'尚硅谷'   }})</script>
</body>
</html>
1.2.2 分析Hello案例
<!--
初识Vue:4. Vue实例和容器是一一对应的;5. 真实开发中只有一个Vue实例,并且会配合着组件一起使用;6. {{xxx}}中的xxx要写js表达式,且xxx可以自动读取到data中的所有属性;7. 一旦data中的数据发生改变,那么模板中用到该数据的地方也会自动更新。注意区分js表达式和js代码(语句)1. 表达式:一个表达式会产生一个值,可以放到任何一个需要值的地方。(1). a(2). a+b(3). demo(1)(4). x === y ? 'a' : 'b'2. js代码(语句)(1). if(){}(2). for(){}
--><!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>初识Vue</title><!-- 引入Vue.js --><script src="../js/vue.js"></script>
</head>
<body><div id="root"><h1>Hello,{{name.toUpperCase()}},{{address}},{{Date.now()}}</h1></div><script>Vue.config.productionTip = false;   //阻止Vue在启动时生成生产提示//创建Vue实例new Vue({el:'#root', data:{  name:'shangguigu',address:'北京'   }})</script>
</body>
</html>

1.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>模板语法</title><!-- 引入Vue.js --><script src="../js/vue.js"></script>
</head>
<body><!-- Vue模板语法有两大类:1.插值语法功能:用于解析标签体内容。写法:{{xxx}}, xxx是js表达式,且可以直接读取到data中的所有属性。2.指令语法功能:用于解析标签(包括:标签属性、标签体内容、绑定事件......)。举例:v-bind:href="xxx" 或者简写为 :href="xxx" xxx同样要写js表达式,且可以直接读取到data中的所有属性。备注:Vue中有很多指令,且形式都是:v-xxx,此处我们只是拿v-bind举例子。--><!-- 准备好一个容器 --><div id="root"><h1>插值语法</h1><h3>你好,{{name}}</h3><hr><h1>指令语法</h1><a v-bind:href="school.url">点我去{{school.name}}学习</a></div>
</body><script>Vue.config.productionTip = false;   //阻止Vue在启动时生成生产提示new Vue({el:'#root',data:{name:'jack',school:{name:'尚硅谷',url:'http://www.atguigu.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>数据绑定</title><!-- 引入Vue --><script src="../js/vue.js"></script>
</head>
<body><!-- Vue中两种数据绑定的方式:1.单项数据绑定(v-bind):数据只能从data流向页面。2.双向数据绑定(v-model):数据不仅能从data流向页面,还可以从页面流向data。备注:1.双向绑定一般都应用在表单类元素上(如:input、select等);2.v-mode:value可以简写为v-model,因为v-model默认收集的就是value值。--><!-- 准备好一个容器 --><div id="root"><!-- 普通写法 -->单项数据绑定:<input type="text" v-bind:value="name"><br>双项数据绑定:<input type="text" v-model:value="name"><br><!-- 简写写法 -->单项数据绑定:<input type="text" :value="name"><br>双项数据绑定:<input type="text" v-model="name"><!-- 如下代码是错误的,因为v-model只能应用在表单类元素(输入类元素)上 --><!-- <h2 v-model:x="name">你好啊</h2> --></div>
</body>
<script>new Vue({el:"#root",data:{name:"尚硅谷"}})
</script>
</html>

1.5 el挂载器和data数据的两种写法

Vue中一个重要的原则:
由Vue管理的函数,一定不要写箭头函数,一旦写了箭头函数,this就不再是Vue实例了。

1.5.1 el挂载器的两种写法
<!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>el的两种写法</title><!-- 引入Vue --><script src="../js/vue.js"></script>
</head>
<body><!-- el挂载器的两种写法:1.new Vue时候配置el属性。2.先创建Vue实例,随后通过v.$mount(‘#root’)指定el的值。--><!-- 准备好一个容器 --><div id="root"><h1>你好,{{name}}</h1></div>
</body>
<script>var v = new Vue({// 容器挂载第一种写法// el:'#root',data:{name:'尚硅谷'}})// 输出Vue实例console.log(v); // 1秒后执行setTimeout(()=>{// 容器挂载第二种写法v.$mount('#root');},1000)
</script>
</html>
1.5.2 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>data的两种写法</title><!-- 引入Vue --><script src="../js/vue.js"></script>
</head>
<body><!-- data数据对象的两种写法:1.对象式2.函数式如何选择:目前哪一种写法都可以,以后学习到组件时,data必须使用函数式,否则会报错。--><!-- 准备好一个容器 --><div id="root"><h1>你好,{{name}}</h1></div>
</body>
<script>var v = new Vue({el:'#root',// data的第一种写法:对象式/* data:{*    name:'尚硅谷'* }*/// data的第一种写法:函数式data:function(){console.log('@@@',this) //此处的this是Vue实例对象return {name:'尚硅谷'}}})
</script>
</html>

1.6 MVVM模型

<!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>MVVM模型</title><script src="../js/vue.js"></script>
</head>
<body><!-- MVVM模型:M:模型(Model):对应data中的数据;V:视图(View):模板;VM:视图模型(ViewModel):Vue实例对象;--><!-- 准备好一个容器 --><div id="root"><h1>学校名称:{{name}}</h1><h1>学校地址:{{address}}</h1></div>
</body>
<script>new Vue({el:'#root',data:{name:'尚硅谷',address:'北京'}})
</script>
</html>

1.7 回顾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>回顾Object.defineproperty方法</title>
</head>
<body><script>let person = {name:'张三',sex:'男'}Object.defineProperty(person,'age',{value:18,enumerable:true, //控制属性是否可以枚举,默认值是falsewritable:true,   //控制属性是否可以修改,默认值是falseconfigurable:true   //控制属性是否可以被删除,默认值是false})console.log(Object.keys(person));</script>
</body>
</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>回顾Object.defineproperty方法</title>
</head>
<body><script>let number = 18;let person = {name:'张三',sex:'男',}Object.defineProperty(person,'age',{// value:18,// enumerable:true, //控制属性是否可以枚举,默认值是false// writable:true,   //控制属性是否可以修改,默认值是false// configurable:true,   //控制属性是否可以被删除,默认值是false// 当有人读取person的age属性时,get函数就会被调用,且返回值就是age的值get:function(){console.log('有人读取了age属性了')return number;},// 当有人修改person的age属性时,set函数就会被调用,且会收到修改的值set(value){console.log('有人修改了age属性,且值是30');number = value;}})// console.log(Object.keys(person));console.log(person);</script>
</body>
</html>

1.8 Vue中的数据代理

1.8.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>何为数据代理</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>
1.8.2 Vue中的数据代理

网页中vm中的_data 和 代码中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>Vue中的数据代理</title><script src="../js/vue.js"></script>
</head>
<body><!-- Vue中的数据代理:通过vm对象来代理data对象中属性的操作(读/写)Vue中数据代理的好处:更加方便的操作data中的数据。基本原理:通过Object.defineProperty()把data对象中所有属性添加到vm上。为每一个添加到vm上的属性,都指定一个getter/setter。在getter/setter内部去操作(读/写)data中对应的属性。--><!-- 准备好一个容器 --><div id="root"><h2>学校名称:{{name}}</h2><h2>学校地址:{{address}}</h2></div>
</body>
<script>let data = {name:'尚硅谷',address:'宏福科技园'}const vm = new Vue({el:'#root',data// data:{//     name:'尚硅谷',//     address:'宏福科技园'// }})
</script>
</html>

数据代理图示:

1.9 事件处理

1.9.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>事件的基本使用</title><!-- 引入Vue --><script src="../js/vue.js"></script>
</head>
<body><!-- 1.使用v-on:xxx或者@xxx绑定事件,其中xxx是事件名;2.事件的回调需要配置在methods对象中,最终会在vm上;3.methods中配置的函数,不要用箭头函数!否则this就不是vm实例化对象了;4.methods中配置的函数,都是被Vue所管理的函数,this的指向是vm或组件实例对象;5.@click=”demo” 和 @click=”demo($event)” 效果一致,但是后者可以传参数。--><!-- 准备好一个容器 --><div id="root"><h2>欢迎来到{{name}}学习</h2><!-- 普通写法 --><button v-on:click="showInfo1">点我提示信息1(不传参)</button><!-- 简写写法 传参数方法 event事件 --><button @click="showInfo2(66,$event)">点我提示信息2(传参数)</button></div>
</body>
<script>const vm = new Vue({el:'#root',data:{name:'尚硅谷'},methods:{showInfo1(event){console.log(this);  //此处的this是vm实例化对象console.log(event.target.innerText);alert('同学你好!');},showInfo2(number,event){console.log(event);alert('同学你好!!'+number);},}})
</script>
</html>
1.9.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>事件修饰符</title><!-- 引入Vue --><script src="../js/vue.js"></script><style>*{margin-top: 20px;}.demo1{height: 50px;background-color: skyblue;}.box1{padding: 5px;background-color: skyblue;}.box2{padding: 5px;background-color: pink;}.list{width: 200px;height: 200px;background-color: peru;overflow: auto;}li{height: 100px;}</style>
</head>
<body><!-- Vue中的事件修饰符:1.prevent:阻止默认事件(常用);2.stop:阻止事件冒泡(常用);3.once:事件只触发一次(常用);4.capture:使用事件的捕获模式;5.self:只有event.target是当前操作的元素时才触发事件;6.passive:事件的默认行为立即执行,无需等待事件回调执行完毕;--><!-- 准备好一个容器 --><div id="root"><h2>欢迎来到{{name}}学习</h2><!-- @click.prevent对事件修饰,阻止默认事件发生 --><a href="http://www.atguigu.com" @click.prevent="showInfo">点我提示信息</a><!-- 阻止事件冒泡 --><div class="demo1" @click="showInfo"><!-- <button @click.stop="showInfo">点我提示信息</button> --><!-- 事件修饰符可以连着写 --><a href="http://www.atguigu.com" @click.stop.prevent="showInfo">点我提示信息</a></div><!-- 事件只触发一次 --><button @click.once="showInfo">点我提示信息</button><!-- 使用事件捕获模式 --><div class="box1" @click.capture="showMessage(1)">div1<div class="box2" @click="showMessage(2)">div2</div></div><!-- 只有event.target是当前操作的元素时才触发事件 --><div class="demo1" @click.self="showInfo"><button @click="showInfo">点我提示信息</button></div><!-- 事件的默认行为立即执行,无需等待事件的回调执行完毕 --><!-- wheel:鼠标滚轮滚动事件;scroll:滚动条滚动事件; --><ul class="list" @wheel.passive="demo"><li>1</li><li>2</li><li>3</li><li>4</li></ul></div>
</body>
<script>new Vue({el:'#root',data:{name:'尚硅谷'},methods:{showInfo(e){alert('同学你好!');// e.preventDefault();  //阻止默认事件// e.stopPropagation();    //阻止事件冒泡console.log(e.target);},showMessage(msg){console.log(msg);},demo(){for (let i = 0; i < 100000; i++) {console.log('@');   //滚动输出@}console.log('累坏了');}}})
</script>
</html>
1.9.3 键盘事件

键盘事件

  • keydown:按下按键不用抬起来就可以触发事件;
  • keyup:按下按键抬起来才会触发事件;

Vue中常用的按键别名:

  • 回车:enter
  • 删除:delete
  • 退出:esc
  • 空格:space
  • 换行:tab (必须配合keydown使用)
  • 上:up
  • 下:down
  • 左:left
  • 右:right

Vue未提供别名的按键,可以使用按键原始key值去绑定,但注意要转为kebab-case(短横线命名)

系统修饰键(用法特殊):ctrl、alt、shift、meta(win键)

  • 配合和keyup使用:按下修饰键的同时,再按下其他键,随后释放其他键,事件才被触发;
  • 配合keydown使用,正常触发事件。

也可以使用keyCode去指定具体的按键(不推荐)。

Vue.config.keyCode.自定义键名 = 键码 ,可以去定制按键别名。

<!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>键盘事件</title><!-- 引入Vue --><script src="../js/vue.js"></script>
</head>
<body><!-- 准备好一个容器 --><div id="root"><h2>欢迎来到{{name}}学习</h2><!-- 键盘事件:keydown:按下按键不用抬起来就可以触发事件;keyup:按下按键抬起来才会触发事件; -->Enter键:<input type="text" placeholder="按下回车提示输入" @keyup.enter="showInfo"><hr>当按下Ctrl+Y键:<input type="text" placeholder="按下Ctrl+Y键提示输入" @keyup.ctrl.y="showInfo"><hr><!-- CapsLock转换为caps-lock -->CapsLock键:<input type="text" placeholder="按下CapsLock键提示输入" @keyup.caps-lock="showInfo"><hr><!-- 自定义键名称 -->Enter键:<input type="text" placeholder="按下huiche键提示输入" @keyup.huiche="showInfo"></div>
</body>
<script>Vue.config.keyCodes.huiche = 13;    //自定义键名称new Vue({el:'#root',data:{name:'尚硅谷',},methods:{showInfo(e){console.log(e.key);console.log(e.keyCode);// // 13为enter回车键// if(e.keyCode != 13) return;console.log(e.target.value);}}})
</script>
</html>

1.10 计算属性——computed

1.10.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>姓名案例_差值语法实现</title><!-- 引入Vue --><script src="../js/vue.js"></script>
</head>
<body><div id="root">姓:<input type="text" v-model="firstName"><br>名:<input type="text" v-model="lastName"><br>全名:<span>{{firstName.slice(0,3)}}-{{lastName}}</span></div>
</body>
<script>new Vue({el:'#root',data:{firstName:'张',lastName:'三'},})
</script>
</html>
1.10.2 姓名案例——methods方法实现
<!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>姓名案例_methods实现</title><!-- 引入Vue --><script src="../js/vue.js"></script>
</head>
<body><div id="root">姓:<input type="text" v-model="firstName"><br>名:<input type="text" v-model="lastName"><br>全名:<span>{{fullName()}}</span></div>
</body>
<script>new Vue({el:'#root',data:{firstName:'张',lastName:'三'},methods:{fullName(){return this.firstName+'-'+this.lastName;}}})
</script>
</html>
1.10.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>姓名案例_计算属性实现</title><!-- 引入Vue --><script src="../js/vue.js"></script>
</head>
<body><!-- 计算属性:1.定义:要用的属性不存在,要通过已有属性计算得来。2.原理:底层借助了Object.defineProperty方法提供的getter和setter。3.get函数什么时候执行?(1)初次读取时会执行一次;(2)当依赖的数据发生变化时会被再次调用;4.优势:与methods实现相比较,内部有缓存机制(复用),效率更高,调试更方便。5.备注:(1)计算属性最终会出现在vm上,直接读取使用即可。(2)如果计算属性要被修改,那必须写set函数去响应修改,且set中要引起计算时依赖的数据发生。--><div id="root">姓:<input type="text" v-model="firstName"><br>名:<input type="text" v-model="lastName"><br>全名:<span>{{fullName}}</span></div>
</body>
<script>const vm = new Vue({el:'#root',data:{firstName:'张',lastName:'三'},computed:{fullName:{// get有什么作用?当有人读取fullName时,get就会被调用,且返回值就作为fullName的值。// get什么时候调用?1.初次读取fullName时,get会被调用。2.所依赖的数据发生变化时,get会被调用。get(){console.log('get就被调用了。');return this.firstName + '-' + this.lastName;},// set()什么时候调用?当fullName被修改时,set就会被调用、set(value){console.log('set被调用了');const arr = value.split('-');this.firstName = arr[0];this.lastName = arr[1];}}}})
</script>
</html>
1.10.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>姓名案例_计算属性简写</title><!-- 引入Vue --><script src="../js/vue.js"></script>
</head>
<body><div id="root">姓:<input type="text" v-model="firstName"><br>名:<input type="text" v-model="lastName"><br>全名:<span>{{fullName}}</span></div>
</body>
<script>const vm = new Vue({el:'#root',data:{firstName:'张',lastName:'三'},computed:{/*          完整写法fullName:{get(){console.log('get就被调用了。');return this.firstName + '-' + this.lastName;},set(value){console.log('set被调用了');const arr = value.split('-');this.firstName = arr[0];this.lastName = arr[1];}} */// 简写写法:只考虑读取不考虑修改的时候用简写方式fullName(){console.log('get被调用了');return this.firstName + '-' + this.lastName;}}})
</script>
</html>

1.11 监视属性——watch

1.11.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>天气案例</title><!-- 引入Vue --><script src="../js/vue.js"></script>
</head>
<body><!-- 准备好一个容器 --><div id="root"><h2>今天天气很{{info}}</h2><button @click="changeWeather">切换天气1</button><!-- 绑定事件的时候@xxx="yyy" yyy可以写一些简单的语句 --><button @click="isHot = !isHot">切换天气2</button></div>
</body>
<script>new Vue({el:'#root',data:{isHot:true},computed:{info(){return this.isHot ? '炎热' : '凉爽';}},methods:{changeWeather(){this.isHot = !this.isHot;}},})
</script>
</html>
1.11.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>天气案例_监视属性</title><!-- 引入Vue --><script src="../js/vue.js"></script>
</head>
<body><!-- 当被监视的属性变化时,回调函数自动调用,进行相关操作;监视的属性必须存在,才能进行监视;监视的两种写法:1.new Vue时传入watch配置;2.通过vm.$watch监视;--><!-- 准备好一个容器 --><div id="root"><h2>今天天气很{{info}}</h2><button @click="changeWeather">切换天气</button></div>
</body>
<script>const vm = new Vue({el:'#root',data:{isHot:true},computed:{info(){return this.isHot ? '炎热' : '凉爽';}},methods:{changeWeather(){this.isHot = !this.isHot;}},// watch监视的第一种写法watch:{isHot:{immediate:true, // 初始化时让handler调用一下。// handler什么时候调用?当isHot发生改变时调用。handler(newValue,oldValue){console.log('isHot修改了',newValue,oldValue);}  },info:{immediate:true, // 初始化时让handler调用一下。// handler什么时候调用?当isHot发生改变时调用。handler(newValue,oldValue){console.log('info修改了',newValue,oldValue);}  }}       })// watch监视第二种写法vm.$watch('isHot',{immediate:true,handler(newValue,oldValue){console.log('isHot修改了',newValue,oldValue);}})
</script>
</html>
1.11.3 天气案例——深度监视实现——deep
<!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>天气案例_监视属性</title><!-- 引入Vue --><script src="../js/vue.js"></script>
</head>
<body><!-- 1.Vue中的watch默认不监测对象内部值的变化(一层);2.配置deep:true可以监测对象内部值改变(多层);备注:(1)Vue自身可以监测对象内部值的改变,但是Vue提供的watch默认不可以;(2)使用watch时根据数据的具体结构,决定是否采用深度监视;--><!-- 准备好一个容器 --><div id="root"><h2>今天天气很{{info}}</h2><button @click="changeWeather">切换天气</button><hr><h3>a的值是{{numbers.a}}</h3><button @click="numbers.a++">点我a+1</button><hr><h3>b的值是{{numbers.b}}</h3><button @click="numbers.b++">点我b+1</button><hr><h3>彻底改变numbers</h3><button @click="numbers = {a:11,b:22}">彻底改变numbers</button></div>
</body>
<script>const vm = new Vue({el:'#root',data:{isHot:true,numbers:{a:1,b:1}},computed:{info(){return this.isHot ? '炎热' : '凉爽';}},methods:{changeWeather(){this.isHot = !this.isHot;},},watch:{isHot:{// immediate:true, handler(newValue,oldValue){console.log('isHot修改了',newValue,oldValue);}  },// 监视多级结构中某个属性的变化'numbers.a':{handler(){console.log('a变了');}},// 监视多级结构中所有属性的变化numbers:{deep:true,handler(){console.log('numbers彻底被改变了');}}}       })
</script>
</html>
1.11.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>天气案例_监视属性_简写形式</title><!-- 引入Vue --><script src="../js/vue.js"></script>
</head>
<body><!-- 准备好一个容器 --><div id="root"><h2>今天天气很{{info}}</h2><button @click="changeWeather">切换天气</button></div>
</body>
<script>const vm = new Vue({el:'#root',data:{isHot:true,numbers:{a:1,b:1}},computed:{info(){return this.isHot ? '炎热' : '凉爽';}},methods:{changeWeather(){this.isHot = !this.isHot;},},watch:{// 正常写法/* isHot:{immediate:true, //初始化时让hanlder调用一下deep:true,  //深度监视handler(newValue,oldValue){console.log('isHot修改了',newValue,oldValue);}  }, */// 简写isHot(newValue,oldValue){console.log('isHot修改了',newValue,oldValue);} }       })// 正常写法/* vm.$watch('isHot',{immediate:true, //初始化时让hanlder调用一下deep:true,  //深度监视handler(newValue,oldValue){console.log('isHot修改了',newValue,oldValue);}  }) */// 简写形式/* vm.$watch('isHot',function(newValue,oldValue){console.log('isHot修改了',newValue,oldValue);}) */
</script>
</html>
1.11.5 姓名案例——监视属性实现
<!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>姓名案例_监视属性</title><!-- 引入Vue --><script src="../js/vue.js"></script>
</head>
<body><div id="root">姓:<input type="text" v-model="firstName"><br>名:<input type="text" v-model="lastName"><br>全名:<span>{{fullName}}</span></div>
</body>
<script>// 监视属性const vm = new Vue({el:'#root',data:{firstName:'张',lastName:'三',fullName:'张-三'},watch:{firstName(newValue){setTimeout(() => {this.fullName = newValue + '-' + this.lastName;    }, 1000);},lastName(newValue){this.fullName = this.firstName + '-' + newValue;}}})
</script>
</html>
1.11.6 计算属性和监视属性的对比

computed和watch之间的区别:

  • computed能完成的功能,watch都能完成;
  • watch能完成的功能,computed不一定能完成,例如:watch可以进行异步操作;

两个重要的小原则:

  • 所被Vue管理的函数,最好写成普通函数,这样this的指向才是vm或者组件实例对象;
  • 所有不被Vue所管理的函数(定时器的回调函数、ajax的回调函数等),最好写成箭头函数,这样this的指向才是vm或者组件实例对象;

1.12 class与style绑定

1.12.1 class绑定

写法:class=”xxx” xxx可以是字符串、对象、数组。
字符串写法适用于:类名不确定,要动态获取。
对象写法适用于:要绑定多个样式,个数不确定,名字也不确定;
数组写法适用于:要绑定多个样式,个数确定,名字也确定,但是不确定用还是不用;

<!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>绑定样式</title><!-- 引入VUE --><script src="../js/vue.js"></script><style>.basic{width: 400px;height: 100px;border:1px solid black;}.happy{background-color: red;}.sad{background-color: green;}.normal{background-color: pink;}.mod1{font-family: '宋体';font-size: 25px;}.mod2{color: red;}.mod3{background-color: pink;}</style>
</head>
<body><!-- 准备好一个容器 --><div id="root"><!-- 绑定class样式——字符串写法,适用于:样式的类名不确定,需要动态指定 --><div id="mode" class="basic" :class="mood" @click="changeMood">{{name}}</div><hr><!-- 绑定class样式——数组写法,适用于:要绑定的样式个数不确定、名字也不确定 --><div class="basic" :class="classArr">{{name}}</div><hr><!-- 绑定class样式——对象写法,适用于:要绑定的样式个数确定、名字也确定,但是要动态决定用不用 --><div class="basic" :class="classObj">{{name}}</div></div>
</body>
<script>new Vue({el:'#root',data:{name:'尚硅谷',mood:'normal',classArr:['mod1','mod2','mod3'],classObj:{mod1:false,mod2:true}},methods:{changeMood(){// document.getElementById('mode').className = 'basic happy';const arr = ['happy','sad','normal'];const index = Math.floor(Math.random()*3);this.mood = arr[index];}}})
</script>
</html>
1.12.2 style绑定
<!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>绑定样式</title><!-- 引入VUE --><script src="../js/vue.js"></script><style>.basic{width: 400px;height: 100px;border:1px solid black;}</style>
</head>
<body><!-- 绑定style样式:style=”{fontSize:xxx}”,其中xxx是动态值;:style=”[a,b]”,其中a,b是样式对象;--><!-- 准备好一个容器 --><div id="root"><!-- 绑定style样式 --><div class="basic" :style="styleObj">{{name}}</div><br><hr><br><!-- 绑定style样式 --><div class="basic" :style="[styleObj1,styleObj2]">{{name}}</div></div>
</body>
<script>new Vue({el:'#root',data:{name:'尚硅谷',styleObj:{fontSize:'40px',color:'red',backgroundColor:'green'},styleObj1:{fontSize:'40px',color:'red',},styleObj2:{backgroundColor:'green' }},})
</script>
</html>

1.13 条件渲染

1.13.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>条件渲染</title><!-- 引入VUE --><script src="../js/vue.js"></script>
</head>
<body><!-- v-if:写法:v-if=”表达式”v-else-if=”表达式”v-else=”表达式”                适用于:切换频率较低的场景。特点:不展示的DOM元素直接被移除。注意:v-if可以和:v-else-if、v-else一起使用,但要求结构不能够被“打断”。v-show:写法:v-show=”表达式”适用于:切换频率比较高的场景。特点:不展示的DOM元素未被移除,仅仅是使用样式隐藏掉。备注:使用v-if时,元素可能无法获取到,而使用v-show时一定是可以获取到的。--><!-- 准备好一个容器 --><div id="root"><!-- 使用v-show做条件渲染 --><h2 v-show="true">1欢迎来到{{name}}</h2><h2 v-show="a">2欢迎来到{{name}}</h2><h2 v-show="1==1">3欢迎来到{{name}}</h2><!-- 使用v-if做条件渲染 --><h2 v-if="false">4欢迎来到{{name}}</h2>    <h2 v-if="1==1">5欢迎来到{{name}}</h2>    <br><hr><h2>当前的n值是{{n}}</h2><button @click="n++">点我n++</button><hr>v-show<div v-show="n==1">1</div><div v-show="n==1">11</div><div v-show="n==3">3</div><hr>v-if<div v-if="n==1">1</div><div v-if="n==1">11</div><div v-if="n==3">3</div><hr>v-else-if<!-- 如果第一个成立,就不会往下再执行了 --><!-- 下面四个div不允许被打断,否则打断后面的就不会生效了 --><div v-if="n==1">1</div>     <div v-else-if="n==1">11</div><div v-else-if="n==3">3</div><div v-else>v-else其他</div><h2 v-show="n==1">你好</h2><h2 v-show="n==1">尚硅谷</h2><h2 v-show="n==1">北京</h2><!-- template不影响结构,template只能配合v-if使用 --><template v-if="n==1"> <h2>你好</h2><h2>尚硅谷</h2><h2>北京</h2>         </template></div>
</body>
<script>new Vue({el:'#root',data:{name:'尚硅谷',a:true,n:1}})
</script>
</html>

1.14 列表渲染

1.14.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>1.基本列表</title><script src="../js/vue.js"></script>
</head>
<body><!-- v-for指令:用于展示列表数据语法:v-for=”(item,index) in xxx” :key=”yyy”可以遍历:数组、对象、字符串(用的很少)、指定次数(用的很少)--><div id="root"><!-- 遍历数组 --><h2>遍历数组:人员列表</h2><ul><li v-for="p in persons" :key="p.id">{{p.name}}-{{p.age}}-{{p.id}}</li></ul><hr><!-- 遍历对象 --><h2>遍历对象:汽车信息</h2><ul><li v-for="(value,key) of car">{{key}}--{{value}}</li></ul><hr><!-- 遍历字符串 --><h2>遍历字符串</h2><ul><li v-for="(char,index) of str" :key="index">{{char}}-{{index}}</li></ul><hr><!-- 遍历指定次数 --><h2>遍历指定次数</h2><ul><li v-for="(num,index) of 5">{{num}}-{{index}}</li></ul></div>
</body><script>new Vue({el:'#root',data:{persons:[{id:'001',name:'张三',age:18},{id:'002',name:'李四',age:19},{id:'003',name:'王五',age:20},],car:{name:'奥迪A8',price:'70w',color:'黑色'},str:'HELLO'}})</script>
</html>
1.14.2 key的原理
  • 面试题:react、vue中的key有什么作用?(key的内部原理)
  • 虚拟DOM中key的作用:

key是虚拟DOM对象的标识,当状态中的数据发生变化时,vue会根据新数据生成新的虚拟DOM,随后vue进行新虚拟DOM与旧虚拟DOM的差异比较,比较规则如下。

对比规则: 旧虚拟DOM中找到了与新虚拟DOM相同的key: 若虚拟DOM中内容没变,直接使用之前的真实DOM;
若虚拟DOM中内容变了,则生成新的真实DOM,随后替换掉页面中之前的真实DOM。 旧虚拟DOM中未找到与新虚拟DOM相同的key:
创建新的真实DOM,随后渲染到页面上。

  • 用index作为key可能会引发的问题:

若对数据进行:逆序添加、逆序删除等破坏顺序的操作: 会产生没有必要的真实DOM更新→界面效果没有问题,但是效率低。
如果结构中还包含输入类DOM: 会产生错误DOM更新→界面有问题。

  • 开发中如何去选择key?

最好使用每条数据的唯一标识作为key,比如id、手机号、身份证号、学号等唯一值。
如果不存在对数据的逆序添加、逆序删除等破坏顺序的操作,仅用于渲染列表用于展示,使用index作为key是没有问题的。


<!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>2.key的原理</title><script src="../js/vue.js"></script>
</head>
<body><div id="root"><!-- 遍历数组 --><h2>遍历数组:人员列表</h2><!-- 点击按钮后,输入框内容会出现问题 --><button @click.once="add">添加一个老刘</button><ul><li v-for="(p,index) in persons" :key="index">{{p.name}}-{{p.age}}-{{index}}<input type="text"></li></ul><hr><h2>遍历数组:人员列表</h2><!-- 点击按钮后,输入框内容不会出现不匹配 --><button @click.once="add">添加一个老刘</button><ul><li v-for="p in persons" :key="p.id">{{p.name}}-{{p.age}}-{{p.id}}<input type="text"></li></ul><hr></div>
</body><script>new Vue({el:'#root',data:{persons:[{id:'001',name:'张三',age:18},{id:'002',name:'李四',age:19},{id:'003',name:'王五',age:20},],},methods:{add(){const p = {id:'004',name:'老刘',age:40};this.persons.unshift(p);    //unshift()方法将新项添加到数组的开头,并返回新的长度。}}})</script>
</html>
1.14.3 列表过滤

当watch属性和computed属性都可以实现的时候,最好是使用过computed属性,用起来比较方便一些。

1.14.3.1 watch属性实现列表过滤
<!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>3.列表过滤_watch写法</title><script src="../js/vue.js"></script>
</head>
<body><div id="root"><!-- 遍历数组 --><h2>遍历数组:人员列表</h2><input type="text" placeholder="请输入名字" v-model="keyWord"><ul><li v-for="p in filterPersons" :key="p.id">{{p.name}}-{{p.age}}-{{p.sex}}-{{p.id}}</li></ul><hr></div>
</body><script>// 用watch实现new Vue({el:'#root',data:{keyWord:'',persons:[{id:'001',name:'马冬梅',age:18,sex:'女'},{id:'002',name:'周冬雨',age:19,sex:'女'},{id:'003',name:'周杰伦',age:20,sex:'男'},{id:'004',name:'温兆伦',age:21,sex:'男'},],filterPersons:[]},watch:{/* // 简写监视出现bugkeyWord(val){console.log('keyWord被改变为:'+val);   //使用监听事件拿到变化的数据// 使用filter生成新的数组替换掉原来的persons就可以实现页面效果,但是更改了原来的数据有bugthis.filterPersons = this.persons.filter((p)=>{// indexOf方法是判断字符串中存在第几位,如果返回-1则表示不存在// indexOf一个空字符串是0return p.name.indexOf(val) != -1;})} */// 这种情况不要写成简写形式的监视keyWord:{immediate:true,handler(val){this.filterPersons = this.persons.filter((p)=>{return p.name.indexOf(val) != -1;})}}}})</script>
</html>
1.14.3.2 computed属性实现列表过滤
<!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>4.列表过滤_computed写法</title><script src="../js/vue.js"></script>
</head>
<body><div id="root"><!-- 遍历数组 --><h2>遍历数组:人员列表</h2><input type="text" placeholder="请输入名字" v-model="keyWord"><ul><li v-for="p in filterPersons" :key="p.id">{{p.name}}-{{p.age}}-{{p.sex}}-{{p.id}}</li></ul><hr></div>
</body><script>// 用computed实现new Vue({el:'#root',data:{keyWord:'',persons:[{id:'001',name:'马冬梅',age:18,sex:'女'},{id:'002',name:'周冬雨',age:19,sex:'女'},{id:'003',name:'周杰伦',age:20,sex:'男'},{id:'004',name:'温兆伦',age:21,sex:'男'},],},computed:{filterPersons(){return this.persons.filter((p)=>{return p.name.indexOf(this.keyWord) != -1;})}}})</script>
</html>
1.14.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>5.列表排序</title><script src="../js/vue.js"></script>
</head>
<body><div id="root"><!-- 遍历数组 --><h2>遍历数组:人员列表</h2><input type="text" placeholder="请输入名字" v-model="keyWord"><button @click="sortType=2">年龄升序</button><button @click="sortType=1">年龄降序</button><button @click="sortType=0">原顺序</button><ul><li v-for="p in filterPersons" :key="p.id">{{p.name}}-{{p.age}}-{{p.sex}}-{{p.id}}</li></ul><hr></div>
</body><script>// 用computed实现new Vue({el:'#root',data:{keyWord:'',sortType:'0',   //排序类型:0:原顺序,1:降序,2:升序。persons:[{id:'001',name:'马冬梅',age:40,sex:'女'},{id:'002',name:'周冬雨',age:30,sex:'女'},{id:'003',name:'周杰伦',age:10,sex:'男'},{id:'004',name:'温兆伦',age:20,sex:'男'},],},computed:{filterPersons(){const arr = this.persons.filter((p)=>{return p.name.indexOf(this.keyWord) != -1;})// 判断下是否需要排序if(this.sortType != 0){arr.sort((p1,p2)=>{return this.sortType == 1 ? p2.age-p1.age : p1.age-p2.age; })}return arr;}}})</script>
</html>
1.14.5 更新时的一个问题
<!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>6.更新时的一个问题</title><script src="../js/vue.js"></script>
</head>
<body><div id="root"><!-- 遍历数组 --><h2>遍历数组:人员列表</h2><button @click="updateMa">更新马冬梅信息</button><ul><li v-for="p in persons" :key="p.id">{{p.name}}-{{p.age}}-{{p.sex}}-{{p.id}}</li></ul><hr></div>
</body><script>// 用computed实现const vm = new Vue({el:'#root',data:{persons:[{id:'001',name:'马冬梅',age:40,sex:'女'},{id:'002',name:'周冬雨',age:30,sex:'女'},{id:'003',name:'周杰伦',age:10,sex:'男'},{id:'004',name:'温兆伦',age:20,sex:'男'},],},methods: {updateMa(){// 以下代码生效// this.persons[0].name = '马老师',// this.persons[0].age = 50,// this.persons[0].sex = '男'// 以下代码未生效// this.persons[0] = {id:'001',name:'马老师',age:50,sex:'男'}// 以下代码奏效this.persons.splice(0,1,{id:'001',name:'马老师',age:50,sex:'男'});}},})</script>
</html>
1.14.6 Vue检测数据改变的一个原理——对象
1.14.7 Vue.set()方法的使用
<!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>8.Vue.set的使用</title><script src="../js/vue.js"></script>
</head>
<body><div id="root"><h2>学校名称:{{name}}</h2><h2>学校地址:{{address}}</h2><hr><h1>学生信息</h1><button @click="addSex">添加一个性别属性</button><h2>学生姓名:{{student.name}}</h2><h2 v-if="student.sex">学生性别:{{student.sex}}</h2><h2>学生年龄:真实:{{student.age.rAge}},对外:{{student.age.sAge}}</h2><h2>朋友们</h2><ul><li v-for="f in student.friends" :key="index">{{f.name}}---{{f.age}}</li></ul></div>
</body><script>const vm = new Vue({el:'#root',data:{name:'尚硅谷',address:'北京',student:{name:'tom',age:{rAge:40,sAge:29,},friends:[{name:'jerry',age:35},{name:'tony',age:36}]}},methods: {addSex(){// 两种方法都可以实现// Vue.set(this.student,'sex','男')this.$set(this.student,'sex','男') }},})</script>
</html>
1.14.8 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>9.Vue监测数据改变的原理_数组</title><script src="../js/vue.js"></script>
</head>
<body><div id="root"><h2>学校名称:{{name}}</h2><h2>学校地址:{{address}}</h2><hr><h1>学生信息</h1><button @click="addSex">添加一个性别属性</button><h2>学生姓名:{{student.name}}</h2><h2 v-if="student.sex">学生性别:{{student.sex}}</h2><h2>学生年龄:真实:{{student.age.rAge}},对外:{{student.age.sAge}}</h2><h2>爱好:</h2><ul><li v-for="(h,index) in student.hobby">{{h}}</li></ul><h2>朋友们</h2><ul><li v-for="f in student.friends" :key="index">{{f.name}}---{{f.age}}</li></ul></div>
</body><script>const vm = new Vue({el:'#root',data:{name:'尚硅谷',address:'北京',student:{name:'tom',age:{rAge:40,sAge:29,},hobby:['抽烟','喝酒','烫头'],friends:[{name:'jerry',age:35},{name:'tony',age:36}]}},methods: {addSex(){// 两种方法都可以实现// Vue.set(this.student,'sex','男')this.$set(this.student,'sex','男') }},})</script>
</html>
1.14.9 Vue数据监测总结
  • Vue会监视data中所有层次的数据.
  • 如何监测对象中的数据?
如何监测对象中的数据?通过setter实现监视,且要在new Vue时就传入要监测的数据。(1)对象中后追加的属性,vue默认不做响应式处理。(2)如需要给后添加的属性做响应式,请使用如下的API:Vue.set(target,propertyName/index,value)vm.$set(target,propertyName/index,value)
  • 如何监测数组中的数据?
如何监测数组中的数据?通过包裹数组更新元素的方法实现,本质就是做了两件事:(1)调用原生对应的方法对数组进行更新。(2)重新解析模板,进而更新页面。
  • 在Vue修改数组中的某个元素一定要用如下方法:
在Vue修改数组中的某个元素一定要用如下方法:(1)使用这些API:push()、pop()、shift()、unshift()、splice()、sort()、reverse()(2)Vue.set() 或 vm.$set()特别注意:Vue.set() 和 vm.$set() 不能给vm的根数局对象添加属性。
<!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>10.总结Vue数据监测</title><script src="../js/vue.js"></script>
</head>
<body><div id="root"><h1>学生信息</h1><button @click="student.age++">年龄+1</button><br><button @click="addSex">添加性别属性,默认值:男</button><br><button @click=" student.sex='未知' ">修改性别</button><br><button @click="addFriends">在列表首页添加一位朋友</button><br><button @click="updateFristFriendName">修改第一个朋友的名字为:张三</button><br><button @click="addHobby">添加一个爱好</button><br><button @click="updateFristHobby">修改第一个爱好为:开车</button><br><h3>姓名:{{student.name}}</h3><h3>年龄:{{student.age}}</h3><h3 v-if="student.sex">性别:{{student.sex}}</h3><h3>爱好:</h3><ul><li v-for="(h,index) in student.hobby" ::key="index">{{h}}</li></ul><h3>朋友们:</h3><ul><li v-for="(f,index) in student.friends" ::key="index">{{f.name}}---{{f.age}}</li></ul></div>
</body>
<script>new Vue({el:'#root',data:{student:{name:'tom',age:18,hobby:['抽烟','喝酒','烫头'],friends:[{name:'jerry',age:35},{name:'tony',age:36}]}},methods: {addSex(){// Vue.set(this.student,'sex','男')this.$set(this.student,'sex','男')},addFriends(){this.student.friends.unshift({name:'jack',age:'70'})},updateFristFriendName(){this.student.friends[0].name = '张三'},addHobby(){this.student.hobby.push('学习')},updateFristHobby(){// this.student.hobby.splice(0,1,'开车')// Vue.set(this.student.hobby,0,'开车')this.$set(this.student.hobby,0,'开车')}},})
</script>
</html>

1.15 收集表单数据

收集表单数据:(1)若:<input type="text"/> ,则v-model收集的是value值,用户输入的就是value值。(2)若:<input type="radio"/>,则v-model收集的是value值,且要给标签配置value值。(3)若:<input type="checkbox"/>1)没有配置input的value属性,那么收集的就是checked(勾选or未勾选,值是布尔值)2)配置input的value属性:[1]v-model的初始值是非数组,那么收集的就是checked(勾选or未勾选,值是布尔值)[2]v-model的初始值是数组,那么收集的就是value组成的数组。v-model的三个修饰符:(1)lazy:失去焦点再收集数据;(2)number:输入字符串转为有效的数字;(3)trim:输入首尾空格过滤;
<!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>收集表单数据</title><script src="../js/vue.js"></script>
</head>
<body><!-- 收集表单数据:若:<input type="text"/> ,则v-model收集的是value值,用户输入的就是value值。若:<input type="radio"/>,则v-model收集的是value值,且要给标签配置value值。若:<input type="checkbox"/>1.没有配置input的value属性,那么收集的就是checked(勾选or未勾选,值是布尔值)2.配置input的value属性:(1) v-model的初始值是非数组,那么收集的就是checked(勾选or未勾选,值是布尔值)(2) v-model的初始值是数组,那么收集的就是value组成的数组。备注:v-model的三个修饰符:lazy:失去焦点再收集数据;number:输入字符串转为有效的数字;trim:输入首尾空格过滤; --><div id="root"><form @submit.prevent="demo"><!-- 这样写点击账号标签也能将光标聚集到输入框 --><label for="demo1">账号:</label><input type="text" id="demo1" v-model.trim="userInfo.account"><br><label for="demo2">密码:</label><input type="password" id="demo2" v-model="userInfo.password"><br>性别: <br>男<input type="radio" value="male" v-model="userInfo.sex">女<input type="radio" value="female" v-model="userInfo.sex"><br>年龄:<input type="number" v-model.number="userInfo.age">爱好:<br>抽烟<input type="checkbox" value="抽烟" v-model="userInfo.hobby">喝酒<input type="checkbox" value="喝酒" v-model="userInfo.hobby">烫头<input type="checkbox" value="烫头" v-model="userInfo.hobby"><br>所属校区: <select name="" id="" v-model="userInfo.city"><option value="">请选择校区</option><option value="beijing" >北京</option><option value="shanghai">上海</option><option value="shenzhen">深圳</option><option value="wuhan">武汉</option></select><br>其他信息:<!-- 失去焦点的瞬间收集信息 --><textarea v-model.lazy="userInfo.other"></textarea><br><input type="checkbox" v-model="userInfo.isAgree"> 阅读并接受<a href="http://www.atguigu.com">用户协议</a><button>提交</button></form></div>
</body>
<script>new Vue({el:'#root',data:{userInfo:{account:'',password:'',sex:'female',age:'',hobby:[],city:'',other:'',isAgree:''}},methods: {demo(){console.log(JSON.stringify(this._data));}},})
</script>
</html>

1.16 过滤器

<!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>过滤器</title><script src="../js/vue.js"></script><script src="../js/dayjs.min.js"></script>
</head>
<body><!-- dayjs().startOf('month').add(1, 'day').set('year', 2018).format('YYYY-MM-DD HH:mm:ss') --><!-- 过滤器:定义:对要显示的数据进行特定格式化后再显示(适用于一些简单逻辑的处理)。语法:1.注册过滤器:Vue.filter(name,callback) 或 new Vue(filters:{})2.使用过滤器:{{xxx | 过滤器名}} 或 v-bind:属性 = "xxx | 过滤器名"备注:1.过滤器也可以接受额外参数、多个过滤器也可以串联。2.并没有改变原本的数据,是产生新的对应的数据。--><div id="root"><h2>显示格式化后的时间</h2><h3>computed</h3><br><h3>现在时间:{{timeFormatComputed}}</h3><hr><h3>methods</h3><h3>现在时间:{{timeFormatMethods()}}</h3><hr><h3>filters</h3><h3>现在时间:{{time | timeFormatFilters}}</h3><hr><h3>filters(传参)</h3><h3>现在时间:{{time | timeFormatFilters('YYYY-MM-DD')}}</h3><hr><h3>现在时间:{{time | timeFormatFilters}}</h3><hr><h3>filters(传参)串联</h3><h3>现在时间:{{time | timeFormatFilters('YYYY-MM-DD') | mySlice}}</h3><hr></div><div id="root2"><h3>{{str | mySlice}}</h3><hr><h3 :x="str | mySlice">看属性,过滤器不只是适用于插值</h3></div>
</body>
<script>Vue.filter('mySlice',function(value){return value.slice(0,4); })new Vue({el:'#root',data:{time:1621561377603    //时间戳,Date.now()获取到,注意time不能赋值成字符串,不然时间不对。},computed:{timeFormatComputed(){return dayjs(this.time).format('YYYY-MM-DD HH:mm:ss');}},methods: {timeFormatMethods(){return dayjs(this.time).format('YYYY-MM-DD HH:mm:ss');}},// 局部过滤器filters:{timeFormatFilters(value,str='YYYY-MM-DD HH:mm:ss'){return dayjs(value).format(str);},// mySlice(value){//     return value.slice(0,4);// }}})new Vue({el:'#root2',data:{str:'Hello! nihao!'}})
</script>
</html>

1.17 Vue内置指令

1.17.1 v-text指令
<!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>v-text指令</title><script src="../js/vue.min.js"></script>
</head>
<body><!-- 学过的指令:v-bind:单向绑定解析表达式,可简写为:xxxv-model:双向数据绑定v-for:遍历数组、对象、字符串v-on:绑定事件监听,可简写为@v-if:条件渲染(动态控制节点是否存在)v-else:条件渲染(动态控制节点是否存在)v-show:条件渲染(动态控制节点是否展示)--><!-- v-text指令:1.作用:向其所在的节点中渲染文本内容。2.与插值语法的区别:v-text会替换掉节点中的内容,{{xxx}}插值语法则不会替换掉。--><div id="root"><div>{{name}}</div><div v-text="name">这段内容不显示,显示的是name</div><div v-text="str"></div></div>
</body>
<script>new Vue({el:'#root',data:{name:'尚硅谷',str:'<h3>你好</h3>'}})
</script>
</html>
1.17.2 v-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>v-html指令</title><script src="../js/vue.min.js"></script></head>
<body><!-- v-html指令:1.作用:向指定节点中渲染包含html结构的内容。2.与插值语法的区别:(1) v-html会替换掉节点中的所有内容,{{xxx}}则不会。(2) v-html可以识别html结构。3.严重注意,v-html有安全性的问题。(1) 在网站上动态渲染任意HTML是非常危险的,容易导致KSS攻击。(2) 一定要在可信的内容上使用v-html,永远不要在用户提交的内容区使用v-html。--><div id="root"><div>{{name}}</div><!-- v-html支持结构性解析与v-text不同 --><div v-html="str"></div><div v-html="str2"></div></div>
</body>
<script>new Vue({el:'#root',data:{name:'尚硅谷',str:'<h3>你好</h3>',str2:'<a href=javascript:location.href="http://www.baidu.com?"+document.cookie>兄弟我找到你想要的东西了</a>'}})
</script>
</html>
1.17.3 v-cloak指令
<!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>v-cloak指令</title><!-- 此处应该给一个延时的vue.js来测试 --><script src="../js/vue.js"></script><style>[v-cloak]{display: none;}</style>
</head>
<body><!-- v-cloak指令:1.本质是一个特殊属性,Vue实例创建完毕并接管容器后,会删除掉v-cloak属性。2.使用css配合v-cloak可以解决网速慢时页面展示出{{xxx}}的问题。--><div id="root"><h2 v-cloak>{{name}}</h2></div>
</body>
<script>new Vue({el:'#root',data:{name:'尚硅谷'}})
</script>
</html>
1.17.4 v-once指令
<!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>v-once指令</title><script src="../js/vue.min.js"></script>
</head>
<body><!-- v-once指令:1.v-once指令所在节点在初次动态渲染后,就视为静态内容了。2.以后数据的改变不会引起v-once所在结构的更新,可以用于优化性能。--><div id="root"><h2 v-once="n">初试的n值是:{{n}}</h2><h2>当前的n值是:{{n}}</h2><button @click="n++">点我n+1</button></div>
</body>
<script>new Vue({el:'#root',data:{n:1}})
</script>
</html>
1.17.5 v-pre指令
<!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>v-pre指令</title><script src="../js/vue.min.js"></script>
</head>
<body><!-- v-pre指令:1.跳过其所在节点的编译过程。2.可利用它跳过:没有使用指令语法、没有使用插值语法的节点,会加快编译。--><div id="root"><h2 v-pre>Vue其实很简单</h2><h2 v-pre>当前的n值是:{{n}}</h2><button v-pre @click="n++">点我n+1</button></div>
</body>
<script>new Vue({el:'#root',data:{n:1}})
</script>
</html>

1.18 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>自定义指令</title><script src="../js/vue.min.js"></script>
</head>
<body><!-- 需求1:定义一个v-big指令,和v-text功能类似,但是会把绑定的数值放大10倍。(函数式)需求2:定义一个v-fbind指令,和v-bind功能类似,但是可以让其所绑定的input元素默认获取焦点。(对象式)--><!-- 自定义指令总结:一、定义语法:(1)局部指令:new Vue({directive:{指令名:配置对象}})或者new Vue({directives{指令名:回调函数}})(2)全局指令:Vue.directive(指令名,配置对象)或者Vue.directive(指令名,回调函数)二、配置对象中常用的3个回调:(1)bind:指令与元素成功绑定时回调。(2)inserted:指令所在元素被插入页面时调用。(3)update:指令所在模块结构被重新解析时调用。三、备注:(1)指令定义时不加v-,但是使用的时候要加v-;(2)指令名如果是多个单词,要使用kebab-case命名方式,不要用小驼峰cameCase命名。--><div id="root"><h2>当前的n值是:<span v-text="n"></span></h2><h2>放大10倍的n值是:<span v-big="n"></span></h2><h2>放大10倍的n值是:<span v-big-number="n"></span></h2><button @click="n++">n+1</button><hr><input type="text" v-bind:value="n"><input type="text" v-fbind2:value="n"></div><div id="root2"><hr><h2>全局的自定义指令</h2><input type="text" v-fbind:value="x"><h2>全局的自定义指令——函数写法</h2><h2>放大10倍的n值是:<span v-big-all="x"></span></h2></div>
</body>
<script>// 全局的自定义指令Vue.directive('fbind',{// 指令与元素成功绑定时bind(element,binding){console.log('fbind-bind',this);console.log('bind');element.value = binding.value;},// 指令所在元素被插入页面时。inserted(element,binding){console.log('fbind-inserted',this);console.log('insert');element.focus();},// 指令所在模板被重新解析时update(element,binding){       console.log('fbind-update',this);             console.log('update');element.value = binding.value;}})Vue.directive('big-all',function(element,binding){console.log('big',this);    //指令的this都是windowconsole.log('big');element.innerText = binding.value * 10;})new Vue({el:'#root',data:{n:1},directives:{// big函数何时会被调用?// 1、指令与元素成功绑定时调用(一开始)。// 2、指令所在的模板被重新解析时。big(element,binding){console.log('big',this);    //指令的this都是windowconsole.log('big');element.innerText = binding.value * 10;},// 不建议使用驼峰命名法bingNumber,建议使用big-number,但是要加引号'big-number'(element,binding){console.log('big');element.innerText = binding.value * 10;},fbind2:{// 指令与元素成功绑定时bind(element,binding){console.log('fbind-bind',this);console.log('bind');element.value = binding.value;},// 指令所在元素被插入页面时。inserted(element,binding){console.log('fbind-inserted',this);console.log('insert');element.focus();},// 指令所在模板被重新解析时update(element,binding){       console.log('fbind-update',this);             console.log('update');element.value = binding.value;}}}})new Vue({el:'#root2',data:{x:1}})
</script>
</html>

1.19 生命周期

1.19.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>引出声明周期</title><script src="../js/vue.min.js"></script>
</head>
<body><!-- 生命周期:1.又名:生命周期回调函数、生命周期函数、生命周期钩子。2.是什么?Vue在关键时刻帮我们调用的一些特殊名称的函数。3.声明周期函数的名字不可更改,但函数的具体内容是程序员根据需求编写的。4.生命周期函数中的this指向是vm或组件实例对象。--><div id="root"><!-- :style="{opacity: opacity}"动态绑定需要写冒号,里面的数据需要写成对象的格式 --><h2 :style="{opacity: opacity}">欢迎学习Vue</h2></div>
</body>
<script>
/*     // 通过外部的定时器可以实现,但是不推荐const vm = new Vue({el:'#root',data:{opacity:1}})setInterval(()=>{vm.opacity -= 0.1;if(vm.opacity <= 0){vm.opacity = 1;}},100)*/new Vue({el:'#root',data:{opacity:1},methods: {},// Vue完成模板的解析并把初试的真实DOM元素放入页面后(挂载完毕)调用mountedmounted() {setInterval(()=>{this.opacity -= 0.1;if(this.opacity<=0){this.opacity = 1;}},100)},})</script>
</html>
1.19.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><!-- 引入Vue.js --><script src="../js/vue.min.js"></script>
</head>
<body><!-- 准备好一个容器 --><div id="root"></div>
</body>
<script>new Vue({el:'#root',data:{name:'尚硅谷'}})
</script>
</html>
1.19.3 总结声明周期

vm的生命周期:
将要创建==>调用beforeCreate函数
创建完毕==>调用Created函数
将要挂载==>调用beforeMount函数
挂载完毕==>调用Mounted函数==>重要钩子
将要更新==>调用beforeUpdate函数
更新完毕==>调用update函数
将要销毁==>调用beforeDestory函数==>重要钩子
销毁完毕==>调用Destory函数

<!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><!-- 引入Vue.js --><script src="../js/vue.min.js"></script>
</head>
<body><!-- 常用的生命周期钩子:1.mounted:发送ajax请求、启动定时器、绑定自定义事件、订阅消息等【初始化操作】2.beforeDestroy:清除定时器、解绑自定义事件、取消订阅消息等【收尾工作】关于销毁Vue实例:1.销毁后借助Vue开发者工具看不到任何消息。2.销毁后自定义事件会失效,但原生DOM事件依然有效。3.一般不会在beforeDestroy操作数据,因为即使操作数据,也不会再出发更新流程了。--><!-- 准备好一个容器 --><div id="root"><h2 :style="{opacity}">欢迎学习Vue</h2><button @click="opacity = 1">透明度设置为1</button><button @click="stop">点我停止变换</button></div>
</body>
<script>new Vue({el:'#root',data:{opacity:1},methods: {stop(){this.$destroy();}},// Vue完成模板的解析并把初试的真实DOM元素放入页面后(挂载完毕)调用mountedmounted(){console.log('mounted',this);this.timer = setInterval(() => {this.opacity -= 0.1;if (this.opacity<=0) {this.opacity = 1;}},16)},beforeDestroy() {console.log('vm即将被销毁了');// 清除定时器clearInterval(this.timer)},})</script>
</html>

2.Vue组件化编程

2.1 非单文件组件

2.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><!-- 引入Vue.js --><script src="../js/vue.min.js"></script>
</head>
<body><!-- Vue中使用组件的三大步骤:1.定义组件(创建组件)2.注册组件3.使用组件一、如何定义一个组件?使用Vue.extend(options)创建,其中options和new Vue(options)时传入的那个options几乎一样,但也有点区别。区别如下:1.el不要写。原因:最终所有的组件都要经过一个vm的管理,由vm中的el决定服务哪个容器。2.data必须要写成函数。原因:避免组件被复用时,数据存在引用关系。备注:使用template可以配置组件结构。二、如何注册组件?1.局部注册:靠new Vue的时候传入components选项。2.全局注册:靠Vue.component('组件名',组件)三、编写组件标签例如:<school></school>        --><!-- 准备好一个容器 --><div id="root"><student></student><hr><school></school>        <hr><hello></hello><hr></div><div id="root2"><hello></hello></div>
</body>
<script>// 创建学校组件const school = Vue.extend({template:`<div><h2>学校名称:{{schoolName}}</h2><h2>学校地址:{{address}}</h2><button @click="showSchoolName">点我提示学校名<button></div>`,// 一定不要写el配置项,因为最终所有的组件都要被vm管理,由vm决定服务于哪个对象// el:'#root',data(){return {schoolName:'尚硅谷',address:'北京昌平',}},methods: {showSchoolName(){alert(this.schoolName)}},})// 创建学生组件const student = Vue.extend({template:`<div><h2>学生姓名:{{studentName}}</h2><h2>学生年龄:{{age}}</h2></div>`,// 一定不要写el配置项,因为最终所有的组件都要被vm管理,由vm决定服务于哪个对象// el:'#root',data(){return {studentName:'张三',age:18}}})// 创建hello组件const hello = Vue.extend({template:`<div><h2>你好啊!{{name}}</h2>    </div>`,data(){return {name:'Tom'}}})// 注册组件(全局注册)Vue.component('hello',hello)// 注册组件new Vue({el:'#root',// 注册组件(局部注册)components:{school,student}}) new Vue({el:'#root2',})
</script>
</html>
2.1.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><!-- 引入Vue.js --><script src="../js/vue.min.js"></script>
</head>
<body><!-- 几个注意点:1.关于组件名:一个单词组成时:第一种写法(首字母小写):school第二种写法(首字母大写):School多个单词组成时:第一种写法(kebab-case命名):my-school第二种写法(CamelCase命名):MySchool(需要Vue脚手架支持)备注:(1).组件名尽可能回避HTML中已有的元素名称,例如:h2、H2都不行。(2).可以使用name配置项指定组件在开发者工具中呈现的名字。2.关于组件标签:第一种写法:<school></school>第二种写法:<school/>备注:不用使用脚手架时,<school/>会导致后序组件不能渲染。3.一个简写方式:const school = Vue.extend(options) 可简写为:const school = options--><!-- 准备好一个容器 --><div id="root"><my-school></my-school></div>
</body>
<script>const school = Vue.extend({name:'atguigu',template:`<div><h2>学校名称:{{name}}</h2><h2>学校地址:{{address}}</h2><hr></div>`,data(){return {name:'尚硅谷',address:'北京'}}})new Vue({el:'#root',data:{},components:{'my-school':school,}})
</script>
</html>
2.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><!-- 引入Vue.js --><script src="../js/vue.min.js"></script>
</head>
<body><!-- 准备好一个容器 --><div id="root"></div>
</body>
<script>// 定义一个student组件const student = Vue.extend({name:'student',template:`<div><h2>学生姓名:{{name}}</h2><h2>学生年龄:{{age}}</h2><hr></div>`,data(){return {name:'张三',age:18}}})// 定义school组件const school = Vue.extend({name:'school',template:`<div><h2>学校名称:{{name}}</h2><h2>学校地址:{{address}}</h2><student></student><hr></div>`,data(){return {name:'尚硅谷',address:'北京'}},components:{student}})// 定义一个hello组件const hello = Vue.extend({template:`<h1>{{msg}}</h1>`,data(){return {msg:'Hello'}}})// 定义app组件const app = Vue.extend({template:`<div><school></school><hello></hello></div>`,components:{school,hello}})// 创建Vuenew Vue({template:`<app></app>`,el:'#root',// 注册组件components:{app}})
</script>
</html>
2.1.4 VueComponent

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>VueComponent</title><!-- 引入vue.js --><script src="../vue.js"></script>
</head>
<body><!-- 关于VueComponent:1、school组件的本质是一个名为VueComponent的构造函数,且不是程序员定义的,是Vue。extend生成的。2、我们只需要写<school/>或者<school></school>,Vue解析时会帮我们创建school组件的实例对象,即Vue帮我们执行的:new VueComponent(options).3、特别注意:每次调用Vue.extend,返回的都是一个全新的VueComponent。4、关于this指向:(1)组件配置中data函数、methods中的函数、watch中的函数、computed中的函数,他们的this均是【VueComponent实例对象】。(2)new Vue()配置中:data函数、methods中的函数、watch中的函数、computed中的函数,他们的this均是【Vue实例对象】。5、VueComponent的实例对象,以后简称vc(也可称之为:组件实例对象)。Vue的实例对象,以后简称vm。--><!-- 准备好一个容器 --><div id="root"><school></school><hello/></div>
</body>
<script>Vue.config.productionTip = false// 定义school组件const school = Vue.extend({name:'school',template:`<div><h2>学校名称:{{name}}</h2><h2>学校地址:{{address}}</h2><button @click="showName">点我显示this是谁</button></div>`,data(){return {name:'尚硅谷',address:'北京'}},methods:{showName(){console.log('showName',this)}}})// 定义hello组件const hello = Vue.extend({template:`<h2>{{msg}}</h2>`,data(){return{msg:'你好啊!'}}})console.log('@',school);console.log('#',hello);// 创建vmnew Vue({el:'#root',components:{school,hello}})
</script>
</html>

2.2 单文件组件

School.vue文件

<template><!-- 组件的结构 --><div class="demo"><h2>学校名称:{{schoolName}}</h2><button @click="showName">点我提示学校名</button></div>
</template><script>//组件交互相关的代码(数据、方法等等)export default {name:'School',data(){return {schoolName:'尚硅谷'}},methods:{showName(){alert(this.schoolName)}}}
</script><style>/* 组件的样式 */.demo{background-color: orange}
</style>

App.vue文件

<template><div><school></school></div>
</template><script>// 引入组件import School from './School.vue'export default {name:'App',components:{School}}
</script><style></style>

main.js文件

import App from './App.vue'new Vue({el:'#root',template:`<App></App>`,component:{App},
})

index.html

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>测试一下单文件组件语法</title>
</head>
<body><div id='root'></div><script src="../vue.js"></script><script src="./main.js"></script>
</body>
</html>

3.使用Vue脚手架

4.Vue中的ajax

5.Vuex

6.Vue-router

7.Vue UI组件库

【Vue学习笔记】尚硅谷Vue2.0+Vue3.0全套教程丨vue.js从入门到精通相关推荐

  1. [Vue]学习笔记目录 【Vue2与Vue3完结】 (尚硅谷Vue2.0+Vue3.0全套教程丨vuejs从入门到精通)

    文章目录 前言 遇见的问题及其解决方案 之前笔记 Vue2 Vue3 前言 本笔记根据如下笔记和视频进行整理 老师的课件笔记,不含视频 https://www.aliyundrive.com/s/B8 ...

  2. MySQL学习笔记——尚硅谷李玉婷经典版MySQL基础笔记(一)

    MySQL学习笔记--尚硅谷李玉婷经典版MySQL基础笔记(一) MySQL学习笔记目录 MySQL学习笔记--尚硅谷李玉婷经典版MySQL基础笔记(一) 一.基础知识 1.MySQL的语法规范 2. ...

  3. maven学习笔记——尚硅谷

    文章目录 maven学习笔记--尚硅谷 第一章 Maven概述 第一节 为什么要学习Maven 1.Maven 作为依赖管理工具 1.1 jar 包的规模 1.2 jar 包的来源 1.3 jar 包 ...

  4. 尚硅谷最新版JavaScript基础全套教程完整版(p79-p90)

    尚硅谷最新版JavaScript基础全套教程完整版(140集实战教学,JS从入门到精通) 一.函数的方法 1.call()和 apply()方法 -这两个方法都是函数对象方法,需要通过函数对象来调用 ...

  5. Rabbitmq学习笔记(尚硅谷2021)

    Rabbitmq学习笔记 (尚硅谷) 1.MQ 的概念 1.1 什么是 MQ? 1.2 为什么要用 MQ? 削峰 解耦 异步 1.3 MQ 的分类 ActiveMQ Kafka RocketMQ Ra ...

  6. 【HBase学习笔记-尚硅谷-Java API shell命令 谷粒微博案例】

    HBase学习笔记 HBase 一.HBase简介 1.HBase介绍 2.HBase的逻辑结构和物理结构 3.数据模型 4.基本架构 二.快速入门 1.配置HBase 2.命令 三.API 1.获取 ...

  7. Java学习笔记 | 尚硅谷项目三详解

    该笔记基于B站视频:尚硅谷Java入门视频教程 目录 1,目标 2,需求说明 2.1,功能实现 2.1,菜单显示 2.2,添加功能 2.3,删除功能 2.3,查看团队成员 3,软件设计结构 4,具体实 ...

  8. Elasticsearch7学习笔记(尚硅谷)

    文章目录 一.ElasticSearch概述 1.ElasticSearch是什么 2.全文搜索引擎 3.ElasticSearch 和 Solr 3.1 概述 3.2 比较总结 二.Elastics ...

  9. [Vue]Vue3学习笔记(尚硅谷)

    文章目录

最新文章

  1. Unity初步 基本拼图实现
  2. python 以 utf-8 格式写文件
  3. [转载]图的割点、桥与双连通分支
  4. java课后习题_【整理】java私塾教程课后习题
  5. css中一些必要的公共样式
  6. stream of java_Java 8 新特性-Stream更优雅的处理集合入门
  7. vuex使用模块的时候 获取state里的数据语法
  8. 优秀程序员必学的开发工具教程!
  9. 蓝桥杯 ALGO-1 算法训练 区间k大数查询
  10. Oracle 客户端连接server 的方法
  11. java alert 乱码_在servlet中输出JS中文乱码,servlet中alert对话框出现中文乱码的解决方法...
  12. 【贪心】【堆】Gym - 101485A - Assigning Workstations
  13. 实验2 黑盒测试方法:等价类划分法+边界值分析方法
  14. 【前端react 粒子特效】
  15. dac生成信号频率取决于_关于高速AD/DAC测量及设计中82个疑难问题的解答
  16. 职业选择与职业规划【转载】
  17. pyspark steaming常规语句及操作
  18. 逻辑综合重点解析55题(Design Compiler篇)
  19. 图像处理之Matlab图像读取
  20. hadoop编程:分析CSDN注册邮箱分布情况

热门文章

  1. 基于密码的移动办公安全能力体系构建
  2. 疯狂的“元宇宙”炒房:有玩家囤了100套房,不到半年翻6倍
  3. SAS常用基础代码例子-数据描述性分析
  4. python爬取指定分辨率模特壁纸
  5. python识别音乐歌曲_如何轻松识别您正在听的歌曲
  6. 使用钉钉Api 向企业群发送文件 python
  7. 利用匿名管道实现远程CMD---我的解读
  8. innerText和innerHTML区别
  9. js replace() 使用
  10. 零基础计算机英语教程,零基础学英语语法的方法