Vue2、Vue3知识总结---完整版✨

⭐️Vue

Vue 2

是一套用于构建用户界面的框架

Vue 的特性

  • 数据驱动视图Vue2、Vue3知识总结---完整版✨_第1张图片

  • 双向数据绑定

Vue2、Vue3知识总结---完整版✨_第2张图片

  • MVVM

    • MVVM 指的是 Model、View 和 ViewModel,它把每个 HTML 页面都拆分成了这三个部分
      • Model 表示当前页面渲染时所依赖的数据源。
      • View 表示当前页面所渲染的 DOM 结构。
      • ViewModel 表示 vue 的实例,它是 MVVM 的核心。
  • 数据代理

    通过vm对象来代理data对象中属性的操作(读/写)

    • 更加方便的操作data中的数据

    • 基本原理

      • 通过Object.defineProperty()把data对象中所有属性添加到vm上。

      • 为每一个添加到vm上的属性,都指定一个getter/setter。

      • 在getter/setter内部去操作(读/写)data中对应的属性。

Vue监视数据的原理:

    1. vue会监视data中所有层次的数据。

    2. 如何监测对象中的数据?
	通过setter实现监视,且要在new Vue时就传入要监测的数据。
        (1).对象中后追加的属性,Vue默认不做响应式处理
        (2).如需给后添加的属性做响应式,请使用如下API:
        Vue.set(target,propertyName/index,value) 或 
        vm.$set(target,propertyName/index,value)

	3. 如何监测数组中的数据?
		通过包裹数组更新元素的方法实现,本质就是做了两件事:
            (1).调用原生对应的方法对数组进行更新。
            (2).重新解析模板,进而更新页面。

	4.在Vue修改数组中的某个元素一定要用如下方法:
		1 使用这些API:push()、pop()、shift()、unshift()、splice()、sort()、reverse()
		2 Vue.set() 或 vm.$set()
				
		特别注意:Vue.set() 和 vm.$set() 不能给vm 或 vm的根数据对象 添加属性!!!

Vue 的基本使用

  • 使用步骤

    • 1 导入 vue.js 的script 脚本文件
    • 2 在页面中声明一个将被 Vue 所控制的 DOM 区域
    • 3 创建 vm 实例对象
    <!-- 希望 Vue 能够控制下面的这个 div,帮我们在把数据填充到 div 内部 -->
      <div id="app">{{ username }}</div>
    
      <!-- 1. 导入 Vue 的库文件,在 window 全局就有了 Vue 这个构造函数 -->
      <script src="./lib/vue-2.6.12.js"></script>
      <!-- 2. 创建 Vue 的实例对象 -->
      <script>
        // 创建 Vue 的实例对象
        const vm = new Vue({
          // el 属性是固定的写法,表示当前 vm 实例要控制页面上的哪个区域,接收的值是一个选择器
          el: '#app',
          // data 对象就是要渲染到页面上的数据
          data: {
            username: 'zhangsan'
          }
        })
      </script>
    

Vue2、Vue3知识总结---完整版✨_第3张图片

指令

指令 是 Vue 为开发者提供的模板语法,用于辅助开发者渲染页面的基本结构

按照不同用途可分为:

1 内容渲染指令

  • v-text

    • 示例:

      性别:

    • ❗️v-text 指令会覆盖元素内默认的值
  • ⭐️{{ }}

    • 性别:{{ gender }}

    • 不会覆盖元素内默认的值
  • v-html

    • 把包含 HTML 标签的字符串渲染为页面的 HTML 元素

    • ❗️v-html有安全性问题

      • (1).在网站上动态渲染任意HTML是非常危险的,容易导致 XSS 攻击。

      • (2).一定要在可信的内容上使用v-html,不要用在用户提交的内容上!(和eval()有点像)

  • v-cloak

    • 1.本质是一个特殊属性,Vue实例创建完毕并接管容器后,会删掉v-cloak属性。
    • 2.使用css(display:'none')配合v-cloak可以解决网速慢时页面展示出{{xxx}}的问题。
  • v-once

    • 1.v-once所在节点在初次动态渲染后,就视为静态内容了。
    • 2.以后数据的改变不会引起v-once所在结构的更新,可以用于优化性能。
  • v-pre

    • 1.跳过其所在节点的编译过程。
    • 2.可利用它跳过:没有使用指令语法、没有使用插值语法的节点,会加快编译。

2 属性绑定

  • v-bind:

    • v-bind: 指令可以简写为 :

    • 动态绑定 class / style / checked

      • :checked="isChecked"

        • isChekced是 Boolean值
      • 字符串:

        • 适用于:类名不确定,要动态获取。
        • :class="classes"
          • classes是一个计算属性
      • 对象语法:

        • 要绑定多个样式,个数确定,名字也确定,但不确定用不用

        • :class="{active:isActive}"

        • :class="{active:isActive,line:isLine}"

        • class="title":class="{active:isActive,line:isLine}"

      • 数组语法:

        • 要绑定多个样式,个数不确定,名字也不确定。
        • :style='[styleobj,overridingStyles]'

    使用 JavaScript 表达式 的运算

    Vue2、Vue3知识总结---完整版✨_第4张图片

3 事件绑定

  • v-on :简写形式:@

    • eg: @click=‘addCount’ @keyup=‘count += 1’
  • 需要在 methods 节点中进行声明
    Vue2、Vue3知识总结---完整版✨_第5张图片

  • 事件参数对象

    • $(event) 指原生的事件参数对象 event

    • 绑定事件并传参

  • 事件修饰符

    事件修饰符 说明
    .prevent 阻止默认行为(eg:阻止 a 链接的跳转、阻止表单的提交等)
    .stop 阻止事件冒泡
    .capture 以捕获模式触发当前的事件处理函数
    .once 绑定的事件只触发一次
    .self 只有在 event.target 是当前元素自身时触发事件处理函数
  • 按键修饰符

    • .enter
    • .delete
    • .esc
    • .space
    • .up .down .left .right
    • tab 换行 (必须配合 keydown去使用)
  • 可以执行少量代码 count++

  • 可以写函数传参(可以获取事件对象,没写参数默认有,写参数要 (a,$event)

    • 给调用函数+个()eg:@change="handelClick()"
    • 如果只有一个 e 不加 ()
    • e.target.value/checkded

4 双向绑定

  • v-model

    • 实现表单数据的双向绑定

    • 用于获取表单(输入类)的数据

    • 场景

      • 表单(value / checked)、全选(状态在 computed )反选(状态在 data )
    • 收集表单数据:
          若:<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 修饰符

      修饰符 作用 示例
      .number 自动把用户输入的值转为数值类型
      .trim 自动过滤用户输入 的首尾空白字符
      .lazy 在“change”时而非“input”时更新

5 条件渲染

  • 条件渲染指令用来辅助开发者按需控制 DOM 的显示与隐藏

    • v-if

      • 这是被 v-if 控制的元素

      • 会动态地创建或移除 DOM 元素

        • v-elsev-else-if=“ ”
        • 必须相邻
      • 只能在与 v-if 平级的时候使用

        优秀
        良好
        一般
      • 移除时 dom 不存在

    • v-show

    • 这是被 v-show 控制的元素

      • 会动态为元素添加或移除 style=“display: none;” 样式
      • 移除时 dom 存在
    v-if v-show
    动态地创建或移除 DOM 元素 动态为元素添加或移除 style="display: none;"样式
    支持多条件显示 不支持多条件显示
    有更高的开销 有更高的初始渲染开销
    使用场景:切换频率较低、判断条件较多的场景 使用场景:非常频繁地切换

6 列表渲染

  • v-for

    • 基于一个数组来循环渲染一个列表结构
    • 需要使用 item in items 形式的特殊语法
    <tr v-for="(item, index) in list" :key="item.id">
      <td>{{ index }}</td>
      <td>{{ item.id }}</td>
      <td>{{ item.name }}</td>
    </tr>
    
    • 1 用于 循环 数组 (item,index) in array
    • 2 用于循环 对象 (item,key) in obj
    • 3 用于循环 数字 item in num
    • 使用 key 维护列表的状态
      • Vue 复用已存在的DOM元素提升渲染性能 但导致有状态的列表无法被正确更新
      • key 注意事项
        • key 的值只能是字符串或数字类型
        • key 的值必须 具有唯一性
        • 建议把数据项的 id 属性值作为 key 的值
        • 使用 index 的值当做 key 的值没有意义( index 不具唯一性)
        • 建议使用 v-for 指令时要指定 key 的值(既提升性能,又防止列表状态紊乱)
    • label 的 for 属性
      • :for="'cb' + item.id" input里面 :id="'cb' + item.id"

过滤器

过滤器(Filters)是 vue 为开发者提供的功能,常用于文本的格式化。本质是 js 函数

  • 过滤器放在 js 表达式的尾部 由“管道符”进行调用

    • 插值表达式
      • message 的值是:{{ message | capi }}

      • 不能给属性用,直接“ ”
    • v-bind 属性绑定
  • 定义过滤器

    • 在创建 vue 实例期间,可以在 filters 节点中定义过滤器

      filters: {
          // 注意:过滤器函数形参中的 val,永远都是“管道符”前面的那个值
          capi(val) {
            // 字符串有 charAt 方法,这个方法接收索引值,表示从字符串中把索引对应的字符,获取出来
            // val.charAt(0)
            const first = val.charAt(0).toUpperCase()
            // 字符串的 slice 方法,可以截取字符串,从指定索引往后截取
            const other = val.slice(1)
            // 强调:过滤器中,一定要有一个返回值
            return first + other
          }
        }
      
    • 私有过滤器

      在 filters 节点下定义的过滤器,称为“私有过滤器”,因为它只能在当前 vm 实例所控制的 el 区域内使用。

    • 全局过滤器

      // 使用 Vue.filter() 定义全局过滤器
          Vue.filter('capi', function (str) {
            const first = str.charAt(0).toUpperCase()
            const other = str.slice(1)
            return first + other + '~~~'
          })
      
  • 连续调用多个过滤器

    • message 的值是:{{ message | capi | maxLength }}

  • 过滤器传参

    • 本质是 js 函数

      <p>{{ message | filterA(arg1,arg2)}</p>
      
      Vue.filter('filterA',(mesg,arg1,arg2)=>{})
      
  • 兼容性

    • 仅在 Vue1、2中受支持
    • vue3 不支持
      • 官方建议使用 计算属性方法 代替过滤器功能
      • 参考

侦听器

watch 侦听器允许开发者监视数据的变化,从而针对数据的变化做特定的操作。

当被监视的属性变化时, 回调函数自动调用, 进行相关操作

  • 1 在 watch 节点进行声明
const vm = new Vue({
  el: '#app',
  data: {
    username: 'admin'
  },
  // 所有的侦听器,都应该被定义到 watch 节点下
  watch: {
    // 侦听器本质上是一个函数,要监视哪个数据的变化,就把数据名作为方法名即可
      
    // 新值在前,旧值在后
    username(newVal) {
      if (newVal === '') return
      // 1. 调用 jQuery 中的 Ajax 发起请求,判断 newVal 是否被占用!!!
      $.get('https://www.escook.cn/api/finduser/' + newVal, function (result) {
        console.log(result)
      })
    }
  }
})
  • 2 使用 watch 检测用户名是否可用

    监听 username 值的变化,并使用 axios 发起 Ajax 请求,检测当前输入的用户名是否可用:

    watch: {
    // 监听 username 值的变化
        async username(newVal) {
            if (newVal === '') return
            // 使用 axios 发起请求,判断用户名是否可用
            const { data: res } = await axios.get('https://www.escook.cn/api/finduser/' + newVal)
    	} 
    }
    
  • 3 immediate选项

    默认情况下,组件在初次加载完毕后不会调用 watch 侦听器。如果想让 watch 侦听器立即被调用,则需要使 用 immediate 选项。

    watch: {
       // 让被监听的对象指向一个 配置对象
    username: {
    // handler 是固定写法,表示当 username 的值变化时,自动调用 handler 处理函数
        handler: async function (newVal) {
            if (newVal === '') return
            const { data: res } = await axios.get('https://www.escook.cn/api/finduser/' + newVal)
            console.log(res)
    },
    // 表示页面初次渲染好之后,就立即触发当前的 watch 侦听器
    immediate: true
    } }
    
  • 4 deep 选项

    如果 watch 侦听的是一个对象,如果对象中的属性值发生了变化,则无法被监听到。此时需要使用 deep 选项

    • 在上面的基础上加一个 deep:true
  • 5 监听对象单个属性的变化

    watch:{
        info: {
          handler(newVal) {
            console.log(newVal)
          },
          deep:true,
        }
        // 如果要侦听的是 子属性 的变换,则必须包裹一层单引号
        'info.username'(newVal) {
          console.log(newVal)
        }
        // 配置对象
        'info.username':{
           async handler(newVal){
              const { data:res } = await axios.get('https://www.escook.cn/api/finduser/' + newVal.username)
              console.log(res)
            }
        }
    }
    

监视的属性必须存在,才能进行监视!!

  • 应用场景

    • 本地存储

      subjectList() { // 要侦听的属性
          localStorage.setItem('scoreMsg', JSON.stringify(this.subjectList))
          }
      
    • 当监听 对象数组 时,数组的长度变化时,不用 deep 也可以,但是监听不到对象内部的 变化

    • 数据变化时,发起 ajax 请求

计算属性

计算属性指的是通过一系列运算之后,最终得到一个属性值

  • 个动态计算出来的属性值可以被模板结构或 methods 方法使用。

    <div id="app">
        <!-- 专门用户呈现颜色的 div 盒子 -->
        <!-- 在属性身上,: 代表  v-bind: 属性绑定 -->
        <!-- :style 代表动态绑定一个样式对象,它的值是一个 {  } 样式对象 -->
        <!-- 当前的样式对象中,只包含 backgroundColor 背景颜色 -->
        <div class="box" :style="{ backgroundColor: rgb }">
          {{ rgb }}
        </div>
        <button @click="show">按钮</button>
    </div>
    
      <script>
        // 创建 Vue 实例,得到 ViewModel
        var vm = new Vue({
          el: '#app',
          data: {
            // 红色
            r: 0,
            // 绿色
            g: 0,
            // 蓝色
            b: 0
          },
          methods: {
            // 点击按钮,在终端显示最新的颜色
            show() {
              console.log(this.rgb)
            }
          },
          // 所有的计算属性,都要定义到 computed 节点之下
          // 计算属性在定义的时候,要定义成“方法格式”
          computed: {
            // rgb 作为一个计算属性,被定义成了方法格式,
            // 最终,在这个方法中,要返回一个生成好的 rgb(x,x,x) 的字符串
            rgb() {
              return `rgb(${this.r}, ${this.g}, ${this.b})`
            }
          }
        });
    
        console.log(vm)
      </script>
    
    • 所有的计算属性,都要定义到 computed 节点之下
    • 计算属性在定义的时候,要定义成“方法格式”
  • 计算属性的特点

    • 1 虽然计算属性在声明的时候被定义为方法,但是计算属性的本质是一个属性
    • 2 计算属性会缓存计算的结果,只有计算属性依赖的数据变化时,才会重新进行运算
  • 好处:

    • 代码复用
    • data变化,计算属性也变化
  • 应用场景

    • 反选
      • return this.list.every(item => item.checked === true)
    • total
      • return this.subjectList.reduce((pre, current) => (pre += current.score), 0)
全选:v-model="allChecked" 反选:computed

computed: {
    allChecked: {
      get() {
        return this.list.every(item => item.checked === true)
      },
      set(allChecked) {
        this.checked = !allChecked
        this.list.forEach(item => (item.checked = allChecked))
      }
    }
  }
计算属性:
    1.定义:要用的属性不存在,要通过`已有属性`计算得来。
    
    2.原理:底层借助了Objcet.defineproperty方法提供的getter和setter。

    3.get函数什么时候执行?
        (1).初次读取时会执行一次。
        (2).当依赖的数据发生改变时会被再次调用。

    4.优势:与methods实现相比,内部有缓存机制(复用),效率更高,调试方便。
    
    5.备注:
        1.计算属性最终会出现在vm上,直接读取使用即可。
        2.如果计算属性要被修改,那必须写set函数去响应修改,且set中要引起计算时依赖的数据发生改变。

计算属性 vs 侦听器

1 计算属性侧重于监听多个值的变化,最终计算并返回一个新值

2 侦听器侧重于监听单个数据的变化,最终执行特定的业务处理,不需要有任何返回值

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

axios

axios 是一个专注于网络请求的库

  • 调用 axios 方法得到的返回值是 Promise对象

  • const result = axios({
        method:'GET',
        url:'',
      	// URL 中的查询参数 GET
        // params:{},
        // 请求体参数 POST
        // data:{}
    })
    result.then(res=>{
        console.log(res.data)
    })
    
    $('#btnPost').on('click',async ()=>{
        const { data:res } = await axios({
            method:'POST',
            url:'',
            data:{
                name:'zs',
                age:20
        }
    }) // 返回的是数据对象 可以解构单独拿出 data 把 data 重命名为 res
    })
    

Vue2、Vue3知识总结---完整版✨_第6张图片

如果调用某个方法的返回值是 Promise 实例,则前面可以添加 await

await 只能在被 async “修饰”的方法中

用 jQuery 可以发起 $.ajax() $.get() $.post() 请求

axios:axios() axios.get() axios.post() axios.delete() axios.put() axios.patch()

axios.get()

$('#btnPost').on('click',async ()=>{
    const { data:res } = await axios.get('url',{params:{id:1}})
})

axios.post()

$('#btnPost').on('click',async ()=>{
    const { data:res } = await axios.post('url',{name:'zs',gender:'女'}) // axios.post()里面的请求体直接写数据对象
})

组件中发起axios 请求,不用每个组件都要导入 axios,在 main.js 导入,变成 Vue内置的成员

// main.js
import axios from 'axios'

// 配置请求根路径
axios.defaults.baseURL = 'http://www.itcbc.com:3006'

// 把 axios 挂载到 Vue.prototype上,供每个组件的实例直接使用
// 缺点: 不利于接口的 复用
Vue.propotype.$http = axios

// 组件中
methods:{
    async getBooks(){
        const {data : res} = await this.$http.get('http://www.itcbc.com:3006/api/getbooks')
    }
}

$mount方法

const vm = new Vue({
  data: {
    username: 'admin'
  }
})

vm.$mount('#app')

vue/cli

vue-cli 是 Vue.js 开发的标准工具。它简化了程序员基于 webpack 创建工程化的 Vue 项目的过程

下载: npm i -g @vue/cli 查找安装: vue -V

  1. 在指定目录的 终端下 创建指定名称的项目

    • vue create demo-first

    • 项目名称不能有空格、中文、大写字母
      Vue2、Vue3知识总结---完整版✨_第7张图片

    • 创建冻结 按 ctrl + c

    • 创建成功 cd 项目名称 npm run serve 不要关掉终端

  2. vue 项目中 src 目录的构成

  • assets 放:图片、css 样式等静态资源

  • components :放封装好的 组件

  • main.js :是项目的入口文件,整个项目的运行,要先执行 main.js

![在这里插入图片描述](https://img-blog.csdnimg.cn/721187076eeb40748414a0f0fa998f01.png#pic_center)
  • app.vue:是项目的根组件(render渲染的组件就是根组件)
  1. vue 项目运行流程

    • 通过 main.js 把 App.vue 渲染到 HTML 页面

单页面应用程序

单页面应用程序(英文名:Single Page Application)简称 SPA,顾名思义,指的是一个 Web 网站中只有唯一的一个 HTML 页面,所有的功能与交互都在这唯一的一个页面内完成。

vue组件

组件是对 UI 结构的复用

组件化开发

组件化开发指的是:根据封装的思想,把页面上可重用的 UI 结构封装为组件,从而方便项目的开发和维护。

组件的后缀名是 .vue

一个重要的内置关系

  • VueComponent.prototype.proto === Vue.prototype
为什么要有这个关系
  • 让组件实例对象(vc)可以访问到 Vue原型上的属性、方法。
  • this.$refs.xx(ref=xx).属性/方法()

定义组件

组成部分:
  • 1 template -> 组件的模板结构(必须包含

    • template 中只能包含唯一的根节点
  • 2 script -> 组件的 JavaScript 行为

组件配置中: data函数、methods中的函数、watch中的函数、computed中的函数 它们的this均是【VueComponent实例对象】

new Vue(options)配置中: data函数、methods中的函数、watch中的函数、computed中的函数 它们的this均是【Vue实例对象】。

使用组件

  • 1 使用 import 语法导入需要的组件
    • @ 表示定位到 src
    • import MyCount from 'xxx'
  • 2 使用 components 节点注册组件
  • 3 以标签的形式使用刚才注册的组件
组件间的父子关系
  • 组件封装之后,彼此之间是相互独立的,不存在父子关系
  • 在使用组件的时候,根据彼此的嵌套关系构成 父子、兄弟关系
私有组件
  • 使用 components 注册的是 私有组件
  • 在组件 A 的 components 节点下,注册了组件 F。 则组件 F 只能用在组件 A 中;不能被用在组件 C 中。
  • component:{ MyCount }
  • ⭐️component:{ 'my-count', MyCount }
注册全局组件
  • 在 vue 项目的 main.js 入口文件中,通过 Vue.component() 方法,可以注册全局组件。
    • 1 import
    • 2 Vue.component('MyCount',MyCount)

组件的 name 会显示在 devtools 上

组件的 props

props 是组件的自定义属性,在封装通用组件的时候,合理地使用 props 可以极大的提高组件的复用性

exports default{
	props:['自定义属性A''自定义属性B''...'],
    data(){
        return {}
    }
}
  • props 是只读的

    • 修改:把 props 的值 转存 到 data 中,data 中的数据都是可读写的

    • 不要直接在 子组件里修改 props 的值 (会报错,父组件没跟着变)

      props:['init'],
      data(){
          return{
              count:this.init
          }
      }
      
  • props 的 default 默认值

    • props:{ init: { default: 0 }}

    • 用户没传 init 的值时,default 的值生效

    • 对象或数组默认值必须从一个工厂函数获取

      default:function() {
          return {message:'hello'}
      }
      
  • type 值类型

    • eg:type: Number
    • :init="9" v-bind: 加上 js 的数字
    • 写在 props 里面
    • props:{name:String}
  • required 必填项

    • required: true

使用:

组件之间的样式冲突问题

默认情况下,写在 .vue 组件中的样式会全局生效,因此很容易造成多个组件之间的样式冲突问题。

  • 根本原因

    • 1 单页面应用程序中,所有组件的 DOM 结构,都是基于唯一的 index.html 页面进行呈现的
    • 2 每个组件中的样式,都会影响整个 index.html 页面中的 DOM 元素
  • 解决

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

      <style> .container[data-v-0001]{ border: 1px solid red;} </style>
      
    • 2 style 的 scoped 属性

      • 防止组件之间的样式冲突问题
      • 则当前组件的样式对其子组件是不生效的
    • 3 /deep/ 样式穿透

      • 让某些样式对子组件生效
  • 当使用第三方组件库的时候,如果有修改第三方组件默认样式的需求,需要用到 /deep/

    Vue2、Vue3知识总结---完整版✨_第8张图片

组件的生命周期

生命周期

生命周期(Life Cycle)是指一个组件从创建 -> 运行 -> 销毁的整个阶段,强调的是一个时间段

生命周期函数

是由 vue 框架提供的内置函数,会伴随着组件的生命周期,自动按次序执行,强调的是时间点

  • 组件生命周期函数的分类

    • 组件创建阶段、组件运行阶段
      Vue2、Vue3知识总结---完整版✨_第9张图片

    • 生命周期图示
      Vue2、Vue3知识总结---完整版✨_第10张图片

  • beforeCreate()

    • 创建阶段的第一个生命周期函数
    • 组件的 props/data/methods 尚未被创建,都处于 不可用 状态
  • ⭐️created()

    • 组件的 props/data/methods 已创建好,都处于 可用 状态,但是组件的模板结构未生成
    • 在里面调用 methods 方法,请求服务器的数据,并且,把请求到的数据,转存到 data 中,供 template 使用
    • 有些bus.$on()写在 created 里面
  • beforeMount

    • 浏览器还没当前组件的 DOM结构
  • ⭐️mounted

    • 已渲染 HTML,第一次取到 DOM 结构
    • 启动定时器绑定自定义事件订阅消息等【初始化操作】
  • beforeUpdate

    • 将要 根据变化、更新后的数据,重新渲染组件的模板结构
  • ⭐️updated

    • 已根据最新的数据,完成了组件 DOM 结构 的重新渲染
    • 当数据变化之后,为了能够操作到最新的 DOM 结构,必须把代码写到 updated 生命周期函数中
    • 但是一般不在这里做什么,因为一个属性变化就会触发 updated
  • beforeDestroy

    • 尚未销毁组件,还处于 正常工作状态
    • 清除定时器解绑自定义事件取消订阅消息等【收尾工作】
  • destroyed

    • 组件已被销毁,DOM 结构已被完全移除
    • 销毁后自定义事件会失效,但原生DOM事件依然有效。
    • 一般不会在beforeDestroy操作数据,因为即便操作数据,也不会再触发更新流程了。
      Vue2、Vue3知识总结---完整版✨_第11张图片
⭐️组件之间的数据共享

1 父组件向子组件共享数据

  • 需要使用自定义属性

Vue2、Vue3知识总结---完整版✨_第12张图片

  • 也就是 使用自定义属性的方法

2 子组件向父组件共享数据

  • 使用自定义事件(以传参的形式 去共享数据)
  • 父:函数
    • 函数接收数据
  • 子:props:[‘函数名称’]
    • 调用函数,传递参数数据

Vue2、Vue3知识总结---完整版✨_第13张图片

3 兄弟组件之间的数据共享

  • 在 vue2 中,兄弟组件之间的数据共享的方案是 EventBus

  • EventBus 的使用步骤

    • 1 创建 eventBus.js 模块,并向外共享一个 Vue 的实例对象
    • 2 在数据发送方,调用 bus.**$emit(**'事件名称', 要发送的数据) 方法触发自定义事件
    • 3 在数据接收方,调用 bus.**$on**('事件名称', 事件处理函数) 方法注册一个自定义事件
    • bus.$off('xxx')解绑

Vue2、Vue3知识总结---完整版✨_第14张图片

4 ⭐️全局事件总线:任意组件间通信

  • main.js

    • 在vue 实例beforeCreate(){ Vue.prototype.$bus = this}
  • 发送方

    • this.$bus.$emit('deleteTodo', 参数)
  • 接收方

     mounted() {
     this.$bus.$on('checkTodo', this.checkTodo)
    this.$bus.$on('deleteTodo', this.deleteTodo)
      },
          
      beforeDestroy() {
        this.$bus.$off('checkTodo')
        this.$bus.$off('deleteTodo')
      }
    

5 消息订阅与发布 实现任意组件间通讯

使用步骤:

  1. 安装pubsub:npm i pubsub-js

  2. 引入: import pubsub from 'pubsub-js'

  3. 接收数据:A组件想接收数据,则在A组件中订阅消息,订阅的回调留在A组件自身。

    methods(){
      demo(data){......} =》或者写在回调函数里
    }
    ......
    mounted() {
      this.pid = pubsub.subscribe('xxx',this.demo) //订阅消息 (msgName,data)=>{...} 写箭头函数
    }
    beforeDestroy(){ pubsub.unsunscribe(this.pid)}    
    
  4. 提供数据:pubsub.publish('xxx',数据)

  5. 最好在beforeDestroy钩子中,用PubSub.unsubscribe(pid)去取消订阅。

ref 引用

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

每个 vue 的组件实例上,都包含一个 $refs 对象,里面存储着对应的 DOM 元素或组件的引用。

默认情况下, 组件的 this.$refs 指向一个空对象。

  • 使用 ref 引用 DOM 元素

Vue2、Vue3知识总结---完整版✨_第15张图片

  • 使用 ref 引用组件实例

Vue2、Vue3知识总结---完整版✨_第16张图片

  • ref=' ' 写在 组件使用标签上

  • 引用到组件的实例后,就可以调用组件上的 methods 方法

  • 控制文本框和按钮的按需切换

    通过布尔值 inputVisible 来控制组件中的文本框与按钮的按需切换。

    Vue2、Vue3知识总结---完整版✨_第17张图片

  • 让文本框自动获得焦点

    当文本框展示出来之后,如果希望它立即获得焦点,则可以为其添加 ref 引用,并调用原生 DOM 对象的 .focus() 方法即可。

    Vue2、Vue3知识总结---完整版✨_第18张图片

  • this.$nextTick(cb) 方法

    组件的 $nextTick(cb) 方法,会把 cb 回调推迟到下一个 DOM 更新周期之后执行。

    即等组件的 DOM 更新完成之后,再执行 cb 回调函数。从而能保证 cb 回调函数可以操作到最新的 DOM 元素。
    Vue2、Vue3知识总结---完整版✨_第19张图片

@ 从 src 源目录从外往里找

❗️一个重要的内置关系:

VueComponent.prototype.__proto__ === Vue.prototype

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

动态组件

动态组件指的是动态切换组件的显示与隐藏。

动态组件的渲染

vue 提供了一个内置的 组件,专门用来实现动态组件的渲染。

data(){ // 函数 避免组件被复用时,数据存在引用关系。
    return {comName:'Left'}
}

<componet :is="comName"></componet>

<button @click="comName = 'Left'">切换 Left 组件</button>
<button @click="comName = 'Right'">切换 Right 组件</button>
使用 内置的 keep-alive 保持状态

解决默认情况下,切换动态组件时无法保持组件的状态的问题。

<keep-alive>
	<component :is="comName"></component>
</keep-alive>
keep-alive 对应的生命周期函数
  • 当组件被缓存时,会自动触发组件的 deactivated 生命周期函数。
  • 当组件被激活时,会自动触发组件的 activated 生命周期函数。
    • 当组件第一次被创建是,即会触发created 也会触发 actived
    • 当组件被激活,只会触发 actived,不再触发 created,因为组件没有被重新创建
keep-alive 的 include 属性

include 属性用来指定:只有名称匹配的组件会被缓存。多个组件名之间使用英文的逗号分隔:

  • 与 include 相对的是 exclude(指定哪些组件不需要被缓存)只能二选一
<keep-alive include="MyLeft,MyRight">
    <component :is="comName"></component>
</keep-alive>

组件的name属性:

当提供了 name 属性之后,组件的名称,就是 name 属性的值

export default{
    name:'MyRight'
}

对比:

  • name
    • 1 调试的时候 出现的 组件名称
    • 2 与 结合 指定被缓存与不被缓存
  • 注册名称
    • 应用场景:以标签的形式,把注册好的组件,渲染和使用到页面结构之中

mixin(混入)

可以把多个组件共用的配置提取成一个混入对象

独立的 js 文件

使用:

1 定义混合

export const xxx = {
    data(){...}
	methods(){...}
	...
}
export const yyy = {
data(){...}
methods(){...}
...
}

2 使用混合

  • 全局混入
    • 在 main.js 中 Vue.mixin(xxx)
  • 局部混入 // App.vue or 某一组件中
    • import {xxx,yyy} from '/mixin'
    • mixins:[xxx,yyy]

插件

独立的 js 文件

// 1 定义插件 plugins.js
export default {
    install(Vue,x,y,z)
    // 1. 添加全局过滤器
    Vue.filter('mySlice',function(value){
        return value.sclice(0,4)
    })
    
    // 2. 添加全局指令
    Vue.directive('fbind',{bind(el,binding){ el.value = binding.value},
	insert(el,binding){el.focus()},update(el,binding){el.value = 		binding.value}
	})

    // 3. 配置全局混入(合)
    Vue.mixin({data(){ return {x:100,y:200 }}})

    // 4. 添加实例方法
    Vue.prototype.$myMethod = function () {...}
    Vue.prototype.$myProperty = xxxx
                                           
    // 5. 添加全局组件
    Vue.component('myButton',{})                                       
}

// 2 引入插件 main.js
import myBtn from '@/plugin/plugins.js'
// 3 使用自定义插件
<my-button/>

插槽

插槽(Slot)是 vue 为组件的封装者提供的能力。允许开发者在封装组件时,把不确定的、希望由用户指定的部分定义为插槽。

可以把插槽认为是组件封装期间,为用户预留的内容的占位符。

Vue2、Vue3知识总结---完整版✨_第20张图片

基础用法: