第一章Vue核心
1.1Vue简介
一套用于构建用户界面的渐进式JavaScript框架
1.1.1Vue特点:
1. 采用组件化模式,提高代码复用率,且让代码更好维护
2. 声明式编码,让编码人员无需直接操作DOM,提高开发效率
3. 使用虚拟DOM+优秀的Diff算法,尽量复用DOM节点
1.1.2学习Vue之前要掌握的Js基础知识
ES6语法规范、ES6模块化、包管理器、原型、原型链、数组常用方法、axios、promise。。。
1.2初识Vue
- 想让vue工作:创建一个Vue实例+配置对象(data)
- root容器里的代码依然符合html规范,只不过加入了一些Vue语法
- root容器里的代码被称为【Vue模板】
- Vue实例和容器是一一对应的
- 真实开发中只有一个Vue实例,它有许多帮手
- {{xxx}}中的 xxx 只能是表达式,且xxx可以自动读取到data中的所有属性
- data中的数据如果改变,页面中也会改
<body>
<!-- 准备好一个容器 -->
<div id="root">
<h1>Hello.{{name}}</h1>
<h1>他.{{age}}岁</h1>
</div>
<script type="text/javascript">
Vue.config.productionTip = false;<!-- 阻止 vue 在启动时生成生产提示 -->
//创建Vue实例
const x = new Vue({
el:'#root', <!-- el用于指定当前Vue实例为哪个容器服务,值通常为为css选择器字符串 -->
data:{ <!-- data供el所制定的容器使用,值先暂时写成一个对象-->
name:'张天保',
age:19,
}
})
</script>
</body>
注意区分:js表达式 和 js代码(语句)
-
表达式:一个表达式会产生一个值,可以放在任何需要值的地方:
(1)a
(2)a+b
(3)demo(1)
-
js代码(语句)
(1)if(){}
(2)for(){}
1.3模板语法
1.3.1.插值语法
功能:用于解析标签体内容
写法:{{xxx}}. xxx 是js的表达式,且xxx可以自动读取到data中的所有属性
1.3.2.指令语法
功能:用于解析标签(包括:标签属性,标签体内容,绑定事件…)
举例:v-bind:href=“xxx” 可以简写成 :href=“xxx” xxx要写成js表达式,且xxx可以自动读取到data中的所有属性
备注:Vue中有很多的指令,且形式都是:v-???,此处只是用v-bind举了个例子
如果有多个name的话 建立一个 子.name
<h1>插值语法</h1>
<h3>你好.{{name}}</h3>
<hr>
<h1>指令语法</h1>
<a v-bind:href="children.url">点我去{{children.name}}</a>
1.4数据绑定
1.4.1单向数据绑定
v-bind: 数据只能从data–>页面
1.4.2双向数据绑定
v-model: 数据能从data<–>页面
备注:一般用在表单类元素上
v-model:value可简写为v-model,因为v-model默认收集的是value值
单向数据绑定<input type="text" v-bind:value="name"><br>
双向数据绑定<input type="text" v-model:value="name"><br>
双向数据绑定<input type="text" v-model="name">
1.5 el与data的两种写法
1.5.1el的两种写法
(1)new Vue时候配置el属性。
el:‘#root’
new Vue({
el:'#root',
data:{
name:'尚硅谷一',
}
})
(2)先创建Vue实例,随后再通过vm.$mount(‘#root’)指定el的值
v.$mount(‘#root’)
const v = new Vue({
data:{
name:'尚硅谷二'
}
})
console.log(v)
v.$mount('#root')
1.5.2 data的两种写法
(1)对象式
data: {
name: '尚硅谷'
}
(2)函数式:组件必须用函数式
data:function(){
return{
name:'尚硅谷'
}
}
注:由Vue管理的函数,一定不要写箭头函数,否则,this就不再是Vue实例了。
1.6 MVVM
Model-View-ViewModel
- M:模型:deta数据
- V:视图:模板代码
- VM:视图模型:vue实例
data中的所有属性,最后都到了vm
vm中的所有属性,都可以体现在vue实例中
<h3>姓名:{{name}}</h1>
<h3>地址:{{address}}</h3>
<h3>测试1:{{1+1}}</h3>
<h3>测试2:{{$options}}</h3>
1.7数据代理
1.回顾Object.defineProperty
对象的定义与赋值
Object.defineProperty(person,'age',{
value:18,
enumerable:true, //控制属性是否可以枚举,默认值false
writable:true, //控制属性修改,默认值false
condigurable:true //删除,false
})
2.何为数据代理
数据代理:通过一个对象代理对另一个对象中属性的操作
<script>
let obj1 = {x:100}
let obj2 = {y:200}
Object.defineProperty(obj2,'x',{
get(){
return obj1.x
},
set(value){
obj1.x = value
}
})
</script>
3.Vue中的数据代理
1.Vue中的数据代理:
通过vm对象来代理data对象中属性的操作(读/写)
2.Vue中数据代理的好处:
更加方便的操作data中的数据
3.基本原理:
通过Object.defineProperty()把data对象中所有属性添加到vm上
为每一个添加到vm上的属性,都指定一个getter/setter
在getter/setter内部去操作(读/写)data中对应的属性
<body>
<div id="root">
<h2>名称:{{name}}</h2>
<h2>地址:{{address}}</h2>
</div>
<script>
const vm = new Vue({
el:'#root',
data:{
name:'内蒙古农业大学',
address:'呼市'
}
})
</script>
</body>
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-niN3wOKo-1650547834650)(C:\Users\86151\AppData\Roaming\Typora\typora-user-images\image-20220207170509539.png)]
1.8事件处理
1.事件的基本使用
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 @click="showInfo1">点击这里进入1(无参)</button>
<button @click="showInfo2($event,66)">点击这里进入2(有参)</button>
</div>
<script>
new Vue({
el:'#root',
data:{
name:'Vue',
},
methods:{
showInfo1(){
alert('同学你好')
},
showInfo2(event,number){
console.log(event,number)
}
}
})
</script>
2.事件的修饰符
常用:
- prevent:阻止默认事件
- stop:阻止事件冒泡
- once:事件只触发一次
不常用:
-
capture:使用事件的捕获模式
-
self:只有event.target是当前操作的元素时才能触发事件
-
passive:时间的默认行为立即执行,无需等待事件回调执行完毕
可以连用:@click.stop.prevent=“”
<div id="root">
<!-- prevent:阻止默认事件(常用) -->
<a href="https://i.imau.edu.cn/" @click.prevent="showInfo">阻止默认事件</a><br>
<!-- 阻止事件冒泡(常用) -->
<div class="box1" @click="showInfo">
<button @click.stop="showInfo">阻止事件冒泡</button>
</div>
<!-- 事件只触发一次(常用) -->
<button @click.once="showInfo">事件只触发一次</button>
<!-- 使用事件的捕获模式 -->
<div class="box1" @click.capture="div1">
div1
<div class="box2" @click="div2">
div2
</div>
</div>
<!-- 只有event.target是当前操作的元素时才能触发事件 -->
<div class="demo01" @click.self="showInfo">
<button @click="showInfo">event.target是当前操作的元素时才能触发事件</button>
</div>
<!-- 时间的默认行为立即执行,无需等待事件回调执行完毕 -->
<!-- wheel和scroll滚动事件 -->
<ul @wheel.passive="demo" class="list" style="overflow: auto;">
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
</ul>
</div>
3.键盘事件
- Vue中常用的按键
- 回车------enter
- 删除------delete(删除和退格)
- 退出-----esc
- 空格------space
- 换行------tab
- 上-------up
- 下------down
- 左------left
- 右------right
- Vue未提供的可以用按键原始key值去绑定,两个大写字母要转换为kebab-case
- 系统修饰键:ctrl、alt、shift、meta
- @keyup:按下键的同时,按下其他键,释放其他键,事件才触发。
- @keydown:正常触发事件。
@keyup.ctrl.y="showInfo" //按下ctrl+y触发事件
- 使用keyCode(键码)去指定按键(不推荐,不一致)
- Vue.config.keyCodes.自定义键名 = 键码。(自定义按键别名)
@keyup.enter="" //按下、抬起触发
@keydown.enter="" //按下触发
1.9计算属性与监视
1.计算属性
computed:{}
get()、set()
computed:{
fullname:{
get(){
return this.firstname + '-' +this.lastname
},
set(value){
const arr = value.split('-')
this.firstname = arr[0]
this.lastname = arr[1]
}
}
}
简写模式:
条件:只有在只读不改下可以简写,计算属性较methods 具有缓存机制,更高效
computed:{
fullname(){
return this.firstname + '-' +this.lastname
}
}
2.监视属性
watch:{}
-
当被监视属性变化时,回调函数自动调用,进行相关操作
-
监视的属性必须存在
-
监视的两种写法:
new Vue时传入watch配置
通过vm.$watch监视
watch:{ Isappear:{ handler(newValue,oldValue){ console.log('Isappear被修改了',newValue,oldValue) } } }
vm.$watch('Isappear',{ immediate:true, deep:true, handler(newValue,oldValue){ console.log('Isappear被修改了',newValue,oldValue) } })
简写
Isappear(newValue,oldValue){
console.log('Isappear被修改了',newValue,oldValue)
}
vm.$watch('Isappear',function(newValue,oldValue){
console.log('Isappear被修改了',newValue,oldValue)
})
3.深度监视
-
Vue中watch默认不检测对象内部(一层)
-
deep:true可以检测对象内部值改变(多层)
-
备注:
Vue自身可以检测对象内部值的改变,但是watch默认不可以
使用watch随机应变,决定是否采用深度监视
1.10绑定样式
1.基础
- 正常的样式正常写: class=“basic normal”
- 需要变化的样式: :class=“a” (提供一个数据a:‘normal’)
<div class="basic" :class="mood" @click="changeMood">{{name}}</div>
<script>
new Vue({
el:'#root',
data:{
name:'绑定class样式',
mood:'normal'
}
})
</script>
-
style样式:
:style="{fontSize:x}" //xxx为动态值 :style="[a,b]" //a,b为样式对象
2.绑定样式
-
class
- 字符串写法::class=“mood” 适用于类名、名字不确定,动态改变
- 数组写法::class=“classArr” 适用于绑定样式个数、名字不确定
- 对象写法::class=“classObj” 适用于绑定样式个数、名字确定 需要动态指示
-
style
- 数组写法::style=“styleArr”
- 对象写style法::style=“styleObj”
1.11 条件渲染
-
v-show
适用于:切换频率较高的场景
不展示的DOM元素不被移除,仅隐藏掉
<h2 v-show="false">今日我们学{{name}}
-
v-if
适用于:切换频率较低的场景
不展示的DOM元素被移除
v-if和v-else-if 一起使用时,不能被打断
<h2 v-if="false">今日我们学{{name}}</h2>
<div v-if="n===1">1</div>
<div v-if="n===2">2</div>
<div v-else-if="n===3">3</div>
1.12列表渲染
1.基础列表
-
遍历数组
v-for=" x in xxx"
<ul> <li v-for="p in persons" :key="p.id"> {{p.name}}-{{p.age}} </li> </ul> persons:[ {id:'001',name:'张三',age:18}, {id:'002',name:'李四',age:19}, {id:'003',name:'王五',age:20} ],
-
遍历对象
car:{
name:'奥迪',
price:'70万',
color:'黑色'
}
2.key的原理
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-aeRfF6Ul-1650547834652)(C:\Users\86151\AppData\Roaming\Typora\typora-user-images\image-20220304142702081.png)]
3.列表过滤
- 计算属性监视属性都可,计算更好
computed:{
filPersons(){
return this.persons.filter((p)=>{
return p.name.indexOf(this.keyWord)!==-1
})
}
}
4.列表排序
1.13手机表单数据
手机表单数据
-
text : v-model收集的是value值,用户输入的就是value值
-
radio : v-model收集的是value值,且要给标签配value值
-
checkbox :要收集数组形式 [ ]
-
v-model的三个修饰符
lazy:失去焦点再收集数据
number:输入字符串转为有效数字
trim:输入首尾空格过滤
第二章组件
1.模块与组件、模块化与组件化
Vue中使用组件的三大步骤:定义(创建)、注册、使用(写组件标签)
-
如何定义
使用Vue.extend({ })创建
- el不要写——最终组件要经过vm管理,由vm中的el决定服务那个容器
- data需写成函数——避免组件被复用时,数据出现引用关系
- 使用template可以配置组件结构
// 第一步 创建组件 const school = Vue.extend({ //配置结构 template:` <div> <h2>学校名称:{{schoolName}}</h2> <h2>学校地址:{{address}}</h2> </div> `, //注意:无el data函数形式 data(){ return{ schoolName:'内农大', address:'呼和浩特' } } })
-
如何注册
局部注册:new Vue 中传入components选项
全局注册:Vue.component(‘组件名’,组件)
// 第二步 注册组件 new Vue({ el:'#root', components:{ school:school } })
-
编写组件标签
<组件></组件>
<div id="root"> <school></school> </div>
2.几个注意点
-
组件名
一个单词:school/School
多个单词:my-school/MySchool(需要Vue脚手架支持)
注:要回避html已有元素名 可使用name配置项在开发者工具中呈现名字
-
组件标签
注:不使用脚手架时会导致后续组件不能渲染
-
简写方式
const school = Vue.extend({ }) =>const school = { }
第三章路由
1. 一级路由
第一步:安装vue-router,命令:npm i vue-router
第二步:在mian.js中应用插件:Vue.use(VueRouter)
第三步:创建pages文件夹存放路由组件
第四步:创建一个router文件夹存放index.js
// 引入VueRouter
import VueRouter from "vue-router";
//引入路由组件
import MeHealth from '../components/MeHealth'
import MyTodo from '../components/MeTodo'
//创建并暴露一个路由器
export default new VueRouter({
router:[
{
path:'/MeHealth',
component:MeHealth
},
{
path:'/MyTodo',
component:MyTodo
}
]
})
第五步:实现切换(active-class配置高亮样式)
<router-link active-class="active" to="/about">About</router-link>
第六步:指定展示位置
<router-view></router-view>
2.二级路由(嵌套)
注:二级路由path后不需要加/
中的to属性中需要带上一级
routers:[
{
path:/one,
component:one,
//二级嵌套
children:[
{
path:two,//注意:这里不用加/
component:two,
}
]
}
]
<router-link active-class="active" to="one/two">二级路由</router-link>
3.query参数
路由传参
<router-link to="{
path:'/home/message/detail',
query:{
id:x.id,
title:x.title
}
}">点击内容</router-link>
{{$route.query.id}}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-D42o8GA2-1650547834652)(C:\Users\86151\AppData\Roaming\Typora\typora-user-images\image-20220318174303379.png)]
4.命名路由
简化路由的跳转
在index.js配置时 在routes:[ ]中加上name:‘luyou’ 在router-link中可直接找到
<router-link to="{name:'luyou'}">二级路由</router-link>
5.params参数
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-z61gINmp-1650547834653)(C:\Users\86151\AppData\Roaming\Typora\typora-user-images\image-20220318180158954.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jaXtBF5z-1650547834653)(C:\Users\86151\AppData\Roaming\Typora\typora-user-images\image-20220318180229338.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-oFCor6Ui-1650547834654)(C:\Users\86151\AppData\Roaming\Typora\typora-user-images\image-20220318180255103.png)]
er-view>
## 2.二级路由(嵌套)
注:二级路由path后不需要加/
<router-link>中的to属性中需要带上一级
```web
routers:[
{
path:/one,
component:one,
//二级嵌套
children:[
{
path:two,//注意:这里不用加/
component:two,
}
]
}
]
<router-link active-class="active" to="one/two">二级路由</router-link>
3.query参数
路由传参
<router-link to="{
path:'/home/message/detail',
query:{
id:x.id,
title:x.title
}
}">点击内容</router-link>
{{$route.query.id}}
[外链图片转存中…(img-D42o8GA2-1650547834652)]
4.命名路由
简化路由的跳转
在index.js配置时 在routes:[ ]中加上name:‘luyou’ 在router-link中可直接找到
<router-link to="{name:'luyou'}">二级路由</router-link>
5.params参数
[外链图片转存中…(img-z61gINmp-1650547834653)]
[外链图片转存中…(img-jaXtBF5z-1650547834653)]
[外链图片转存中…(img-oFCor6Ui-1650547834654)]