Vue笔记

Vue3

基本介绍

  • 服务器渲染造成前后端不分离。model(数据)views(视图)。
  • Rest风格服务器,只返回JSON数据。由前端将JSON数据解析并展示成网页。传统的方式通过操作DOM生成网页,麻烦且性能不好。
  • MVVM (model — view — view model) view model视图模型,负责将model 和 views建立联系。模型发生变化时自动更新视图,也可以通过视图操作模型。
  • 声明式的,即结果导向。告诉vue我想要什么(即声明),vue会自动生成代码。
  • 组件化编程。网页中的每一个模块都可以称为一个组件,提高代码复用性,提高开发效率。
  • 渐进式。可以局部使用组件,不影响原来的代码。
  • 不兼容IE

基本使用

  • 在Vue3中,组件就是一个普通的JS对象。通过组件创建组件实例,即组件是组件实例的模板。通过组件实例操作虚拟DOM。
  • 创建实例,创建应用实例,将应用挂载在页面中的元素上,该元素就成为根元素。(应用指整个网页项目,组件指网页中的一部分)
  • data方法返回一个对象,对象中的属性会自动添加到组件实例中。在模板中可以直接访问组件实例中的属性
  • 定义模板的方式
    • 在组件中通过template属性定义(优先级更高)
    • 直接在网页的元素中定义(基本不用)
    • 通过render() 直接渲染(通常不用)
  • 子组件的使用流程
    • 封装定义子组件并导出
    • 在要用到子组件的文件中导入,在组件中注册子组件,在模板中用标签添加子组件。
  • 引入的子组件最好重命名为小写,因为浏览器解析时会将标签全部转换为小写,之后才轮到vue解析
  • template用字符转的形式编写模板,在项目运行时在浏览器中被编译为JS的函数,其次编写体验极差。为了解决这个问题,Vue提供了单文件组件SFC。
  • vue文件用来编写单文件组件,但是浏览器不识别,所以需要先用构建工具打包。单文件组件的模板会在打包时被构建工具转换为函数,减少了浏览器的负担。 @vitejs/plugin-vue
  • 自动创建项目 npm init vue@latest
  • 一般应用实例上只关联一个根组件。
data 响应式
  • data用来指定实例对象中的响应式属性(包括数组和对象)

  • 组件实例是一个代理对象 Proxy

  • 在data中,this就是当前的组件实例,如果使用箭头函数,则无法使用this,但是会将组件实例作为第一个参数传入。所以不推荐箭头函数。

  • data会返回一个对象,vue对该对象进行代理,从而将其转换为响应式数据。

  • 注意:直接向组件实例中添加的属性不是响应式数据 this.arrt = ‘xxx’,data返回的对象中的数据才是。

  • 对代理对象的读写都是对被代理对象的读写。

  • 可以为代理对象设置handle参数,该参数中由get和set方法。在vue中,读取属性时,get返回值之前做一个跟踪读取该属性的对象。修改属性时,set返回值之前调用trigger让所有使用该属性的对象做出对应的修改。

  • vm.$data是实际的代理对象。通过vm可以直接访问$data属性。

  • 深层响应式对象。在构建响应式对象时,同时将对象中的属性做成响应式的。

  • 要想更改为浅层响应式对象 使用 shallowReactive。浅层响应式对象只有返回对象的根对象会响应。(很少用)

  • 建议将后期使用的属性也添加到data返回 的对象中,值先设置为null,不要通过 this.$data.xxx添加属性。

methods
  • 用来指定实例对象中的方法。是一个对象,可以定义多个方法,最终都会被挂载到组件实例上。
  • methods对象中的函数的this会自动被绑定为组件实例。箭头函数例外。
computed 计算属性
  • 计算属性相当于为实例对象的属性设置getter和setter。虽然是函数的形式,但是不用加() 即可调用。
  • 与methods的区别在于 只在其依赖的响应式数据(即为ref或reactive创建的)发生变化时才会重新执行,会对数据进行缓存。methods中的 方法每次组件重新渲染都会调用。
  • 与data的区别在于,通过方法返回属性值,可以编写一定的逻辑。
  • 也会被挂载到组件实例中。
  • 在计算属性的getter中,尽量只编写读取相关的而逻辑。不要编写产生产生作用的代码。
  • set在计算属性被修改时调用。不建议设置setter。
  • 计算属性的返回值是ref对象,即响应式数据。并且计算属性会自动追踪响应式依赖,依赖更新时,计算属性同时更新。
组合式API
  • setup中的变量可以通过返回值暴露
  • 在组合式api中声明的变量时普通变量,不是响应式的。
  • 可以通过reactive函数创建响应式对象。reactive中只能传对象,不能传字面量。value cannot be made reactive. 可以使用ref代替reactive解决该问题。ref将值包装为对象,通过.value才能访问到原来的值,在template中不用.value也能访问到,因为ref顶层对象会被自动解包(自动加.value)。
  • reactive函数 生成指定对象的深层响应式代理。
模板语法
  • 插值语法{{}}中,只能使用表达式,就是有返回值的语句
  • 插值实际上就是在修改元素的textContent,不会解析标签
  • app.config.globalProperties 添加全局变量
指令
  • 指令,为标签设置的一些特殊属性,控制标签如何显示内容。
  • v-text 将表达式的值作为元素的textContent插入,作用同{{}}。使用指令时,不需要{{}}
  • v-html 将表达式的值作为元素的innerHTML插入,有XSS注入风险。
  • v-bind 为标签动态设置属性。可以简写为:
  • 布尔值属性可以为变量设置true(有该属性)和false(没有该属性)
  • v-show 设置一个元素是否显示。通过display: none 实现
  • v-if 设置一个元素是否显示(懒加载)。直接删除DOM中的元素。可以加到 标签中,而DOM中值显示内容,不显示template标签
  • v-show和v-if的区别。v-show通过css实现,切换时不涉及到重新渲染,性能较高,但是初始化时对所有组件重新渲染,初始化的性能交叉。v-if会重新渲染,性能较差,初始化性能更高。
  • v-for 动态添加时,旧结构和新结构按顺序对比。会造成元素错位。指定属性解决该问题。 :key = “对象自身的唯一标识”。对key相同的对比。
style
  • scoped 当前组件生效。vue会自动为组件的所有元素生成一个随机的自定义属性 data-v-xxxxxxxx,所有的选择器都会添加[data-v-xxxxxxxx] 成为属性选择器。并将该随机属性添加到子组件的单根元素上。
  • 深度选择器 :deep(div) 子组件的div也会受影响。
  • 全局选择器 :global(div) 所有的div。
  • module 自动对模块中的类名进行hash化确保类名唯一性。 $style.类名 使用
props
  • 子组件中的 数据通常不会在子组件中直接定义,而是在创建组件实例时确定,即在父组件中定义。
  • 父组件可以用props将数据传递给子组件
  • 使用
    • 现在子组件中定义props, defineProps([]) 宏指令
    • 在创建组件实例时传入数据
  • 父组件通过props传给子组件的数据是只读的(单向数据)。可以通过在ref中传入对象的方式实现双向数据。
  • props复杂配置 type,required,default,validator等查看文档
网页渲染
  • 流程
    • 加载html和css源码
    • html转换为DOM,css转换为CSSOM
    • 将DOM和CSSOM构建成一棵渲染树
    • 对元素进行排版。
    • 对元素进行绘制。
  • 渲染树
    • 从根元素开始检查哪些元素可见以及它们的样式
    • 忽略那些不占位置的元素
    • 匹配样式
  • 重排(回流)reflow。元素的大小或者位置发生变化。
  • 重绘repaint。元素的样式发生变化。
  • 减少回流的方式。(实际上框架都已经优化过,不需要考虑)
    • 将样式写到类中,为元素添加类。
    • 先display:none,修改玩样式后display:block
插槽
  • 在父组件中指定子组件中的内容
事件
  • 内联事件处理器和方法事件处理器
  • 如果区分两种事件处理器:检查事件的值是否是合法的JS标识符或属性访问路径,如果是则为方法,否则为内联。
  • 内联事件处理器回调函数的参数由我们自己决定,可以传入$event 表示事件对象或是使用箭头函数传入事件对象。方法事件处理器回调函数的参数由vue帮我们传递。即事件对象。
透传
  • 单根组件的根元素自动继承透传属性,如果组件的根元素是子组件则继续向下传递。多跟组件需要通过v-bind="$attrs"指定继承的根元素。在脚本中 通过 useAttrs() 获取透传属性。
  • 透传发生在没有被声明为props和emit的属性上。
双向数据绑定
  • .lazy input事件改为change事件 .trim 取出首尾空格 .number 数据转换为数值
  • Object.assign() 浅复制,将响应式数据复制为普通数据。或者结构 {…data.value}
状态提升
  • 状态(state)即数据。视图(view)呈现状态,用户通过视图访问状态。交互(action),改变状态。
  • 多个组件使用同一个状态state时,可以将state提升到共同的祖先组件中,然后用依赖注入传给要使用该状态的组件。或者使用单例,将状态提出到一个单独的文件,谁使用谁引入。

Vue2

基本使用

  • 通过vm对象代理data对象中属性的操作。通过Object.defineProperty() 把data对象中所有属性添加到vm上,并为每一个添加的属性执行setter和getter方法,在getter和setter中华操作data对应的属性。
  • 每个组件只能有一个根元素
  • 计算属性不能依赖异步数据
  • Vue.set(Object, property, value) 追加对象的响应式属性,不能直接追加data顶层数据。
  • Vue2如何监测数组元素的更新,包装了几个操作数组元素的方法。调用数组原生操作以及重新解析模板更新页面。
  • type位radio和checkbox的输入框都要指定value值,v-model才奏效。多个checkbox需要用数组接收数据。
  • 全局过滤器Vue.filter(name, function)。过滤器不改变原数据,过滤器可以用在插值语法和v-bind上。v-model不能用。
  • v-cloak 用于隐藏尚未完成编译的 DOM 模板。如引入JS文件时,DOM已经渲染,但是Vue尚未解析编译。没有构建步骤的环境下需要使用。
  • 自定义指令何时调用:指令与元素成功绑定时。指令所在的模板被重新解析时。指令名模板中 v-big-number,脚本中加引号。钩子函数中this都指向window
  • props的优先级比data高,即先解析数据。
  • 混入mixin,多个组件共享同配置项。配置复用。优先级低于自身配置项,生命周期钩子函数则会都保留(混合在前,自身在后)。
  • 当数据改变后,要基于新插入的DOM进行的操作需要在nextTick回调中执行。因为新的DOM是在缓存到下一轮更新时才插入的。

组件

  • 组件本质上是一个VueComponent的构造函数,由Vue.extend生成。
  • 在使用组件时,Vue解析并创建组件的实例对象,即new VueComponent(options配置对象)
  • 每次调用Vue.extend时, 返回的都是一个全新的 VueComponent
  • 组件配置中的this均是组件实例对象,new Vue()配置中this均是Vue实例对象。
  • 组件实例是特殊的Vue实例,el只有根组件才能有。
  • VueComponent.prototype.__proto__ === Vue.prototype 组件实例可以访问到Vue原型上的方法和属性。
  • ref 给元素或子组件(实例对象)注册引用信息
  • v-model绑定的值不能是props传过来的值。
  • 绑定在子组件标签上的原生事件需要加 .native 因为绑定在子组件标签上的默认全都为自定义事件

生命周期

  • beforeCreate,无法通过vm(Vue实例)访问到data、methods中的方法。
  • 创建数据代理和数据监测。
  • created,可以通过vm访问到data、methods中的方法
  • beforeMount, 页面呈现的是未经Vue渲染的DOM结构。此阶段所有对DOM的操作最终都是不奏效的。
  • 虚拟DOM转换为真实DOM
  • mounted,页面中呈现的都是经过Vue渲染的DOM结构。初始化过程结束。
  • beforeUpdate,数据是新的,页面是旧的。
  • 根据新数据生成新的虚拟DOM,随后与旧的虚拟DOM比较,最终完成页面更新。
  • updated,数据和页面同步。
  • vm.$destroy 完全销毁一个实例,清理它与其它实例的连接,解绑它的全部指令以及自定义事件监听器
  • beforeDestroy,data、methods、指令等等都处于可用状态,一般在此阶段关闭定时器、取消订阅消息、解绑自定义事件等。

全局事件总线

  • 绑定以及回调函数写在接收数据的组件内。触发事件写在传递数据的组件内。
  • 子组件传递数据给父组件,兄弟组件间传递数据。
  • 为什么要放在beforeCreate钩子中?因为要在组件访问$bus前(即组件挂载前,mounted中访问$bus)将$bus放到Vue的原型对象上。

路由

  • 路由:一组对应关系。

  • 配置流程

    • npm install vue-router@3 (最新版本为4,只能配合Vue3使用)
    • 在main.js中引入并Vue.use(VueRouter)
    • 创建路由器 new VueRouter({配置项routes})并导出
    • 引入路由器router 并配置Vue 的配置项 router: router
    • 在模板中插入切换路径的标签 (就是对a标签的包装)配置to属性
    • 在模板中插入 指定组件显示位置。
  • 路由组件一般存放在pages文件夹下。

  • 被切走的路由组件会被销毁。所以组件ajax请求一般在mounted中?

  • 路由组件的实例对象上多两个属性 $route 组件的配置信息(每个组件不一样)$router 路由器信息,整个应用只有一个路由器。

  • 命名路由。增加name属性。在 中以对象的方式使用 :to=“{name: ‘xxx’}” 从而可以省略path属性。

  • params参数,需要在路由器中占位。并且只能用name不能用path。

  • props

    • 如果为对象,则对象中的所有键值对都会以props的形式传递给组件。
    • 如果为布尔值true,则会把收到的params参数(但是不传query参数)以props的形式传递给组件,在组件中用props接收就行。
    • 如果为函数。props($route){return {}}。 与第一种方法的区别在于$route参数可以访问到动态传递的参数,从而以props的形式传递给组件。
  • 浏览器历史记录保存在栈中。分为两种模式push和replace模式。replace模式覆盖栈顶的记录,push则压入栈顶。

  • 编程式路由导航: this.$router.push({}) this.$router.replace({}) this.$router.back() this.$router.forward()

  • 标签切换时不销毁,inclde属性设置不销毁的组件名,不设置默认为在该位置的所有组件。想缓存部分的写成数组。:include=[‘News’, ‘Messages’]

  • 路由独有的两个声明周期钩子activated(激活)deactivated(失活)

  • 路由守卫

    • 前置路由首位 beforeEach 初始化或每次路由切换之前调用回调函数。函调函数参数 to, from, next
    • 后置路由守卫 afterEach 初始化或每次路由切换之后调用回调函数。函调函数参数 to, from 。通常利用后置路由守卫修改title信息。
    • 独享路由守卫。配置项 beforeEnter 。只有前置没有后置。
    • 组件内路由守卫。写在组件内的配置项,beforeRouteEnter 通过路由规则进入该组件时被调用。 beforeRouteLeave 通过路由规则离开该组件时被调用。都需要调用next放行。
  • 路由器的两种工作模式

    • hash模式。#后面的内容不会作为路径内容发给服务器
      • 地址中永远带着#号,不美观
      • 通过手机app分享地址,若检验严格,地址会被标记为不合法
      • 兼容性较好
    • history模式。
      • 地址干净,美观
      • 兼容性略差
      • 部署上线时需要后端人员支持解决刷新页面出现404问题。
  • 上线流程。

    • npm run build 打包,生成html、css、js文件。
    • 部署在服务器,将打包的文件放在static文件夹下
    • connect-history-api-fallback 解决history模式刷新404问题
  • ElementUI 按需引入

个人理解

基础部分

  • 每个Vue项目都是一个或多个Vue应用,而每个Vue应用在代码中通过一个应用实例实现。所以一上来就调用createApp方法创建一个应用实例。再将应用实例挂载到网页中才会渲染出来。挂载的目标通常是某个元素。
  • 在createApp方法中传入的是组件,通常是根组件。根组件可能包含多个或多层子组件,每个组件内部都有自己独立的逻辑样式结构。数据在组件之间传递。
  • 插值语法{{}} 和 v-bind 可以结合起来理解。都是用来绑定响应式数据。插值语法将标签中的内容设置为响应式,v-bind将标签中的属性设置为响应式。两者都可以绑定表达式或是函数调用。
  • 动态参数属性(属性名是动态的)最好结合计算属性使用。
  • 要实现响应式,就要能监测到数据的变化。通常使用reactive(针对对象)和ref(针对原始类型number、string、boolean,会包装为对象)创建响应式数据。其实现原理是代理对象,即Proxy对象。依赖于响应式数据的计算属性也是响应式的,本质是ref。响应式DOM和逻辑通过侦听器实现。
  • 对同一个原始对象多次调用reactive方法会返回相同的代理对象,而对代理对象调用reactive返回代理对象本身。
  • 对reactive创建的响应式对象赋值(传参也是赋值)或是结构至新的变量时,新的变量将失去响应。因为响应式系统是通过属性访问跟踪的,必须保持对响应式对象的引用。
  • 响应式数据通常有对应的方法更改数据,而方法通常作为事件监听器,所以响应式数据、响应式方法、事件三者经常结合使用。
  • 响应式数据发生变化时,vue的DOM更新不是同步的,有一定的缓冲周期,存在缓冲队列中。该周期内的所有变化将一次性更新至DOM中。
  • 组合式与选项式。选项式的this指向组件实例,在某个选项访问其它选项的数据时,需要用this。组合式可以直接访问。
  • 计算属性有缓存,其主要作用是根据已有的值派生出一个值,不建议在计算属性的getter中做异步请求或更改DOM,也不建议使用计算属性的setter,即将计算属性视为只读的。
  • 为了保证自己的数据自己操作的原则,如果子组件要修改的数据在父组件中,实现方法通常是:在父组件中自定义事件,交由子组件触发。
  • emit和prop类似,可以结合起来看,一个接收父组件的方法,一个接收父组件的数据。
  • emit通常是在子组件中的某个事件要修改父组件中的数据。
  • 在父组件中的事件需要获取子组件中的数据.
  • 组合式API可以实现逻辑复用,组件则是模板复用。
  • Transition 组件中只能用ref数据,不能用reactive数据?
  • v-for遍历时,虚拟DOM中同一个key的旧的结构和新的结构进行对比。只更改变化的数据,但是有些数据在真实DOM中(如input 输入型元素),虚拟DOM中并没有不同。
  • data为什么是函数,因为组件可能复用,对象存在引用关系。
  • 兄弟组件通信:全局事件总线,消息订阅与发布,Vuex。
  • 插槽的使用:框架重复,可形成单独的组件,但是框架中的内容需要父组件决定。
组件间通信
  • 子组件向父组件传递数据
    • 自定义事件传参
    • 父组件通过props向子组件传递方法,子组件调用方法并传参。
  • 父组件向子组件传递数据
    • props
    • 依赖注入 provide和inject
    • 透传,将class、style、id、事件监听器、props等传递给子组件的根元素
  • 祖先向孙组件及后代组件传递数据
    • $attrs传递props
  • 孙组件向祖先组件传递数据
    • $listeners 传递emit事件,孙组件在事件中传参
  • 任意组件间通信
    • 消息订阅与发布
    • 事件总线

Vue2与Vue3的对比

  • Vue2中的数据代理通过Object.defineProperty()实现,对每个属性进行代理?Vue3中通过Proxy对象实现,对整个对象进行代理?
  • 自定义指令在Vue2中的调用时机(钩子函数)是bind和update,在Vue3中是mounted和updated
  • Vue3中的应用实例相当于Vue2中的Vue实例

你可能感兴趣的:(前端笔记,vue.js,javascript,前端)