概念:Vue是用于构建用户界面的渐进式(就是学一点就能够用一点)框架,总的来说,就是基于数据来构建用户页面,以便于用户看懂。
Vue的两种使用方式:
1.核心包开发
2.核心包加插件加工程化开发
1.Vue的基础语法
1.创建第一个Vue实例
- 准备容器 div
- 引包 <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.js"></script>
- 创建Vue实例 new Vue()
- 指定配置项el data =>渲染数据(其中 el用于指定挂载点,选择器控制的是那一个盒子,而data用于提供数据)
<body>
<div id="app">
{{msg}}
</div>
</body>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.js"></script>
<script>
const app = new Vue({
el:'#app',
data:{
msg:'Hello'
}
})
</script>
2.插值表达式{{ }}
插值表达式是一种Vue的模板语法
1.作用:利用表达式进行插值,渲染到页面中
表达式:是可以被求值的代码,JS引擎会将其计算出一个结果
2.语法:{{ 表达式 }}
<div class="box">
{{ ct }}
{{age >= 18?'你已经成年了' : '你还没成年'}}
{{ name +'你好'}}
</div>
<script src="./vue.js"></script>
<script>
const ct = new Vue({
el:'.box',
data:{
ct:'大家好,我是杨文凯',
age:'18',
name:'杨文凯'
}
})
</script>
3.Vue核心特点:响应式
- data中的数据是会被添加到实例身上的,数据一但改变,视图就会自动更新
- 所以我们可以通过以下方式访问和修改数据
- 访问数据: 实例.属性名
- 修改数据: 实例.属性名 = 新值
- 此外,我们在进行调试的时候,可以使用开发者工具的插件来进行调试,效率更佳,但是要注意打开插件的访问文件权限,否则将无法看到实例。
4.Vue指令
Vue会根据不同的指令,针对标签实现不同功能。
指令:带有v-前缀的特殊标签属性
1. v-html:用于设置元素的innerhtml,语法:v-html ='表达式'
<div id="box">
<div v-html="msg"></div>
</div>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.js"></script>
<script>
const app = new Vue({
el:'#box',
data:{
msg:`<a href="https://www.baidu.com">百度</a>`
}
})
</script>
2. v-show 和 v-if
- v-show(通过display的值来简单的显示和隐藏)
- 作用:控制元素的显示隐藏
- 语法:v-show ="表达式" 表达式值true显示,false隐藏
- 原理:切换display:none来控制显示隐藏
- 适用场景:频繁切换显示隐藏的场景
- v-if (通过条件渲染来新建和移除元素)
- 作用:控制元素的显示隐藏
- 语法:v-if ="表达式" 表达式值true显示,false隐藏
- 原理:基于条件判断,是否创建和移除元素节点
- 适用场景:要么显示,要么隐藏,不频繁切换的场景
3. v-else v-else-if
配合v-if来进行使用,不能够单独地进行使用
- 作用:辅助v-if进行条件判断渲染
- 语法:v-if v-else-if =“表达式”
- 注意:需要紧挨着v-if一起使用
<div id="app">
<p v-if="score>=90">成绩高于90</p>
<p v-else-if="score>=85">成绩高于85</p>
<p v-else-if="score>=80">成绩高于80</p>
<p v-else>成绩低于80</p>
</div>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.js"></script>
<script>
const app = new Vue({
el:'#app',
data:{
xingbie:1,
score:75
}
})
</script>
4. v-on
- 作用:注册事件 = 添加监听 +处理逻辑
- 语法:v-on:事件名 =“内联语句”
-
-
- v-on:事件名 =“methods中的函数名”
- 简写:@事件名=“内联语句/methods中的函数名”
-
<div id="app">
<button v-on:mouseenter="score--">-</button>
<span>{{score}}</span>
<button @click="score++">+</button>
</div>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.js"></script>
<script>
const app = new Vue
el:'#app',
data:{
xingbie:1,
score:75
}
})
v-on配置的methods中的函数名:
在methods中想要使用data中的数据,应该怎么办?
- 因为使用vue进行数据的挂载时,已经将data数据挂载到实例身上,所以在后续使用时,可以直接通过实例.数据名的形式来进行调用。
- 可以使用this这个关键字来进行来直接代表新创建的这个实例,从而进行实例.数据名的调用,也就是this.数据名
v-on的参数传递:
5. v-bind
使用原因:因为在标签的属性不可以使用插值表达式,我们又想要设置给这个标签增加属性和属性值
1.作用:动态的设置html的标签属性 -> src url title ...
2.语法 v-bind : 属性名="表达式"
案例1 漫画故事播放案例
- 将图片以数组形式进行存储
- 设置图片的下标索引,以便于图片的提取
- 对图片标签的src属性通过v-bind:属性名="表达式"进行动态绑定
- 对上一页下一页的按钮进行点击事件的绑定,同时改变索引值
- 判断边界条件,通过v-show来控制上下页按钮的显示与隐藏
6.v-for
- 作用:基于数据渲染,多次渲染整个元素,可以在工程化开发中,多次创建需要渲染的组件
- 遍历数组语法:v-for="(item,index) in 数组" :key="index",其中item代表每一项,index代表下标
如果index不需要时,可以将其省略,其结构为v-for ="item in 数组" :key="item"
3.v-for中的key
- 作用:给元素添加的唯一标识,便于Vue进行列表项的正确排序复用。
- 注意点:key的值只能是字符串或数字类型
- key的值必须具有唯一性
- 由于id属于数据的固有属性,而index属于数据的暂时属性,随着数据在数组中的空间改变而变化,所以
- 推荐使用id作为key,不推荐index作为key,
."
案例2 书架系统逻辑案例
- 使用v-for来多次渲染通过接口交互获取来的数据
- 灵活使用v-for语句自带的item,index来进行数据的回显等等
- 通过filter过滤器结合id值判断来进行将书本移出书架操作
7.v-model
- 作用:给表单元素使用,双向数据绑定 可以快速获取和设置表单元素内容
- 数据变化时视图自动更新
- 视图变化时数据自动更新
- 语法:v-model ='变量'
5.指令的修饰符
通过"."指明一些指令后缀,不同后缀封装了不同的处理操作,其目的是简化代码
- 按键修饰符 @keyup.enter ->键盘回车监听
- v-model修饰符 v-model.trim ->去除首尾空格 v-model.number ->转数字
- 事件修饰符 @事件名.stop ->阻止冒泡 @事件名.prevent ->阻止默认行为
6.v-bind对于样式控制的增强-操作class
语法::class="对象/数组"
- 对象:此时键是类名,值是布尔值。如果值为true则有这个类,否则就没有这个类。适用场景:一个类名来回切换
- 数组:此时数组中的所有的类,都会被添加到盒子上,其本质是一个class列表 适用场景:批量进行class的添加或者删除操作
案例 导航栏高亮切换思路
- 通过v-for渲染导航栏列表,注意要设置key
- 清除默认列表默认格式:在ul的css中设置list-style=none;在li中设置float:left;随后设置margin属性等等。清除超链接<a>的默认格式:text-decoration: none;
- 设置当前下标索引值onindex存储数据,通过:class={active:index===onindex}来设置只有index===onindex时才会添加active这个类,再通过@click="onindex=index"当点击哪个li时将这个被点击的index赋值给onindex,最终实现将带有装饰的高亮块的class(active)添加至被点击的li
<style>
.main ul{
list-style: none;
}
.main li{
float: left;
margin-left: 50px;
}
.active{
width: 200px;
height: 200px;
background-color: rgb(255, 0, 0);
}
a{
text-decoration: none;
color: black;
}
</style>
</head>
<body>
<div class="main">
<ul >
<li v-for="(item,index) in list" :key="item.id" @click="onindex=index">
<a :class="{active:index===onindex}" href="#">{{item.name}}</a>
</li>
</ul>
</div>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.js"></script>
<script>
const main = new Vue({
el:'.main',
data:{
onindex:0,
list:[
{id:1,name:'首页'},
{id:2,name:'关于我们'},
{id:3,name:'联系我们'},
{id:4,name:'产品中心'},
]
},
})
</script>
7.v-bind 对于样式控制的增强 - 操作style
语法: :style="样式对象"
适用场景:对于某个具体属性进行动态设置(如进度条的设置,其本质是两个盒子,其中内部盒子的宽度的变化实现了进度条的变化)
案例 进度条的进度设置
- 设置外层盒子和内层盒子,内层盒子的宽度width属性作为进度的可视化(盒子一定要设置高度,否则不显示)
- 在新建的vue实例的data中设置一个percent属性来记录内层盒子百分号前的数字
- 通过v-bind:style{width:percent +'%'}来给内层盒子使用vue实例中的数据来动态设置宽度
- 再将4个写有设置xx%的按钮绑定点击事件@click='percent=xx'
- 最终即可实现进度条的设置
8.v-model应用于其他表单元素
常见的表单元素都可以使用v-model进行数据的绑定关联,其目的是快速获取或者设置表单元素的值,他会根据控件类型来选取正确的方法来更新元素
在HTML中,input元素的type属性用于指定输入字段的类型。以下是一些常见的input类型:
- text:用于接受单行文本输入。
- password:用于接受密码输入,文本会被隐藏。
- checkbox:用于选择一个或多个选项。
- radio:用于从一组选项中选择一个选项。
- submit:用于提交表单数据。
- reset:用于重置表单数据。
- button:用于创建一个按钮。
- file:用于选择文件上传。
- number:用于接受数字输入。
- date:用于接受日期输入。
- email:用于接受电子邮件地址输入。
- tel:用于接受电话号码输入。
- url:用于接受URL输入。
- color:用于选择颜色。
- range:用于选择范围内的值。
- time:用于接受时间输入。
- month:用于接受月份输入。
- week:用于接受周数输入。
这些是常见的input类型,每种类型都有不同的用途和功能。
9.计算属性computed
概念:根据现有的数据,计算出来的新属性。现有的数据发生变化,会自动重新计算。其本质上是一个属性。
语法:
- 声明在computed配置项中,一个计算属性对应一个函数
- 使用起来和普通属性一样使用{{ 计算属性名 }}
computed属性和methods方法的异同点
conputed计算属性:
- 作用:封装了一段对于数据的处理,求得一个结果。侧重处理数据。
- 语法:写在comouted配置项之中;本质是属性,可以直接使用this.计算属性{{ 计算属性 }}
- 注意:计算属性是有缓存特性的,所以能够有效提高性能,一旦计算出结果就会立刻缓存,只要依赖项没有发生变化,就可以直接读取原本的缓存,当依赖项发生变化时,会立刻重新计算,立刻缓存。
methods方法:
- 作用:给实例提供一个方法,调用以处理业务逻辑。侧重处理业务。
- 语法:写在methods配置项中;作为方法,需要调用。调用方法:this.方法名() {{ 方法名()} } @click="方法名"
计算属性的完整写法:
计算属性默认的简写,只能够读取访问,不能“修改”。如果要修改,则要使用计算属性的完整写法。完整的计算属性写法如下:
computed:{
//当fullname计算属性被获取求值时,会执行get(有缓存),并且将返回值作为求值的结果
fullname:{
get(){
},
//当fullname被修改赋值时,执行set
//修改的值会传给set的形参
set(形参 ){
}
}
}
10.综合案例--成绩登记案例
11.watch侦听器(监视器)
作用:监视数据变化。执行一些业务逻辑或异步操作。
语法:1.简单写法 ->监视简单类型数据,直接监视
<div id="app">
<textarea name="" id="" cols="30" rows="10" v-model="obj.msg"></textarea>
</div>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.js"></script>
<script>
const app = new Vue({
el:'#app',
data:{
obj:{msg:"快来输入些什么吧",}
},
watch:{
'obj.msg'(newvalue,oldvalue){
console.log('改变了',newvalue,oldvalue)
}
}
})
</script>
2.完整写法->添加额外配置项
- deep:true 对复杂类型深度监视,比如对对象中的所有属性都进行监视
- immediate:true 初始化立刻执行一次handler方法
实例:实时翻译功能的实现
需求:
- 改变文本,更换语言都能够触发监听事件,所以设置deep:true来实现对于obj对象的深度监视
- 此时在watch:{}中添加handler(){}处理函数,当触发监听时,执行函数内部的处理逻辑
- 需求优化,当文本内容有默认值时,也想要有默认的翻译值,该怎么办?添加配置项immediate:true,使得一进入页面就立刻执行翻译一次
如果可以只使用简单写法时尽量使用简单写法
12.Vue的生命周期和生命周期的四个阶段
生命周期概念:一个Vue实例从创建到销毁的整个过程,从new Vue()开始创建到销毁,整个完整的过程才是Vue 的生命周期。
生命周期的四个阶段:
- 创建阶段:对数据进行初始化设置,对数据进行响应式处理。即经过创建阶段后,数据就已经是响应式的了。只执行一次。
- 挂载阶段:渲染模板,使用响应式数据进行渲染。只执行一次。
- 更新阶段:数据修改,视图进行更新,可以进行重复多次的更新,不同于创建阶段和挂载阶段,即可以进行多次的循环,可以执行多次。
- 销毁阶段:把实例给销毁。
什么时候可以发送初始化渲染请求?(越早越好)
至少要等响应式数据创建完毕之后,即创建阶段的最后。所以使用的是created钩子函数。
什么时候可以开始操作dom?(至少dom得渲染出来)
至少要等挂载阶段结束之后。所以使用的是mounted钩子函数。
13.生命周期钩子函数
Vue生命周期过程中,会自动运行一些函数,被称为【生命周期钩子函数】 -> 可以让开发者在【特定阶段】运行自己的代码,生命周期过程中可以分为四对钩子函数(或者八个钩子函数)
- created钩子函数:创建阶段的尾巴,可以用来发送初始化渲染的请求。
- mounted钩子函数:挂载阶段的尾巴,dom渲染完毕了,可以开始进行操作dom了。
- beforeupdate钩子函数:数据更新时执行,这个beforeupdate钩子函数拿到的是更新之前的dom结构,数据修改了,视图还没更新。
- updated钩子函数:同样数据更新时执行,这个updated函数拿到的时更新后的dom结构,数据修改了,视图已经更新。
- before Distory钩子函数:在销毁之前,释放Vue以外的资源(如清除定时器,延时器等),用于提升性能。
卸载当前实例的方法:在控制台上输入app.$destory()
14.钩子函数的运用
1.created的应用
以渲染新闻列表为例:
原因:在拥有对数据进行初始化设置的需求时,可以在与data并列的位置进行对于created钩子函数的设置,在其中发出初始化请求。
2.mounted的应用
以输入框焦点获取为例:
原因:因为auto-focus在vue中不可使用,而用户又有对于获取焦点框的需求。所以我们可以在数据渲染之后进行dom的操作(即获取焦点)
<script>
const app = new Vue({
el: '#app',
data: {
words: ''
},
mounted(){
document.querySelector('#inp').focus()
}
})
</script>
15.工程化开发和脚手架工具Vue CLI
开发vue的两种方式:
- 核心包传统开发模式:基于html/css/js文件,直接引入核心包,开发vue
- 工程化开发模式:基于构建工具(例如webpack)的环境中开发Vue。
基本介绍:
Vue CLI是Vue官方提供的一个全局命令工具。
可以帮助我们快速创建一个开发Vue项目的标准化基础架子。(集成了标准化的webpack配置)
脚本命令可以在 package.json 文件中的scripts里面进行设置
项目目录介绍和运行流程
16.组件化开发 & 根组件
组件化:一个页面可以拆分成一个个组件,每个组件都有着自己独立的结构、样式、行为。这样的好处是便于维护,利于复用,以达成提升开发效率的目的
组件分类:普通组件,根组件(整个应用最上层的组件,包裹所有普通小组件)
App.vue文件(单文件组件)的三个组成部分
三部分组成:
- template:结构(有且只能一个根元素)
- script:js逻辑(可以提供data(特殊) methods computed watch 生命周期钩子函数)
- style:样式(可支持less,需要装包),装包步骤
(1)在style标签中增添lang="less" 开启less功能
(2)安装依赖包 npm i less less-loader --save-dev
普通组件的注册使用
注册组件的两种方式:
- 局部注册:只能在注册的组件内使用 步骤1.创建组件vue文件(三个组成部分) 步骤2.在使用的组件内导入注册,即先导入需要进行注册的组件,然后再进行局部注册
- 全局注册:一旦注册成功后,所有组件中都能够使用。步骤1:创建.vue文件(三个组成部分) 步骤2:在main.js中进行注册,也是先导入需要进行注册组件,然后进行全局注册
组件的使用:
- 当成html标签使用 `<组件名></组件名>`
注意事项:
- 组件名的命名规范 -> 大驼峰命名法,如:HmHeader
使用脚手架工具建立项目-以购物商城为例
1.页面开发思路
- 分析页面,按照模块拆分组件,搭架子(局部或者是全局注册),
- 根据设计图,编写组件html结构css样式(已准备好)
- 拆分封装成通用小组件(局部或者全局注册)
- 最后,通过js来进行动态渲染,实现功能
17.scoped冲突(组件和组件之间的样式冲突)
组件的三大组成部分-注意点说明
- 结构<template> 只能有一个根元素
- 组件中的样式<style>全局样式(默认):会影响全局的样式,但是我们常常只是想要更改局部的样式,却连同全局的样式一起修改,所以这会和我们的预期背道而驰。所以我们想要只更改局部的样式:就在style的后面加上scoped下的样式,这样style中的所有样式就只作用于当前组件。
- 逻辑<script>el是根实例独有的,data是一个函数,其他配置项一致
默认情况:写在组件中的样式会全局生效 ->因此很容易造成多个组件之间的样式冲突问题。
- 想要设置全局样式时:默认组件中的样式会作用到全局
- 想要设置局部样式时:可以给组件的style后面加上加上scoped属性,可以让样式只作用于当前组件,而不影响全局
scoped原理:
1.当前组件模板的所有元素,都会被添加上一个自定义属性data - v - hash值
2.此种包裹的css选择器都被添加上了属性选择器[data-v-hash]
最终达成的效果:必须是当前组件的元素,才会有这个自定义属性,才会被这个样式作用到
18.data是一个函数
逻辑原理:一个组件的data选项必须是一个函数。其目的是保证每个组件的实例都有独立的一份数据对象。
每次创建新的组件实例,都会新执行一次data函数,从而得到一个新的对象。
data(){
return {
count:100
}
},
19.组件通信
组件通信的定义:就是指组件与组件之间的数据传递
- 组件的数据是独立的,无法直接访问其他组件的数据
- 想用其他组件的数据 ->组件通信
不同组件关系和组件通信方案分类
组件关系分类:
- 父子关系
- 非父子关系
父组件:
子组件:
组件通信解决方案:
父子通信流程图:
- 父组件通过props将数据传递给子组件
什么是prop
prop定义:组件上注册的一些自定义属性/96+
prop作用:向子组件传递数据
特点:
- 可以传递任意数量的prop
- 可以传递任意类型的prop
props校验
作用:为组件的prop指定验证要求,不符合要求,控制台就会有错误提示 -> 帮助开发者,快速发现问题
语法:
- 类型校验
props:{
校验的属性名:类型 //Number String Boolean...
},
- 非空校验
- 默认值
- 自定义校验
props:{
w:{
type:类型,//Number String Boolean...
required:true,//是否必填
default:默认值,//默认值
validator(value){
//自定义校验逻辑
//console.log(value)
if(value >= 0 && value <= 100){
return true
}else{
console.error('传入的prop w,必须在0~100之间')
return false是否通过校验
}
}
}
}
prop & data 单向数据流
共同点:都可以给组件提供数据。
区别:
- data的数据是自己的 -> 随便改(谁的数据谁负责)
- prop的数据是外部的 -> 不能直接修改,要遵循 单向数据流,使用$emit通知父组件,让父组件来对数据进行修改,父组件的数据进行修改后,单向向下流动,影响到子组件
- 子组件利用$emit通知父组件修改更新
this.$emit('事件名',数据),父组件再在使用这个模板的地方进行时间监听然后再完善事件处理逻辑,如果处理逻辑简单,可以直接写行内,注意:行内要想拿到子组件传递来的数据,也就是拿到当前的形参,我们要使用$event来进行获取
非父子通信(拓展)-event bus事件总线
非父子组件之间,进行简易消息传递。(复杂场景 -> vuex)
- 创建一个都能访问的到的事件总线(空vue实例) -> utils/EventBus.js
import Vue from 'vue'
const Bus = new Vue()
export default Bus
- A组件(接收方),监听Bus实例的事件
created(){
Bus.$on('sendMsg',(msg) => {
this.msg = msg
})
}
3.B组件(发送方),触发Bus实例的事件
Bus.$emit('sendMsg','这是一个消息')
非父子通信(拓展)-provide & inject
provide & inject 作用:跨层级共享数据,子孙后代的层级都能够使用
export default{
provide () {
return {
//普通类型(非响应式的)
color: this.color,
//复杂类型(响应式的)
userinfo:this.usrInfo,
}
}
}
export default{
inject:['color','userInfo'],
created () {
console.log(this.color,this.userInfo)
}
}
简单类型的数据是非响应式的,复杂类型是响应式的,所以在实际开发中,我们更加倾向于响应式的,所以我们要使用复杂类型,如对象。
组件化管理模块--以小黑记事本为例
1.渲染功能:
- 提供数据 -> 提供在公共的父组件
- 通过父传子,将数据传递给子组件
- 通过v-for来进行数据的渲染
2.添加功能
- 收集表单数据 -> v-model
- 监听事件(回车和点击都要进行添加操作)
- 子传父将任务名称传递给父组件
- 进行添加
3.删除功能
- 监听事件(监听删除的点击)携带id
- 子传父,将被点击删除按钮对应的id传递给父组件
- 在父组件进行删除,filter(自己的数据可以删除),所有不等于当前id的都保留下来
v-model在组件通信上的应用
v-model的原理
原理:v-model的本质上是一个语法糖(语法的间简写)。例如应用在输入框上,就是value属性和input事件的合写。
作用:提供双向数据绑定
- 数据发生变化,页面自动发生变化,把视图绑定数据 :value
- 页面发生变化,数据会自动变化 ,监听输入框的值,赋值给数据:@input
注意:$event用于在模板中,获取事件的形参
<template>
<div id="app">
<input v-model="msg" type="text">
<input :value="msg" @input="msg = $event.target.value" type="text">
</div>
</template>
表单类组件封装&v-model简化代码
- 表单类组件封装
- 父传子:不可以将v-model和props传过来的数据进行绑定,所以我们要进行拆解,v-model拆解绑定数据(v-model是双向数据绑定,但是儿子不可以直接修改父亲的值,所以我们要进行v-model的拆解数据绑定)
- 子传父:监听数据,子传父,使用$emit传递+给父亲,让父亲进行修改
- 父组件v-model简化代码,实现子组件和父组件数据双向绑定,把固定参数写死,子组件中:props通过value接收,事件触发input 父组件中:v-model给组件直接绑数据
20.".sync修饰符"
作用:可以实现子组件与父组件数据的双向绑定,简化代码
特点:prop属性名,可以自定义,非固定为value
场景:封装弹框类的基础组件,visible属性(自定义的属性名 ),true显示,false隐藏
本质:就是 :属性名 和 @update:属性名合写
<dad :visible.sync="isshow"> </dad>
21.ref和$refs
作用:由于queryselector查找范围是整个页面,如果碰到组件和组件之间类名一样的盒子那么就会造成不精准的后果,而利用ref和$refs可以用于获取dom元素,或者组件实例,相比于queryselector而言,更加精准。
特点:查找范围 -> 当前组件内(更加精确稳定)
- 获取dom:
- 目标标签 - 添加ref属性
<div ref="chartRef">我是渲染图标的容器<div>
- 恰当时期(至少在mounted之后),通过this.$refs.xxx,获取目标元素,为什么是恰当时期呢?是因为要等dom盒子渲染出来了,才能够获取这个标签,才能够获取这个标签
mounted () {
console.log(this.$refs.chartRef)
},
- 获取组件
- 目标组件 -添加ref属性
<BaseForm ref="baseForm"> </BaseForm>
- 恰当实际,通过this.$refs.xxx,获取目标组件,就可以调用组件对象里面的方法
this.$refs.baseForm.组件方法()
22.Vue异步更新、$nextTick
需求:编辑标题,编辑框自动聚焦
- 点击编辑,显示编辑框
- 让编辑框,立刻获取焦点
问题:不能够立即获取焦点
原因:Vue是异步更新DOM(提升性能),是因为Vue的特性,导致这时候dom还没有更新,从而提出新的解决方法¥nextTick,所以我们想要在DOM更新完成之后做某件事,可以使用$nextTick
$nextTick:等DOM更新后,才会触发执行此方法里的函数体
语法:this.$nextTick(函数体)
this.$nextTick(() => {
this.$refs.inp.focus()
})
23.自定义指令
自定义指令:自己定义的指令,可以封装一些dom操作,拓展额外功能
需求:当页面加载时,让元素将获得焦点
- 全局注册 - 语法
Vue.directive('指令名',{
inserted (el) {
el.focus()
}
})
- 局部注册 - 语
directives:{
"指令名":{
interted () {
el.focus()
}
}
}
自定义指令--以传递不同的颜色,给标签设置文字颜色为例
需求:实现一个color指令-传入不同的颜色,给标签设置文字颜色
语法:在绑定标签时,可以通过等号的形式为指令绑定具体的参考值
<div v-color="color">我是内容</div>
通过binding.value可以拿到指令值,指令值修改会触发update函数。通过update钩子,可以监听指令值的变化,进行dom更新操作。
directives:{
color:{
inserted(el,binding){
el.style.color=binding.value
},
update(el,binding){
el.style.color=binding.value
}
}
}
自定义指令 -- 以v-loading指令封装为例子
场景:开发中,发送请求是需要时间的,在请求的数据未回来时,页面会一直处于空白状态,用户的体验会不太好
分析:
- 本质上loading效果就是一个蒙层,盖在了盒子上
- 数据请求中,开启loading状态,添加蒙层
- 数据请求完毕,关闭loading状态,移除蒙层
实现
- 准备一个loading类,通过一个伪元素定位,设置宽高,实现蒙层
- 开启(关闭)蒙层状态,本质上就是添加或者移除类即可
- 结合兹定于属性的语法进行封装
25.插槽
插槽-默认插槽(组件内定制一处内容时)
作用:当组件内某一部分结构不确定时,让组件内部的一些结构支持自定义
需求:要在页面中显示一个对话框,封装成为一个组件
问题:组件的内容部分,不希望写死,希望使用的时候能够自定义,所以我们应该怎么办
插槽基本语法:
1.组件内需要定制的结构部分,改用<slot></slot>占位
2.使用组件时,组件标签内部,传入结构替换slot
插槽-后备内容(默认值)
通过插槽完成了内容的定制,传递什么显示什么,但是如果不传会显示空白,所以我们想,能否给插槽设置默认显示内容呢?
插槽后备内容:封装组件时,可以为预留的`<slot>`插槽提供后备内容(默认内容)。
语法:在<slot>标签内部,放置内容,作为默认显示内容。
效果:
外部使用组件时,不传东西,则slot会显示默认的后备内容
外部使用组件时,传东西了,则slot内部默认的后备内容会被从MyDialog中传递的内容替换掉
插槽-具名插槽(组件内定制多处内容时)
需求:一个组件内有多处结构 需要外部传入标签,进行定制,
注意:一旦使用具体插槽,就只支持定向分发
具名插槽语法:
1.定义组件时slot占位,给name属性起名字来进行区分
2.复用组件时template配合 v-slot:插槽名 分发内容
3.分发内容时 v-slot:插槽名可以简写成#插槽名
插槽-作用域插槽
作用域插槽:定义slot插槽的同时,是可以传值的。给插槽上可以绑定数据,将来使用组件时可以用。
基本使用步骤:
1.给slot标签,以添加属性的方式传值
<slot :id="item.id" msg="测试文本"></slot>
2.所有添加的属性,都会被收集到一个对象中
{id:3,msg:'测试文本'}
3.在复用组件时,通过`#插槽名="obj"`来进行接收,默认插槽名为default
26.综合案例-以my-tag标签为例
1.双击显示并且自动获取焦点
2.一离开就隐藏输入框
3.双击回显原数据
4.内容修改了,回车就会修改数据
27.单页应用程序:SPA-Single Page
SPA:所有功能都在一个html上
路由:组件和路径之间的映射关系,就是什么路径对应什么组件
28.VueRouter的介绍
本质上是一个插件,是官方的路由插件,第三方包,我们需要熟悉掌握VueRouter,
使用步骤:5+2(固定的,需要熟练)
router-view 控制更换后组件所展示的位置
路由的封装抽离
目标:将路由模块从main.js中抽离出来,拆分模块,以便于维护。
步骤:1.把路由规则等移动至router下的index.js
2.在index.js中导入vue
3.导出
4.注意,各个vue文件的相对路径在抽离的过程中会发生变化,要进行修改,也可以直接使用绝对路径来进行避免(使用标识符@,@代表根目录)
声明式导航-导航链接
需求:实现导航高亮效果
vue-router提供了一个全局组件router-link(取代a标签)
<router-link to="/路径值"></router-link>
.router-link-exact-active{
backgroundcolor:pink;
}//如此编辑以快速设置背景高亮
使用router-link 代替a标签的本质上是生成一个a标签并给其自动生成两个class以实现简化代码的作用
1.router-link-exact-active 精确匹配(子路径点击,父路径也是高亮的,只要包含即可)
2.router-link-active 模糊匹配
自定义匹配类名
希望自定义时,找到导入的router配置项进行修改
声明式导航-跳转传参
定义:在跳转路由时,进行传值
1.查询参数传参
1.跳转路径时填写查询参数to="/path?参数名=值"
2.在跳转完成的页面组件接收传递过来的值
在vue结构中使用$route.query.参数名 来获取参数值
在js代码中要想获得,则要加上this,即this.$route.query.参数名
2.动态路由传参
配路由,配导航,接收值
两种传参方式s的区别
在配置路由的时候path:"/path/:words"后面加上?即path:"/path/:words?"这样传参不传参都可以,不会出现空白,若没有加上,则没有携带参数就会空白,必须要传参数。参数可传可不传 ->path:"/path/:words?"
组件存放目录问题
组件分类:.vue文件分为两类:页面组件和复用组件,但是本质上都是.vue文件,没有区别
目的:分类开来以达到更加容易维护
29.Vue路由-重定向
实现网页打开时自动跳转至我们想要的路径下
也是在配路由的时候配一下,
routes:[
{path:'/',redirect:'/home'}]
希望匹配的路径 希望跳转的路径
vue路由-404
目的:实现找不到对应的匹配时,给一个页面提示。
位置:配在路由最后
语法:path:"*"(任意路径)-router是按照顺序匹配的,前面的没有匹配到,就用这个最后一个来进行匹配
vue-模式设置
有#存在,会有一些不自然,怎么切换成为真正的路径?
1.hash路由(默认)
2.history路由(常用)
在配置时,增加一个mode配置项来修改模式
mode:"history"(默认为hash)
编程式导航-基本跳转
实现:点击按钮实现跳转(用js代码实现跳转)
两种语法:
1.path路径跳转
【简写】this.$router.push('路由路径')
【完整写法】this.$router.push({
path:'路由路径'})、
2.name命名路径跳转(适合path路径名比较长的场景)
this.$router.push({
name:'路由名'
})
编程式导航-路由传参
两种传参方式:
1.path路径跳转传参
2.name命名跳转传参
30.自定义创建项目
目标:基于VueCli自定义创建项目架子
40.ESlint代码规范(包含快捷指令)
根据错误提示进行手动修正(可以利用ESLint规则表去查询具体含义)或者自动修正
41.Vuex
vuex概述
1.是什么:是一个状态管理工具(插件),状态就是数据,可以帮我们管理vue通用的数据(多组件共享的数据),来减少组件通信的流程
2.应用场景:(1)某个数据在多个组件中使用 (2)多个组件共同维护一份数据
3.优势:(1)共同维护了一份数据,数据集中化管理
(2)响应式变化 (3)操作简洁(vuex提供了一些辅助函数)
创建仓库来存储通用数据
目标:安装vuex插件,初始化一个空仓库
1.yarn add vuex@3 (233 344)//版本号,根据vue的版本来进行插件版本号的确认
2.新建store/index.js来专门存放vuex,存放仓库数据等
3.Vue.use(Vuex)创建仓库new Vuex.Store()
4.在main.js中导入挂载到Vue实例上
如何提供和访问vuex的数据(明确如何给仓库提供数据,如何使用仓库的数据)
概念1:state状态 :state状态 提供唯一的公共数据源,所有共享的数据都要统一放在store中的state中存储,在state对象中可以添加我们要共享的数据。与data不同的是,data是自己的数据,而state是共享的数据。
1.存放数据:在store中开一个state对象,在这个对象中存放要共享的数据
2.使用数据:(1)通过store直接访问
(2)通过辅助函数(简化)
mapState是辅助函数,可以帮助我们把store中的数据自动映射到组件的计算属性之中,其本质还是通过获取路径的方法来进行获取数据,只是使用了mapstate函数来代替路径寻找方式,比如说是this.$store.state.xxx
概念2:mutations,通过mutation来进行修改state的数据,state数据的修改只能通过mutations。
vuex同样遵循单向数据流 ,组件中不可以直接修改仓库中的数据,通过strict:true来开启严格模式,严格控制单向数据流的规则,这样只要出现了不符合单向传递的语句(即组件修改仓库),就会进行报错。但是上线的时候需要关闭 。(监测需要成本)
通过提交mutation的形式来进行提交修改
1.定义mutation对象,对象中存放修改state的方法
2.组件中进行提交并调用mutations
总的就是,在仓库的mutations中进行定义操控数据 的方法,然后 再在组件中需要使用操作数据的地方提交所需要的申请
mutations传参方法
提交 mutation是可以传递参数的`this.$store.commit('xxx',参数)`,提交载荷有且只能有一个参数,如果要使用多个参数,我们可以将其包装成对象或者数组
辅助函数:mapMutations
mapmutations和mapstate很像,她是把位于mutatuions中的方法提取出来,映射到组件methods中
actions
目的:明确actions的基础语法,处理异步操作。
假设需求:一秒钟之后,修改state的count为666
原因 :mutation必须是同步的(便于检测数据变化,记录调试)
定义actions:
调用actions:
辅助函数:mapactions
mapactions是把位于actions中的方法提取了出来,映射到组件 methods中
getters
辅助函数 mapGetters
module(进阶语法) -分模块处理store
分模块之后的访问state&mutations等
尽管已经分模块了,但是子模块的状态,还是会挂到根级别的 state中,属性名就是模块名
使用模块中的数据:
(1)直接通过模块名访问$store.state.模块名 .xxx
(2)通过mapstate映射 maptate('模块名',['数据名']),通过模块名来进行映射时,要先开启命名空间
使用模块中的getter:
42.vant组件库(是组件库中的一种)
目标:认识第三方vue组件库vant-ui
全部导入
按需求导入
分为自动按照需求引入和 手动按需求引入
module.exports = {
presets: [
'@vue/cli-plugin-babel/preset'
],
plugins: [
['import', {
libraryName: 'vant',
libraryDirectory: 'es',
style: true
}, 'vant']
]
}
43.项目中的vw适配
目标:基于postcss插件,实现项目vw适配,将px单位转化成为vw,实现浏览器适配
标签:10,Vue,入门,data,vue2,使用,组件,数据,属性 From: https://blog.csdn.net/qq_73961485/article/details/143822625