Vue进阶

生命周期

组件运行的过程

组件的生命周期是:组件从创建->运行(渲染)->销毁的整个过程,是一个时间段

如何监听组件的不同时刻

vue框架为组件内置了不同时刻的生命周期函数,是他在关键时刻帮我们调用的一些特殊名称的函数,生命周期函数会伴随着组件的运行而自动调用

  • created函数 组件在内存中被创建完毕
  • mounted函数 组件第一次被渲染到页面上
  • unmounted函数 组件被销毁完毕了(隐藏)
  • updated函数 当组件被重新渲染完毕后会自动调用

当组件被重新渲染完毕后,会自动调用updated生命周期函数

组件中全部的生命周期函数

问:为什么不在beforeCreate中发ajax请求?

此阶段无法访问data,请求到的数据无法挂载到data中供组件渲染去使用

完整的生命周期函数

Vue2.x

Vue3.x

组件化编程

模块:向外提供特定功能的Js程序,一般是一个Js文件。

组件:实现应用中局部功能代码资源的代码集合。

模块化:当应用中的Js都以模块化来编写,那这个应用就是一个模块化应用。

组件化:当应用中的功能都是多组件的方式来编写,那这个应用就是一个组件化的应用。

单文件组件:一个文件中只有一个组件

vue单文件组件的构成

template 组件的模板结构(必须)

script 组件的js行为

style 组件的样式

template节点

规定:每个组件对应的模板结构,都需要定义<template>节点中,是vue提供的容器标签,<template>只起到包裹性质的作用,不会被渲染成真正的DOM元素。

<template>节点中支持指令语法

在vue2.x的版本中,DOM结构仅支持单个根节点

在vue3.x的版本中,DOM结构仅支持多个根节点

script节点

<script>
export default{} //data数据和methods方法
</script>

name节点:为组件定义一个名称

data节点:vue组件渲染期间需要用到的数据(data需指向一个函数,函数中再return对象)

methods节点:组件中的事件处理函数节点

style节点

style标签上的lang=‘css’属性是可选的,它表示所使用的样式语言,默认css,还有less和scss语法

组件的基本使用

1、组件的命名

kebab-case命名法(短横线命名法)、Camelcase命名法(大驼峰命名法)(后者可转化为短横线使用,只能在脚手架中使用)

也可以将name属性作为注册后组件的名称,尽可能回避HTML已有的元素名称。

2、组件的注册

组件之间可以相互的引用,但必须先注册后使用

全局和局部注册

被全局注册的组件可以在全局如何一个组件内使用,被局部注册只能在当前注册范围内使用

.component(’ 名称‘,组件名)方法全局注册

component:{键值对}局部注册

使用频率高的进行全局注册,使用频率低的局部注册

3、组件之间的样式冲突问题

父组件的样式会影响子组件

根本原因:SPA中,所有组件的DOM结构,都基于唯一的index.html页面进行呈现,每个组件的样式都会影响到整个index.html页面中的DOM元素

解决:

方法一:为每个组件分配唯一的自定义属性,在编写组件样式时,通过属性选择器来控制样式的作用域

<template>
<div data-v-001> <h1 data-v-001> 这是App.vue组件</h1> <p data-v-001>这是App中的p标签</p>
</div>
</template> <script> </script> <style lang="less">
p[data-v-001]{
color: red;
}
</style>

方法二:vue为style节点提供了scoped属性,从而防止组件之间的样式冲突问题

但如果给当前组件的style的节点添加了scoped属性,则当前组件的样式对其子组件是不生效的,如果想生效,可以使用/deep/深度选择器,vue3.x中推荐 :deep()

/deep/.title{  }  等价于 [data-v-xxx].title 等价于 :deep(title){ }

4、组件的props

封装vue组件时的基本原则:

  • 组件的DOM结构、Style样式尽量复用
  • 组件中要展示的数据,尽量由使用者提供

为了方便使用者为组件提供要展示的数据,vue提供了props的概念

什么是组件的props?props是组件的自定义属性,组件的使用者可以通过props把数据传递到子组件内部,供子组件内部使用

作用:父组件通过props向子组件传递要展示的数据

声明:在封装vue组件时,可以把动态的数据项声明为props自定义属性

(无法使用未声明的props)

<template>
<div data-v-001> <h1 data-v-001> 书名:{{title}}</h1> <p data-v-001>作者:{{author}}</p>
</div>
</template> <script>
export default{
name:'MyArticle',
props:['title','author']
}
</script>

动态绑定props的值:可以使用v-bind属性绑定的形式,为组件动态绑定props的值

props的大小写命名:如果使用camelCase声明props属性的名称,则可以使用:驼峰/短横线的形式为组件绑定属性的值

5、Class和Style绑定

vue允许开发者通过v-bind属性绑定指令,为元素动态绑定class属性的值行内的style样式,来动态操作元素样式

  • 动态绑定HTML的class:可以通过三元表达式,动态的为元素绑定class的类名
<template>
<div> <h3 class="thin" :class="isItalic ? 'italic': ''">MyStyle组件</h3> <button @click="isItalic=!isItalic">Toggle Italic</button>
</div>
</template> <script>
export default{
name:'MyArticle',
data(){//防止一个组件被多次调用时,存在数据的引用关系
return{
isItalic:true,
}
}
}
</script> <style lang="less">
.thin{
font-weight: 200;
}
.italic{
font-style: italic;
}
</style>
  • 数组语法绑定HTML的class

如果元素需要动态绑定多个class类名,可以使用数组的语法格式

<h3 class="thin" :class="[isItalic ? 'italic': '',isDelate ? 'delate': '']">MyStyle组件</h3>
  • 对象语法绑定HTML的class

采用数组语法会导致模板结构臃肿,故使用对象语法进行简化

<h3 class="thin" :class="classObj">MyStyle组件</h3>

<script>
export default{
name:'MyArticle',
data(){
return{
isItalic:true,
classObj:{
isItalic:true,
}
}
}
}
</script>
  • 对象语法绑定内联的style样式
<template>
<div data-v-001> <div :style="{color:active,fontsize:fsize+'px','background-color':bgcolor}"></div>
//不写成驼峰就得用单引号包括,表示是一个字符串的属性
<button @click="isItalic=!isItalic">Toggle Italic</button>
</div> </template> <script>
export default{
name:'MyArticle',
data(){
return{
isItalic:true,
active:'red',
fsize:30,
bgcolor:'pink',
}
}
}
</script>

VueComponent构造函数

  • 组件本质是一个名为VueComponent的构造函数,且不是程序员定义的,由Vue.extend生成的。
  • 调用组件时,Vue解析时会帮我们创建组件的实例对象,即帮我们执行:new VueComponent(options)
  • 注意:每次调用Vue.extend,返回的都是一个个全新的VueComponent

关于this指向:

组件配置中:

data函数、methods中的函数、watch中的函数、computed中的函数,this均是【VueComponent实例对象(vc)】

new Vue()配置中:

data函数、methods中的函数、watch中的函数、computed中的函数,this均是【Vue实例对象(vm)】

一个重要的内置关系:VueComponent.prototype.__proto__==Vue.prototype

让组件实例对象可以访问到Vue原型上的属性、方法。

单页面应用程序(SPA)

一个Web网站中只有唯一的一个HTML页面(所有的功能与交互)

特点:仅在该web页面初始化时加载相应的资源,不会因为用户操作来进行页面的重新加载或跳转

有点:良好的交互体验(不会出现白屏现象)

​ 良好的前后端工作分离模式(后端专注于提供API接口,前端专注于页面的渲染)

​ 减轻服务器的压力(服务器只提供数据,不负责页面合成和逻辑处理)

缺点:首屏加载慢(解决:路由懒加载、代码压缩、CDN加速、网络传输压缩)

​ 不利于SEO(引擎优化) (解决:SSR服务器端渲染)

脚手架—快速创建SPA项目

1、基于vite创建SPA项目

2、基于vue-cli创建SPA项目

vite的基本使用

1、创建vite项目

npm init vite-app 项目名称

cd 项目名称
npm install
npm run dev

2、梳理项目的结构

3、vite项目的运行流程

在工程化项目中,vue要做的事情很单纯,通过main.js把App.vue渲染到index.html的指定区域中

App.vue用来编写待渲染的模板结构

index.html中需要预留一个el区域

main.js把App.vue渲染到index.html所预留的区域中

Vue-cli的基本使用

1、创建cli项目

npm i -g @vue/cli
vue create 项目名称 cd 项目名称
npm run serve

2、查看具体的webpack配置

vue inspect > output.js

组件通讯

组件之间的数据共享的6种方案

组件之间的关系

  • 父子关系
  • 兄弟关系
  • 后代关系

父子组件之间的数据共享

1、父->子共享数据

父组件通过v-bind属性绑定向子组件共享数据。同时,子组件需要使用props接受数据

2、子->父共享数据

子组件通过自定义事件的方式向父组件共享数据,emit传参

3、父<->子双向数据同步

使用v-model指令维护组件内外数据的双向同步

兄弟组件之间的数据共享

4、兄<->弟共享数据

共享方案:EventBus,可以借助第三方包mitt来创建eventBus对象

  • 安装mitt依赖包
npm install mitt@2.1.0
  • 创建公共的EventBus模块
import mitt from 'mitt'
//创建Eventbus的实例对象
const bus=mitt()
//将Eventbus的是实例对象共享出去
export default bus
  • 数据接收方声明自定义事件

调用bus.on('事件名称',事件处理函数)方法注册一个自定义事件

<script>
import bus from 'eventBus.js' export default{
data(){return { count 0}},
created(){
bus.on('',(count)=>{
this.count=count
})
}
}
</script>
  • 数据发送方触发事件

调用bus.emit('事件名称',要发送的数据)方法触发自定义事件

<script>
import bus from 'eventBus.js' export default{
data(){return { count 0}},
methods:{
add(){
this.count++
bus.on('',this.count) }
} }
</script>

后代组件之间的数据共享

5、父<->子孙共享数据

指的是父节点组件向其子孙组件共享数据。此时组件之间的嵌套关系比较复杂,可以使用provideinject实现后代关系组件之间的数据共享

  • 父组件通过provide共享数据
<script>

export default{
data(){return { count 0}},
provide(){
return {
color:this.color
}
} }
</script>
  • 子孙组件通过inject接收数据
<script>

export default{
data(){return { count 0}},
inject:['color'], }
</script>
  • 父节点对外共享响应式数据(provide非响应式)
<script>
import {computed} from 'vue'//从vue中导入computed函数
export default{
data(){return {color:'red'}},
provide(){
return {
//使用computed函数,可以把要共享的数据包装为响应式数据
color:computed(()=>this.color)
}
} }
</script>
  • 子孙节点使用响应式数据

子孙节点必须使用.value的形式进行使用

6、Vuex全局数据共享

总结

ref引用

ref用来辅助开发者在不依赖jQuery的情况下获取DOM元素或组件的引用

每个vue组件实例上,都包含一个$refs对象,里面存储这对应DOM元素或组件的引用,默认情况下,组件里的$refs指向一个空对象

使用ref引用DOM元素

<h1 ref="myh111"> nihao</h1>
<button @click="getRefs">
获取“$refs”引用
</button> <script>
export default {
name:'MyApp',
methods:{
getRefs(){
this.$refs.myh111.style.color='red'
}
}
}
</script>

使用ref引用组件

<h1 ref="myh111"> nihao</h1>
<button @click="getRefs">
获取“$refs”引用
</button> <my-counter ref="countRef"></my-counter> <script>
export default {
name:'MyApp',
methods:{
getRefs(){
this.$refs.countRef.reset()//调用组件内的reset()方法
}
}
}
</script>

控制文本框的按钮的按需切换(文本框自动获得焦点.focus()方法)

组件是异步执行DOM更新的

解决:this.$nextTick(cb) cb回调被延迟到DOM重新渲染完成之后执行,保证cd回调函数可以操作最新的DOM元素

<script>
export default {
name:'MyApp',
methods:{
getRefs(){
this.$nextTick(()=>{
this.$refs.ipt.focus()
})
}
}
}
</script>

mixin混入

components编写mixin.js文件,可以把多个组件共用的配置提取成一个混入对象。

export const mixin={
methods:{
showNmae(){
alert(this.name)
}
}
}
//局部混入
<script>
import {hunhe} from '../mixin'
export default {
name:'MyApp',
data(){
return {
name:''
}
},
mixin:[hunhe],
}
</script> //全局混入
Vue.mixin(xxx)

动态组件

指的是动态切换组件的显示与隐藏。vue提供了一个内置的,专门来实现组件的动态渲染

实现动态组件渲染

<component :is="组件名称"></component>

使用keep-alive保持状态(缓存)

隐藏组件时会将组件在内存中销毁,不会保持最后的状态,可以使用组价保持动态组件的状态

<keep-alive>
<component :is="组件名称"></component>
</keep-alive>

scoped样式

为什么会产生样式类名冲突?

Vue解析组件时,会将所有的style合并,当类名相同时会以后引入的样式为主。

使用scoped解决css样式类名冲突问题,但App组件不适用。

插槽

什么是插槽?

插槽(slot)是vue为组件封装者提供的能力。允许开发者在封装组件时,把不确定的,希望用户指定的部分定义为插槽,(为用户预留的内容的占位符)。

在封装组件时,可以通过<slot></slot>元素定义插槽,从而为用户预留内容占位符

没有预留插槽的自定义内容会被丢弃(Vue不知道将该DOM渲染到何处)

<--header组件!-->
<template>
<div>
<slot></slot>
</div>
</template>
<--引用!-->
<header>
<ul>
<li></li>
<li></li>
</ul>
<--将ul插入header组件!-->
</header>

插槽的默认内容(后备内容)

可以为预留的<slot>插槽提供后备内容(默认内容),如果使用者没有提供内容,则后备内容将会生效

具名插槽

上述定义的是默认插槽,如果在封装组件时需要预留多个插槽节点,则需要为每个<slot>插槽指定具体的name名称,这种带有具体名称的插槽叫做:具名插槽

<slot name=" "></slot>
<slot ></slot> //默认名:default
<--header组件!-->
<template>
<div>
<slot name="center"></slot>
<slot name="footer"></slot>
</div>
</template>
<--引用!-->
<header>
<ul slot="center">
<li></li>
<li></li>
</ul>
<a slot="footer"></a>
</header> <--另一种写法!-->
<header>
<ul slot="center">
<li></li>
<li></li>
</ul>
<template v-slot:header>  
<h1>    
滕王阁序  
</h1>
</template>
</header> <header>
<ul slot="center">
<li></li>
<li></li>
</ul>
<template #header>  
<h1>    
滕王阁序  
</h1>
</template>
</header>

作用域插槽

在封装组件的过程中,可以为预留的<slot>插槽绑定props数据,使得子组件可以向引用传参(数据逆流),这种带有props数据的<slot>叫做:作用域插槽。

<--header组件!-->
<template>
<div>
<slot :games="games"></slot>
</div>
</template> ......
data(){
return{
games:['first','second','third']
}
}
    <header>
<template scope="games">  
<ul>
<li></li>
<li></li>
</ul>
<h1>    
滕王阁序  
</h1>
</template>
</header>

解构作用域插槽的prop

scope是一个对象,那么能否直接使用对象的解构赋值呢?

    <header>
<template scope="{games}">  
<ul>
<li></li>
<li></li>
</ul>
<h1>    
滕王阁序  
</h1>
</template>
</header> <header>
<template slot-scope="{games}">  
<ul>
<li></li>
<li></li>
</ul>
<h1>    
滕王阁序  
</h1>
</template>
</header>

万字血书Vue-Vue进阶的更多相关文章

  1. vue高级进阶( 三 ) 组件高级用法及最佳实践

      vue高级进阶( 三 ) 组件高级用法及最佳实践 世界上有太多孤独的人害怕先踏出第一步. ---绿皮书 书接上回,上篇介绍了vue组件通信比较有代表性的几种方法,本篇主要讲述一下组件的高级用法和最 ...

  2. vue高级进阶( 二 ) 8种组件通信详解

      vue高级进阶( 二 ) 8种组件通信详解 猛兽总是独行,牛羊才成群结队. -------鲁迅 vue组件通信的重要性无需多言...但是你肯定没有全部掌握,所以这第二篇文章应运而生 props和$ ...

  3. Javascript - Vue - vue对象

    vue提供了一整套前端解决方案,可以提升企业开发效率 vue的处理过程 app.js 项目入口,所有请求最先进入此模块进行处理 route.js 由app.js调用,处理路由的分发 controlle ...

  4. Vue - vue.js 常用指令

    Vue - vue.js 常用指令 目录: 一. vuejs模板语法之常用指令 1. 常用指令: v-html 2. 常用指令: v-text 3. 常用指令: v-for 4. 常用指令: v-if ...

  5. 前端开发 Vue Vue.js和Nodejs的关系

    首先vue.js 是库,不是框架,不是框架,不是框架. Vue.js 使用了基于 HTML 的模版语法,允许开发者声明式地将 DOM 绑定至底层 Vue 实例的数据. Vue.js 的核心是一个允许你 ...

  6. [Vue] : Vue概述

    什么是Vue.js Vue.js 是目前最火的一个前端框架,React是最流行的一个前端框架. Vue.js 是前端的主流框架之一,和Angular.js.React.js 一起,并成为前端三大主流框 ...

  7. Property 'validate' does not exist on type 'Element | Element[] | Vue | Vue[]'. Property 'valid...

    使用vue-cli 3.0+Element-ui时候,调用form表单校验时候出现的问题是: Property 'validate' does not exist on type 'Element | ...

  8. Vue Vue.use() / Vue.component / router-view

    Vue.use Vue.use 的作用是安装插件 Vue.use 接收一个参数 如果这个参数是函数的话,Vue.use 直接调用这个函数注册组件 如果这个参数是对象的话,Vue.use 将调用 ins ...

  9. vue & vue router & dynamic router

    vue & vue router & dynamic router https://router.vuejs.org/guide/essentials/dynamic-matching ...

  10. vue & vue router & match bug

    vue & vue router & match bug match bugs solution name must be router https://stackoverflow.c ...

随机推荐

  1. uniapp的下载

    简介 - HBuilderX 文档 (dcloud.net.cn) 下载Hbuiler 直接打开HbuilderX.exe就可以直接使用 可以通过他来创建模板 目录

  2. python在使用过程中安装库的方法

    背景: 在学习python的过程中难免会出现python解释器中没有所需要的库,这时我们就要自行的去安装这些库了:当然如果使用的anaconda集成环境的话在安装python一些依赖环境中会简单不少( ...

  3. ElasticSearch之禁用交换分区

    操作系统将进程加载至内存中执行时,对于当前未使用到的内存页,可能会将相关内存页交换至硬盘上,即swap. 对于性能敏感.时延敏感的应用程序比如ElasticSearch,swap特性会明显影响性能和稳 ...

  4. 在CentOS安装BIND,把所有DNS请求日志转发到syslog服务器去

    在CentOS安装BIND,把所有DNS请求日志转发到syslog服务器去 在vim /etc/named.conf里配置的内容 logging { channel default_debug { f ...

  5. C# 查找PDF页面指定区域中的文本并替换和高亮

    对PDF文档中的内容进行查找时,可针对文档全篇内容获取查找结果,也可在PDF指定页面中的特定范围内(矩形框区域)进行查找,对获取的查找结果可执行文本高亮或替换等操作,本文将对此作相关介绍(附VB.NE ...

  6. CNCF首个云原生多云容器编排项目Karmada正式晋级孵化

    文分享自华为云社区<CNCF首个云原生多云容器编排项目Karmada正式晋级孵化]>,作者:云容器大未来. 近日,云原生计算基金会(CNCF)宣布,CNCF技术监督委员会(TOC)已投票通 ...

  7. 云小课 | SA基线检查—给云服务的一次全面“体检”

    阅识风云是华为云信息大咖,擅长将复杂信息多元化呈现,其出品的一张图(云图说).深入浅出的博文(云小课)或短视频(云视厅)总有一款能让您快速上手华为云.更多精彩内容请单击此处. 摘要: 华为云态势感知( ...

  8. 如何通过appuploader把ipa文件上传到App Store教程步骤​

    iOS APP上架App Store其中一个步骤就是要把ipa文件上传到App Store!​ 下面进行步骤介绍!​ 利用Appuploader这个软件,可以在Windows.Linux或Mac系统中 ...

  9. 企业如何高效平滑迁移数据?火山引擎DataLeap上线整库搬迁解决方案

     更多技术交流.求职机会,欢迎关注字节跳动数据平台微信公众号,回复[1]进入官方交流群   近日,火山引擎大数据研发治理套件DataLeap上线整库搬迁解决方案,包括整库离线同步.整库实时同步两大能力 ...

  10. 一文了解 DataLeap 中的 Notebook

    更多技术交流.求职机会,欢迎关注字节跳动数据平台微信公众号,回复[1]进入官方交流群 概述 Notebook 是一种支持 REPL 模式的开发环境.所谓「REPL」,即「读取-求值-输出」循环:输入一 ...