在vue中使用jquery

首先默认你已经有了一个vue程序,如果你想在vue中使用jquery,那么请继续阅读。

当然,加入你没有一个vue程序,这里也给出创建一个vue程序的命令。当然,你肯定装了vue-cli,不然你不会点进这篇博客

项目的目录类似如下:

对了,这个demo里使用了element-ui

安装方式:

配置方式:

可以直接拷走

jquery安装

直接运行下面的命令

jquery引用

在需要使用jquery的组件里,引入jquery后,即可正常使用

举例

运行效果:

如果需要源码,在下面下载

下载地址:https://download.csdn.net/download/iiiliuyang/12127883

如果这篇博客对你有用,点个赞再走呗~

大厂二面让我谈谈Vue.js框架,我慌了,我不知道啊

Vue (读音 /vjuː/,类似于 view) 是一套用于构建用户界面的渐进式框架。

Vue 的核心库只关注视图层,不仅易于上手,还便于与第三方库或既有项目整合。另一方面,当与现代化的工具链以及各种支持类库结合使用时,Vue 也完全能够为复杂的单页应用提供驱动。

这就是声明式渲染:Vue.js 的核心是一个允许采用简洁的模板语法来声明式地将数据渲染进 DOM 的系统

这里的核心思想就是没有繁琐的DOM操作,例如jQuery中,我们需要先找到div节点,获取到DOM对象,然后进行一系列的节点操作

在vs code中创建代码片段:

文件 => 首选项 => 用户代码片段 => 新建全局代码片段/或文件夹代码片段:vue-html.code-snippets

注意:制作代码片段的时候,字符串中如果包含文件中复制过来的“Tab”键的空格,要换成“空格键”的空格

分享目标

了解 Vue.js 的组件化机制了解 Vue.js 的响应式系统原理了解 Vue.js 中的 Virtual DOM 及 Diff 原理

Vue 是一套用于构建用户界面的渐进式MVVM框架。那怎么理解渐进式呢?渐进式含义:强制主张最少。

Vue.js包含了声明式渲染、组件化系统、客户端路由、大规模状态管理、构建工具、数据持久化、跨平台支持等,但在实际开发中,并没有强制要求开发者之后某一特定功能,而是根据需求逐渐扩展。 Vue.js的核心库只关心视图渲染,且由于渐进式的特性,Vue.js便于与第三方库或既有项目整合。

组件机制

定义:

组件就是对一个功能和样式进行独立的封装,让HTML元素得到扩展,从而使得代码得到复用,使得开发灵活,更加高效。

与HTML元素一样,Vue.js的组件拥有外部传入的属性prop和事件,除此之外,组件还拥有自己的状态data和通过数据和状态计算出来的计算属性computed,各个维度组合起来决定组件最终呈现的样子与交互的逻辑。

数据传递

每一个组件之间的作用域是孤立的,这个意味着组件之间的数据不应该出现引用关系,即使出现了引用关系,也不允许组件操作组件内部以外的其他数据。Vue中,允许向组件内部传递prop数据,组件内部需要显性地声明该prop字段,如下声明一个child组件:

父组件向该组件传递数据:

事件传递

Vue内部实现了一个事件总线系统,即EventBus。在Vue中可以使用 EventBus 来作为沟通桥梁的概念,每一个Vue的组件实例都继承了 EventBus,都可以接受事件on和发送事件emit。

如上面一个例子,child.vue组件想修改 parent.vue组件的 parentMsg 数据,怎么办呢?为了保证数据流的可追溯性,直接修改组件内prop的msg 字段是不提倡的,且例子中为非引用类型 String,直接修改也修改不了,这个时候需要将修改 parentMsg的事件传递给child.vue,让 child.vue 来触发修改parentMsg 的事件。如:

父组件:

父组件parent.vue 向子组件child.vue传递了updateMsg事件,在子组件实例化的时候,子组件将updateMsg事件使用on函数注册到组件内部,需要触发事件的时候,调用函数this.emit来触发事件。

除了父子组件之间的事件传递,还可以使用一个 Vue 实例为多层级的父子组件建立数据通信的桥梁,如:

除了on和emit以外,事件总线系统还提供了另外两个方法,once和off,所有事件如下:

  • $on:监听、注册事件。
  • $emit:触发事件。
  • $once:注册事件,仅允许该事件触发一次,触发结束后立即移除事件。
  • $off:移除事件。
  • 内容分发

Vue实现了一套遵循 Web Components 规范草案 的内容分发系统,即将元素作为承载分发内容的出口。

插槽slot,也是组件的一块HTML模板,这一块模板显示不显示、以及怎样显示由父组件来决定。实际上,一个slot最核心的两个问题在这里就点出来了,是显示不显示和怎样显示。

插槽又分默认插槽、具名插槽。

默认插槽

又名单个插槽、匿名插槽,与具名插槽相对,这类插槽没有具体名字,一个组件只能有一个该类插槽。

如:

如上,渲染时子组件的slot标签会被父组件传入的div.tmpl替换。

具名插槽

匿名插槽没有name属性,所以叫匿名插槽。那么,插槽加了name属性,就变成了具名插槽。具名插槽可以在一个组件中出现N次,出现在不同的位置,只需要使用不同的name属性区分即可。

如:

如上,slot标签会根据父容器给 child标签内传入的内容的slot 属性值,替换对应的内容。

其实,默认插槽也有name属性值,为default,同样指定 slot的 name值为 default,一样可以显示父组件中传入的没有指定slot的内容。

作用域插槽

作用域插槽可以是默认插槽,也可以是具名插槽,不一样的地方是,作用域插槽可以为slot标签绑定数据,让其父组件可以获取到子组件的数据。

如:

如上例子,子组件 child在渲染默认插槽slot的时候,将数据 user传递给了 slot 标签,在渲染过程中,父组件可以通过slot-scope属性获取到user数据并渲染视图。

slot 实现原理:

当子组件vm实例化时,获取到父组件传入的 slot 标签的内容,存放在vm.slot中,默认插槽为vm.slot.default,具名插槽为vm.slot.xxx,xxx为插槽名,当组件执行渲染函数时候,遇到<slot>标签,使用slot中的内容进行替换,此时可以为插槽传递数据,若存在数据,则可曾该插槽为作用域插槽。

至此,父子组件的关系如下图:

模板渲染

Vue.js 的核心是声明式渲染,与命令式渲染不同,声明式渲染只需要告诉程序,我们想要的什么效果,其他的事情让程序自己去做。而命令式渲染,需要命令程序一步一步根据命令执行渲染。如下例子区分:

Vue.js实现了if、for、事件、数据绑定等指令,允许采用简洁的模板语法来声明式地将数据渲染出视图。

模板编译

为什么要进行模板编译?实际上,我们组件中的 template语法是无法被浏览器解析的,因为它不是正确的 HTML 语法,而模板编译,就是将组件的 template编译成可执行的 JavaScript代码,即将 template 转化为真正的渲染函数。

模板编译分三个阶段,parse、optimize、generate,最终生成render函数。

parse阶段:

使用正在表达式将template进行字符串解析,得到指令、class、style等数据,生成抽象语法树 AST。

optimize阶段:

寻找 AST 中的静态节点进行标记,为后面 VNode 的 patch 过程中对比做优化。被标记为static 的节点在后面的diff 算法中会被直接忽略,不做详细的比较。

generate阶段:

根据 AST 结构拼接生成render函数的字符串。

预编译

对于 Vue 组件来说,模板编译只会在组件实例化的时候编译一次,生成渲染函数之后再也不会进行编译。因此,编译对组件的 runtime 是一种性能损耗。而模板编译的目的仅仅是将template转化为render function,而这个过程,正好可以在项目构建的过程中完成。

比如webpack的vue-loader依赖了vue-template-compiler模块,在 webpack 构建过程中,将template预编译成 render 函数,在 runtime 可直接跳过模板编译过程。

回过头看,runtime 需要是仅仅是 render 函数,而我们有了预编译之后,我们只需要保证构建过程中生成 render 函数就可以。与 React 类似,在添加JSX的语法糖编译器babel-plugin-transform-vue-jsx之后,我们可以在 Vue 组件中使用JSX语法直接书写 render 函数。

如上面组件,使用 JSX 之后,可以在 JS 代码中直接使用 html 标签,而且声明了 render 函数以后,我们不再需要声明 template。当然,假如我们同时声明了 template 标签和 render 函数,构建过程中,template 编译的结果将覆盖原有的 render 函数,即 template 的优先级高于直接书写的 render 函数。

相对于 template 而言,JSX 具有更高的灵活性,面对与一些复杂的组件来说,JSX 有着天然的优势,而 template 虽然显得有些呆滞,但是代码结构上更符合视图与逻辑分离的习惯,更简单、更直观、更好维护。

需要注意的是,最后生成的 render 函数是被包裹在with语法中运行的。

小结

Vue 组件通过 prop 进行数据传递,并实现了数据总线系统EventBus,组件集成了EventBus进行事件注册监听、事件触发,使用slot进行内容分发。

除此以外,实现了一套声明式模板系统,在runtime或者预编译是对模板进行编译,生成渲染函数,供组件渲染视图使用。

响应式系统

Vue.js 是一款 MVVM 的JS框架,当对数据模型data进行修改时,视图会自动得到更新,即框架帮我们完成了更新DOM的操作,而不需要我们手动的操作DOM。可以这么理解,当我们对数据进行赋值的时候,Vue 告诉了所有依赖该数据模型的组件,你依赖的数据有更新,你需要进行重渲染了,这个时候,组件就会重渲染,完成了视图的更新。

数据模型 、计算属性 和监听器

在组件中,可以为每个组件定义数据模型data、计算属性computed、监听器watch。

数据模型:Vue 实例在创建过程中,对数据模型data的每一个属性加入到响应式系统中,当数据被更改时,视图将得到响应,同步更新。data必须采用函数的方式 return,不使用 return 包裹的数据会在项目的全局可见,会造成变量污染;使用return包裹后数据中变量只在当前组件中生效,不会影响其他组件。

计算属性:computed基于组件响应式依赖进行计算得到结果并缓存起来。只在相关响应式依赖发生改变时它们才会重新求值,也就是说,只有它依赖的响应式数据(data、prop、computed本身)发生变化了才会重新计算。那什么时候应该使用计算属性呢?模板内的表达式非常便利,但是设计它们的初衷是用于简单运算的。在模板中放入太多的逻辑会让模板过重且难以维护。对于任何复杂逻辑,你都应当使用计算属性。

监听器:监听器watch作用如其名,它可以监听响应式数据的变化,响应式数据包括 data、prop、computed,当响应式数据发生变化时,可以做出相应的处理。当需要在数据变化时执行异步或开销较大的操作时,这个方式是最有用的。

响应式原理

在 Vue 中,数据模型下的所有属性,会被 Vue 使用Object.defineProperty(Vue3.0 使用 Proxy)进行数据劫持代理。响应式的核心机制是观察者模式,数据是被观察的一方,一旦发生变化,通知所有观察者,这样观察者可以做出响应,比如当观察者为视图时,视图可以做出视图的更新。

Vue.js 的响应式系统以来三个重要的概念,Observer、Dep、Watcher。

发布者-Observer

  1. Observe 扮演的角色是发布者,他的主要作用是在组件vm初始化的时,调用defineReactive函数,使用Object.defineProperty方法对对象的每一个子属性进行数据劫持/监听,即为每个属性添加getter和setter,将对应的属性值变成响应式。
  2. 在组件初始化时,调用initState函数,内部执行initState、initProps、initComputed方法,分别对data、prop、computed进行初始化,让其变成响应式。
  3. 初始化props时,对所有props进行遍历,调用defineReactive函数,将每个 prop 属性值变成响应式,然后将其挂载到_props中,然后通过代理,把vm.xxx代理到vm._props.xxx中。
  4. 同理,初始化data时,与prop相同,对所有data进行遍历,调用defineReactive函数,将每个 data 属性值变成响应式,然后将其挂载到_data中,然后通过代理,把vm.xxx代理到vm._data.xxx中。
  5. 初始化computed,首先创建一个观察者对象computed-watcher,然后遍历computed的每一个属性,对每一个属性值调用defineComputed方法,使用Object.defineProperty将其变成响应式的同时,将其代理到组件实例上,即可通过vm.xxx访问到xxx计算属性。

调度中心/订阅器-Dep

  1. Dep 扮演的角色是调度中心/订阅器,在调用defineReactive将属性值变成响应式的过程中,也为每个属性值实例化了一个Dep,主要作用是对观察者(Watcher)进行管理,收集观察者和通知观察者目标更新,即当属性值数据发生改变时,会遍历观察者列表(dep.subs),通知所有的 watcher,让订阅者执行自己的update逻辑。
  2. 其dep的任务是,在属性的getter方法中,调用dep.depend()方法,将观察者(即 Watcher,可能是组件的render function,可能是 computed,也可能是属性监听watch)保存在内部,完成其依赖收集。在属性的setter方法中,调用dep.notify()方法,通知所有观察者执行更新,完成派发更新。

观察者-Watcher

Watcher 扮演的角色是订阅者/观察者,他的主要作用是为观察属性提供回调函数以及收集依赖,当被观察的值发生变化时,会接收到来自调度中心Dep的通知,从而触发回调函数。

而Watcher又分为三类,normal-watcher、 computed-watcher、 render-watcher。

  • normal-watcher:在组件钩子函数watch中定义,即监听的属性改变了,都会触发定义好的回调函数。
  • computed-watcher:在组件钩子函数computed中定义的,每一个computed属性,最后都会生成一个对应的Watcher对象,但是这类Watcher有个特点:当计算属性依赖于其他数据时,属性并不会立即重新计算,只有之后其他地方需要读取属性的时候,它才会真正计算,即具备lazy(懒计算)特性。
  • render-watcher:每一个组件都会有一个render-watcher, 当data/computed中的属性改变的时候,会调用该Watcher来更新组件的视图。

这三种Watcher也有固定的执行顺序,分别是:computed-render -> normal-watcher -> render-watcher。这样就能尽可能地保证,在更新组件视图的时候,computed 属性已经是最新值了,如果 render-watcher 排在 computed-render 前面,就会导致页面更新的时候 computed 值为旧数据。

小结

Observer 负责将数据进行拦截,Watcher 负责订阅,观察数据变化, Dep 负责接收订阅并通知 Observer 和接收发布并通知所有 Watcher。

Virtual DOM

在 Vue 中,template被编译成浏览器可执行的render function,然后配合响应式系统,将render function挂载在render-watcher中,当有数据更改的时候,调度中心Dep通知该render-watcher执行render function,完成视图的渲染与更新。

整个流程看似通顺,但是当执行render function时,如果每次都全量删除并重建 DOM,这对执行性能来说,无疑是一种巨大的损耗,因为我们知道,浏览器的DOM很“昂贵”的,当我们频繁的更新 DOM,会产生一定的性能问题。

为了解决这个问题,Vue 使用 JS 对象将浏览器的 DOM 进行的抽象,这个抽象被称为 Virtual DOM。Virtual DOM 的每个节点被定义为VNode,当每次执行render function时,Vue 对更新前后的VNode进行Diff对比,找出尽可能少的我们需要更新的真实 DOM 节点,然后只更新需要更新的节点,从而解决频繁更新 DOM 产生的性能问题。

VNode

VNode,全称virtual node,即虚拟节点,对真实 DOM 节点的虚拟描述,在 Vue 的每一个组件实例中,会挂载一个$createElement函数,所有的VNode都是由这个函数创建的。

比如创建一个 div:

render 函数执行后,会根据VNode Tree将 VNode 映射生成真实 DOM,从而完成视图的渲染。

Diff

Diff 将新老 VNode 节点进行比对,然后将根据两者的比较结果进行最小单位地修改视图,而不是将整个视图根据新的 VNode 重绘,进而达到提升性能的目的。

patch

Vue.js 内部的 diff 被称为patch。其 diff 算法的是通过同层的树节点进行比较,而非对树进行逐层搜索遍历的方式,所以时间复杂度只有O(n),是一种相当高效的算法。

首先定义新老节点是否相同判定函数sameVnode:满足键值key和标签名tag必须一致等条件,返回true,否则false。

在进行patch之前,新老 VNode 是否满足条件sameVnode(oldVnode, newVnode),满足条件之后,进入流程patchVnode,否则被判定为不相同节点,此时会移除老节点,创建新节点。

patchVnode

patchVnode 的主要作用是判定如何对子节点进行更新,

  1. 如果新旧VNode都是静态的,同时它们的key相同(代表同一节点),并且新的 VNode 是 clone 或者是标记了 once(标记v-once属性,只渲染一次),那么只需要替换 DOM 以及 VNode 即可。
  2. 新老节点均有子节点,则对子节点进行 diff 操作,进行updateChildren,这个 updateChildren 也是 diff 的核心。
  3. 如果老节点没有子节点而新节点存在子节点,先清空老节点 DOM 的文本内容,然后为当前 DOM 节点加入子节点。
  4. 当新节点没有子节点而老节点有子节点的时候,则移除该 DOM 节点的所有子节点。
  5. 当新老节点都无子节点的时候,只是文本的替换。

updateChildren

Diff 的核心,对比新老子节点数据,判定如何对子节点进行操作,在对比过程中,由于老的子节点存在对当前真实 DOM 的引用,新的子节点只是一个 VNode 数组,所以在进行遍历的过程中,若发现需要更新真实 DOM 的地方,则会直接在老的子节点上进行真实 DOM 的操作,等到遍历结束,新老子节点则已同步结束。

updateChildren内部定义了4个变量,分别是oldStartIdx、oldEndIdx、newStartIdx、newEndIdx,分别表示正在 Diff 对比的新老子节点的左右边界点索引,在老子节点数组中,索引在oldStartIdx与oldEndIdx中间的节点,表示老子节点中为被遍历处理的节点,所以小于oldStartIdx或大于oldEndIdx的表示未被遍历处理的节点。同理,在新的子节点数组中,索引在newStartIdx与newEndIdx中间的节点,表示老子节点中为被遍历处理的节点,所以小于newStartIdx或大于newEndIdx的表示未被遍历处理的节点。

每一次遍历,oldStartIdx和oldEndIdx与newStartIdx和newEndIdx之间的距离会向中间靠拢。当 oldStartIdx > oldEndIdx 或者 newStartIdx > newEndIdx 时结束循环。

在遍历中,取出4索引对应的 Vnode节点:

  • oldStartIdx:oldStartVnode
  • oldEndIdx:oldEndVnode
  • newStartIdx:newStartVnode
  • newEndIdx:newEndVnode

diff 过程中,如果存在key,并且满足sameVnode,会将该 DOM 节点进行复用,否则则会创建一个新的 DOM 节点。

首先,oldStartVnode、oldEndVnode与newStartVnode、newEndVnode两两比较,一共有 2*2=4 种比较方法。

情况一:当oldStartVnode与newStartVnode满足 sameVnode,则oldStartVnode与newStartVnode进行 patchVnode,并且oldStartIdx与newStartIdx有移动。

情况二:与情况一类似,当oldEndVnode与newEndVnode满足 sameVnode,则oldEndVnode与newEndVnode进行 patchVnode,并且oldEndIdx与newEndIdx左移动。

情况三:当oldStartVnode与newEndVnode满足 sameVnode,则说明oldStartVnode已经跑到了oldEndVnode后面去了,此时oldStartVnode与newEndVnode进行 patchVnode 的同时,还需要将oldStartVnode的真实 DOM 节点移动到oldEndVnode的后面,并且oldStartIdx右移,newEndIdx左移。

情况四:与情况三类似,当oldEndVnode与newStartVnode满足 sameVnode,则说明oldEndVnode已经跑到了oldStartVnode前面去了,此时oldEndVnode与newStartVnode进行 patchVnode 的同时,还需要将oldEndVnode的真实 DOM 节点移动到oldStartVnode的前面,并且oldStartIdx右移,newEndIdx左移。

当这四种情况都不满足,则在oldStartIdx与oldEndIdx之间查找与newStartVnode满足sameVnode的节点,若存在,则将匹配的节点真实 DOM 移动到oldStartVnode的前面。

若不存在,说明newStartVnode为新节点,创建新节点放在oldStartVnode前面即可。

当 oldStartIdx > oldEndIdx 或者 newStartIdx > newEndIdx,循环结束,这个时候我们需要处理那些未被遍历到的 VNode。

当 oldStartIdx > oldEndIdx 时,说明老的节点已经遍历完,而新的节点没遍历完,这个时候需要将新的节点创建之后放在oldEndVnode后面。

当 newStartIdx > newEndIdx 时,说明新的节点已经遍历完,而老的节点没遍历完,这个时候要将没遍历的老的节点全都删除。

此时已经完成了子节点的匹配。下面是一个例子 patch 过程图:

总结

借用官方的一幅图:

Vue.js 实现了一套声明式渲染引擎,并在runtime或者预编译时将声明式的模板编译成渲染函数,挂载在观察者 Watcher 中,在渲染函数中(touch),响应式系统使用响应式数据的getter方法对观察者进行依赖收集(Collect as Dependency),使用响应式数据的setter方法通知(notify)所有观察者进行更新,此时观察者 Watcher 会触发组件的渲染函数(Trigger re-render),组件执行的 render 函数,生成一个新的 Virtual DOM Tree,此时 Vue 会对新老 Virtual DOM Tree 进行 Diff,查找出需要操作的真实 DOM 并对其进行更新。

什么是vue?为什么用vue?

综合:https://segmentfault.com/a/1190000015560315https://blog.csdn.net/liang377122210/article/details/71545459https://blog.csdn.net/xutongbao/article/details/77870989这几篇都写得非常好1.Vue.js是什么?vue就是一个js库,并且无依赖别的js库,跟jquery差不多。vue的核心库只关注视图层,非常容易与其它库或已有项目整合。Vue.js是一个轻巧、高性能、可组件化的MVVM库,同时拥有非常容易上手的API。2.Vue的MVVM设计模式是什么?导致了和jQuery的那些区别如果你对前端有过了解的话一定知道MVVM和MVC这两种设计模式,而且很有可能对mvp也有一些了解。MVC即model,view,control,jQuery就是采用的这种设计模式,熟悉jQuery的同学恐怕早就对$()深通恶绝了吧。

MVVM即model,view,viewmodel,它是数据驱动模式,即所有的一切通过操作数据来进行,而尽量避免操作dom树。

换句话说,我们不关注dom的结构,而是考虑数据该如何储存,用户的操作在view通过viewmodel进行数据处理,分情况是否通过ajax与model层进行交互,再返回到view层,在这个过程中view和viewmodel的数据双向绑定使得我们完全的摆脱了对dom的繁琐操作,而是专心于对用户的操作进行处理,避免了MVC中control层过厚的问题。现在我们把一个网页应用抽象一下,那么HTML中的DOM其实就是视图,一个网页就是通过DOM的组合与嵌套,形成了最基本的视图结构,再通过CSS的修饰,在基本的视图结构上“化妆”让他们看起来更加美观。最后涉及到交互部分,就需要用到JavaScript来接受用户的交互请求,并且通过事件机制来响应用户的交互操作,并且在事件的处理函数中进行各种数据的修改,比如说修改某个DOM中的innerHTML或者innerText部分。我们把HTML中的DOM就可以与其他的部分独立开来划分出一个层次,这个层次就叫做视图层。Vue 的核心库只关注视图层我们为什么要把视图层抽取出来并且单独去关注它呢?因为在像知乎这种页面元素非常多,结构很庞大的网页中,数据和视图如果全部混杂在一起,像传统开发一样全部混合在HTML中,那么要对它们进行处理会十分的费劲,并且如果其中有几个结构之间存在藕断丝连的关系,那么会导致代码上出现更大的问题,这什么问题呢?你是否还记得你当初写JQuery的时候,有写过 $ (’#xxx’).parent().parent().parent()这种代码呢?当你第一次写的时候,你觉得页面元素不多,不就是找这个元素的爸爸的爸爸的爸爸吗,我大不了在注释里面写清楚这个元素的爸爸的爸爸的爸爸不就好了。但是万一过几天之后你的项目组长或者你的产品经理突然对你做的网页提出修改要求,这个修改要求将会影响页面的结构,也就是DOM的关联与嵌套层次要发生改变,那么$ (’#xxx’).parent().parent().parent()可能就会变成$(’#xxx’).parent().parent().parent().parent().parent()了。

这还不算什么,等以后产品迭代越来越快,修改越来越多,而且页面中类似的关联和嵌套DOM元素不止一个,那么修改起来将非常费劲。而且JQuery选择器查找页面元素以及DOM操作本身也是有性能损失的,可能到时候打开这个页面,会变得越来越卡,而你却无从下手。当你在编写项目的时候遇到了这种问题,你一定会抱怨,为什么世上会有HTML这种像盗梦空间一样的需要无数div嵌套才能做出页面的语言,为什么当初学JQuery看中的是它简洁的DOM操作,现在却一点也不觉得它有多简洁,难道我学的是假的JQuery?为什么写个代码这么难,你想砸电脑,你想一键盘拍在产品狗的脑袋上,责怪他天天改需求才让你原本花清香茶清味的代码变得如此又臭又长。这个时候如果你学过Vue.js,那么这些抱怨将不复存在。3.Vue.js有那些优点?声明式,响应式的数据绑定组件化的开发Virtual DOM响应式的数据绑定1.jQuery首先要获取到dom对象,然后对dom对象进行进行值的修改等操作2.Vue是首先把值和js对象进行绑定,然后修改js对象的值,Vue框架就会自动把dom的值就行更新。3.可以简单的理解为Vue帮我们做了dom操作,我们以后用Vue就需要修改对象的值和做好元素和对象的绑定,Vue这个框架就会自动帮我们做好dom的相关操作4.这种dom元素跟随JS对象值的变化而变化叫做单向数据绑定,如果JS对象的值也跟随着dom元素的值的变化而变化就叫做双向数据绑定<!DOCTYPE html><html lang=\”en\”><head><meta charset=\”UTF-8\”><title>vue.js测试 – 代码之美专栏</title><!– author:昌维 代码之美 https://zhuanlan.zhihu.com/codes –><script src=\”https://unpkg.com/vue/dist/vue.js\”></script></head><body><div id=\”app\”><input type=\”text\” name=\”\” value=\”\” placeholder=\”在这里输入文字,下面会跟着变化\” v-model=\”message\”><hr><p>{{ message }}</p></div><script type=\”text/javascript\”>var app = new Vue({ el: \’#app\’, data: { message: \’Hello Vue!\’ }})</script></body></html>

是不是会发现一个很神奇的现象,文本框里面输入的文字和后面的p标签中的内容一起变化?换句话说,p标签里面通过{{ message }}这个写法与input标签中的value绑定在了一起,其中变化,另外一个和它绑定的数据就跟着变化。结合标题来说,就是vue.js会自动响应数据的变化情况,并且根据用户在代码中预先写好的绑定关系,对所有绑定在一起的数据和视图内容都进行修改。而这种绑定关系,在图上是以input 标签的v-model属性来声明的,因此你在别的地方可能也会看到有人粗略的称vue.js为声明式渲染的模版引擎。组件化开发作为整个VUE文档中篇幅最大的部分,组件可是相当的添彩,要不是有组件这么易于复用,不易污染的特性,怕不是我都疯了无数回。打个比方,我们现在要做一个有一百个页面的项目,其中有三十三个导航栏是A,六十七个导航栏是B,这其中三十三个A导航栏中有一个模块与众不同,可以分为A1,A2,A3,A4……这个如果用jQuery解决的话,就得自己封装模板插件,且要么写(A,B,A1,A2,An).length个模板,要么模板套模板。啧啧,累死个狗娘养的了。这点上,VUE的模板就简单的多,我们先算好要多少个组件,然后看看组件之间有没有相互嵌套,把所有需要的地方都先挖上坑(写好组件标签),并且在组件标签中写好要传入组件的参数,再分别写好各种组件的实现,简简单单的就写好了,即使是嵌套也只是组件标签中套一个组件标签,更简单的改一个传参能够实现。还记得在传统前端开发的时候,我们都是每个人做一个页面,然后最后套入各种后端模版引擎,比如说PHP的Smarty或者Java的JSP等等。但是现在我们做单页应用,页面交互和结构十分复杂,一个页面上就有许许多多的模块需要编写,而且往往一个模块的代码量和工作量就非常庞大,如果还按照原先的方法来开发,那么会累死人。而且遇到以后的产品需求变更,修改起来也非常麻烦,生怕动了其中一个div之后,其他div跟着雪崩,整个页面全部乱套,或者由于JavaScript的事件冒泡机制,导致修改一些内层的DOM事件处理函数之后,出现各种莫名其妙的诡异BUG。

在面向对象编程中,我们可以使用面向对象的思想将各种模块打包成类或者把一个大的业务模块拆分成更多更小的几个类。在面向过程编程中,我们也可以把一些大功能拆分成许多函数,然后分配给不同的人来开发。在前端应用,我们是否也可以像编程一样把模块封装呢?这就引入了组件化开发的思想。Vue.js通过组件,把一个单页应用中的各种模块拆分到一个一个单独的组件(component)中,我们只要先在父级应用中写好各种组件标签(占坑),并且在组件标签中写好要传入组件的参数(就像给函数传入参数一样,这个参数叫做组件的属性),然后再分别写好各种组件的实现(填坑),然后整个应用就算做完了。Virtual DOM现在的网速越来越快了,很多人家里都是几十甚至上百M的光纤,手机也是4G起步了,按道理一个网页才几百K,而且浏览器本身还会缓存很多资源文件,那么几十M的光纤为什么打开一个之前已经打开过,已经有缓存的页面还是感觉很慢呢?这就是因为浏览器本身处理DOM也是有性能瓶颈的,尤其是在传统开发中,用JQuery或者原生的JavaScript DOM操作函数对DOM进行频繁操作的时候,浏览器要不停的渲染新的DOM树,导致页面看起来非常卡顿。而Virtual DOM则是虚拟DOM的英文,简单来说,他就是一种可以预先通过JavaScript进行各种计算,把最终的DOM操作计算出来并优化,由于这个DOM操作属于预处理操作,并没有真实的操作DOM,所以叫做虚拟DOM。最后在计算完毕才真正将DOM操作提交,将DOM操作变化反映到DOM树上。对于vue.js的Virtual DOM,目前业界有着褒贬不一的评价。有人认为Vue.js作为一个轻量级框架,引入Virtual DOM会加大Vue.js本身的代码尺寸,也会消耗更多CPU(手机上会更耗电)(注意:消耗更多的CPU并不意味着会更卡,因为JavaScript计算是后台计算,他的计算量还不至于让DOM操作变得卡顿),并且在操作单个DOM元素的时候,反而多了一道计算工序,会更慢。但也有人认为基本上会用Vue.js开发的都是页面中内容很多的元素,肯定操作的DOM量级普遍较大,平均一下还是比较划算的。

本文作者及来源:Renderbus瑞云渲染农场https://www.renderbus.com

点赞 0
收藏 0

文章为作者独立观点不代本网立场,未经允许不得转载。