jquery 元素 高度-vue知识点整理

加入我们一起学习,每天进步

1 Vue底层原理

当你将一个普通的 JavaScript 对象作为数据选项传递到 Vue 实例中时,Vue 将遍历该对象的所有属性,并使用 Object.defineProperty 将所有此类属性转换为 getter/setter。 Object.defineProperty是ES5中无法shim的功能,这也是Vue不支持IE8及以下版本浏览器的原因。 这里的文档仅推荐官方文档。 您可能遇到的几乎所有问题都可以在文档中找到答案。 本部分仅选取几个常见问题进行说明。 这样就可以防止此类问题的发生。

2 vue的数据机制

单向数据流:顾名思义,数据流是双向的。 数据流向可追踪,流向单一,更快速追踪问题。 缺点是写起来不太方便。 要改变UI,必须创建各种动作来维持相应的状态

双向数据绑定:数据相连,改变数据的操作隐藏在框架内部。 优点是在表单交互较多的场景下简化了很多与业务无关的代码。缺点是很难跟踪本地状态的变化,增加了出现错误时的调试难度

具体来说,当我们使用自定义组件时(比如bin-ui中的按钮,我是按钮),size和disabled是单个数据流的表现。 父组件向按钮组件传递参数,流程单一。 按钮组件只需要显示 props 参数即可。 双向数据绑定大多表现在表单组件中,比如输入,而v-model是单向数据绑定的一个句子糖。 本质的数据流是双向的,即v-model相当于bind: value和@input=''来监听返回值并更新。

3 vue数据驱动视图的理解

vue的特点:

各部分之间的通信是单向的

采用单向绑定:View的变化会自动反映到ViewModel中,反之亦然

传统开发无法避免操作dom。 我们总是想到在数据返回后操作dom元素,但是操作dom元素的成本比较大,并且将视口与业务层分离并不容易。 因此,我们需要改变这个习惯。 当我们完成数据获取后,我们只需要更新当前的vue状态值,剩下的刷新操作就交给vue virtual dom了。

4 什么是虚拟dom

虚拟 DOM 是做什么用的? 这要从浏览器本身开始。

我们知道,当浏览器渲染网页时,加载HTML文档后,会解析文档并构建DOM树,然后与解析CSS生成的CSSOM树结合起来,形成爱情的结晶——RenderObject树。 然后将RenderObject树渲染成页面(当然中间可能还有一些优化,比如RenderLayer树)。 这些过程都存在于渲染引擎中。 渲染引擎与浏览器中的 JavaScript 引擎(JavaScriptCore 或 V8)是分离的。 不过,为了方便 JS 操作 DOM 结构,渲染引擎会暴露一些套接字供 JavaScript 调用。 由于这两部分是相互分离的,通信需要付出一定的代价,因此JavaScript调用DOM提供的socket性能并不好。 各种性能优化最佳实践也在尽可能减少 DOM 操作的数量。

虚拟 DOM 有什么作用? 它直接在 JavaScript 中(大致)实现了 DOM 树。 组件的HTML结构并不直接生成DOM,而是映射生成虚拟的JavaScript DOM结构。 在这个虚拟 DOM 上实现一个 diff 算法,找到最小的变化,然后将这个变化写入到实际 DOM 中。这个虚拟 DOM 以 JS 结构的形式存在,计算性能会更好,而且因为实际 DOM 的数量操作减少,性能将大幅提升

这里只是简单介绍一下virtual dom的概念。 Vue的template模板句型,包括jsx句型,本质上都是在最终渲染时标榜为render函数,而render函数中渲染的内容其实就是virtual dom。 在客户端开发、类库开发和组件开发中,渲染函数的编译也是必须掌握的技能之一。

jquery 元素 高度_js获取元素高度_元素高度扭曲怎么办

5 vue生命周期的理解

vue实例有一个完整的生命周期,是指实例从创建到销毁的过程

beforeCreate() 在实例创建之间执行,数据未加载状态created() 在实例创建、数据加载后,能初始化数据,dom渲染之前执行beforeMount() 虚拟dom已创建完成,在数据渲染前最后一次更改数据mounted() 页面、数据渲染完成,真实dom挂载完成beforeUpadate() 重新渲染之前触发updated() 数据已经更改完成,dom 也重新 render 完成,更改数据会陷入死循环beforeDestory() 和 destoryed() 前者是销毁前执行(实例仍然完全可用),后者则是销毁后执行

Vue 生命周期在日常开发中常用到创建和挂载。 具体应用是,比如我需要在页面加载时获取新闻列表和一些原始数据。 这时候我们就可以调用created的hook函数中的方法来加载数据,并进行绑定,如果有时候我们需要自动实现图表(echarts),这时候由于图表的实现机制,我们需要确保 dom 元素已被渲染。 当图表必须挂载到真实的dom元素上时,它必须在mounted函数中。 去调用图表生成方法。

6 v-if 和 v-show 的区别

使用 v-if 时,如果值为 false,则页面不会生成该 html 标签。

v-show表示无论值为true还是false,html元素都会存在,但是CSS中的显示是显示还是隐藏

指示:

1.这两个在使用的时候会出现一些小问题。 例如,使用 v-if 时,如果子元素中存在 {{}} 绑定的响应属性,如 {{current.name}},则此时 current 不存在,则“可能”在渲染此元素时报告错误。 为什么可能呢? 因为 v-if 可能会判断为 false,根本不渲染外层元素,但是使用 v-show 如果为 true 或 false,就会渲染内层元素,如果当前没有初始化,就会报错报道称。 因此,如果我们通过v-show显示隐藏元素,我们需要确保外部绑定值已经被初始化。

2.个人推荐,如果外部元素不变,比如图片,隐藏了一些样式和内容,可以使用v-show配合过渡来达到更好的性能要求。 如果需要动态渲染,可以使用v-if

3、某些情况下,由于刷新机制的原因,我们可以使用v-if来强制vue重绘元素,比如element、bin-ui。 表格的生成是根据配置的宽高动态生成的,这就需要通过敲击窗口大小来调用组件提供的socket来重新刷新大小,但是还有一个暴力的解决方案就是v-if,比如弹出窗口时渲染表单,关闭时直接 = false 强制消除该元素,保证每次绘制元素时都刷新。

7 NextTick函数是什么

this.$nextTick()函数,官方定义是最后一个DOM更新周期结束后延迟反弹。 一般我们会改变数据然后使用$nextTick(),那么我们就可以在弹跳后得到更新后的DOM元素。

我给大家举一个反例来说明这个函数的具体使用。 上面提到的element,包括我的bin-ui重表,都会提供一个刷新尺寸的接口函数来自动获取table组件并重绘尺寸,但是有时候你代码中这个函数确实没有实现,那么这是为什么呢? 原因是vue在更新DOM时是异步执行的。 只要检测到数据变化,vue就会打开一个队列,缓冲同一个风暴周期内发生的所有数据。 改变一下,如果同一个watcher被触发多次,它只会被扔进队列一次。 缓冲期间的重复数据删除对于防止不必要的计算和 DOM 操作非常重要。 然后,在下一个风暴循环“tick”中,vue 刷新队列以并行执行实际(重复数据删除)工作。

例如,当您设置 vm.someData = 'new value' 时,组件不会立即重新渲染。 当队列被刷新时,组件会在下一个风暴循环“tick”时更新。 大多数时候我们不需要关心这个过程,但是如果你想根据更新的 DOM 状态做一些事情,这可能会很棘手。 虽然 Vue.js 通常鼓励开发人员思考“数据驱动”并避免直接接触 DOM,但有时我们不得不这样做。 为了在数据更改后等待 Vue 完成更新 DOM,可以在数据更改后立即使用 Vue.nextTick(callback)。 这样 DOM 更新完成后就会调用回调函数。 例如:

<div id="example">{{message}}
var vm = new Vue({ el: '#example', data: { message: '123' }})vm.message = 'new message' // 更改数据vm.$el.textContent === 'new message' // falseVue.nextTick(function () { vm.$el.textContent === 'new message' // true})

在组件中使用 vm.$nextTick() 实例方法非常方便,因为它不需要全局 Vue,并且回调函数中的 this 会手动绑定到当前 Vue 实例:

Vue.component('example', {  template: '{{ message }}',  data: function () {    return {      message: '未更新'    }  },  methods: {    updateMessage: function () {      this.message = '已更新'      console.log(this.$el.textContent) // => '未更新'      this.$nextTick(function () {        console.log(this.$el.textContent) // => '已更新'      })    }  }})

由于 $nextTick() 返回一个 Promise,您可以使用新的 ES2017 async/await 语法来完成同样的事情:

methods: {  updateMessage: async function () {    this.message = '已更新'    console.log(this.$el.textContent) // => '未更新'    await this.$nextTick()    console.log(this.$el.textContent) // => '已更新'  }}

回到上面描述的现象,由于dom刷新是异步的,并且添加到一个队列中,类似于setTimeout异步队列,我们​​很难判断当前渲染帧中是否要刷新table sizestorm 。 因此,我们动态估计出长度/高度后,需要准确获取已经更新了dom元素的组件。 我们需要在nextTick函数中获取并执行刷新函数,这样就可以保证元素正常重绘,而不需要使用v-if强制刷新。

注意这里使用this.$nextTick是官方的方法。 我们还可以使用setTimeout(func, 20)来模拟nextTick函数,默认为20毫秒。 20毫秒是一个经验值,但建议使用nextTick函数。

8 Vue 中键值的作用

当 Vue.js 使用 v-for 更新渲染元素列表时jquery 元素 高度,它默认使用“就地重用”策略。 如果数据项的顺序发生改变,Vue 不会连接 DOM 元素来匹配数据项的顺序,而是简单地重用这里的每个元素,并确保它显示在特定索引处渲染的每个元素。 key的作用主要是高效更新虚拟DOM。

这块的关注点主要是动态组件和v-for的情况。 为了标记唯一的dom,键值通常采用像id这样唯一且常量的变量。 如果只是为了区分dom,所有元素不会频繁更新(增加Deletion)可以使用index索引

9 组件通信

1、父组件与子组件通信:子组件通过props属性绑定父组件的数据,实现双方的通信

2、子组件与父组件通信:通过$emit在子组件中触发父组件的扰动

3、非兄弟组件与兄弟组件之间的数据传输

所有 props 都会促进其父 props 和子 props 之间的双向下游绑定:从父 props 的更新流向子组件,但反之则不然。 这将避免意外地从子组件更改父组件的状态,从而使应用程序的数据流难以理解。

另外,每次父组件更新时,子组件中的所有 props 都会刷新为最新值。 这意味着您不应该更改子组件内的 props。 如果您这样做,Vue 将在浏览器的控制台中发出警告。

组件通信,结合4.2的部分,如果我是按钮,size、:disabled都是prop值,即父组件将值传递给子组件,这里有一点需要注意,静态数据绑定、类似size='small':disabled='false'都属于静态绑定,即不会根据父组件数据中的响应值动态改变。 这里有一个数据绑定的规则。 如果数据值是静态数据jquery 元素 高度,切成字符串,可以省略v-bind:如size='small',否则所有数据绑定都需要使用v-bind:,一般我们会省略,以引号开头,后面是绑定值,这个值也可以是各种Class数据类型、表达式,甚至是函数返回值,如:data='[1,2,3]' :data='list? list : []' :data='33' 等如果是布尔值则pass还有一种建议的写法,比如直接在组件中写我这里的按钮disabled就相当于:disabled ='真'

10 个插槽

这里简单介绍一下jack的概念。 编译组件时,可以提供两种传值形式:props和jack。 不同的是,槽位比道具的数值更加灵活多变,比如上面的按钮。

按钮中间的‘我是按钮’是插孔,这个插槽可以让你插入任何你想要的东西,比如

我是一个按钮,你可以将任何你想要自定义的内容插入到组件中,目前的前提是组件提供了默认的插孔,就像你小时候玩的卡带游戏机一样,直接插入卡带即可你想玩哪个游戏

但这还不够强大。 如果我认为当我插入内容时,默认情况下会有一个字符或元素。 这是您需要在组件中编写的内容...在您想要的默认元素内容的中间。

与电脑主板类似,不同的厂家也会按照共同的标准提供不同的插座和插孔,以方便用户按需扩展。 Vue的组件插孔也提供了这些方法。有时候我们也会有多个插孔,比如

<div class="container">  <header>      </header>  <main>      </main>  <footer>      </footer></div>

对于这种情况,元素有一个特殊的特征:名称。 此功能可用于定义附加插孔:

<div class="container">  <header>    <slot name="header"></slot>  </header>  <main>    <slot></slot>  </main>  <footer>    <slot name="footer"></slot>  </footer></div>

没有名称的退出将具有隐含名称“default”。

当向命名槽提供内容时,我们可以在元素上使用 v-slot 指令并将其名称作为 v-slot 的参数提供:

<base-layout>  <template v-slot:header>    <h1>Here might be a page title</h1>  </template>
<p>A paragraph for the main content.</p> <p>And another one.</p>
<template v-slot:footer> <p>Here's some contact info</p> </template></base-layout>

现在元素中的所有内容都将被传递到相应的套接字。 任何未包含在 v 槽中的内容都被假定为默认槽。

除了默认和命名的插孔之外,该插槽还用作作用域插孔。 例如,父组件插入子组件的插孔可以访问子组件的数据。 这是范围插孔。 具体使用可以参考 bin-ui, element-ui 中table的使用

11 混合混合

在新项目中使用vue实现数据绑定的朋友可能会发现每个vue实例下面都写了一行

js获取元素高度_元素高度扭曲怎么办_jquery 元素 高度

mixins:[mixin],这是做什么用的?

Mixins 提供了一种非常灵活的方式来在 Vue 组件中分发可重用功能。 mixin对象可以包含任意组件选项。当组件使用mixin对象时,mixin对象的所有选项都会“混合”到组件本身的选项中

Mixin混合在Vue开发中很常见,而且用法也很简单。 你只需要记住,所有的公共方法函数属性都可以放在mixin中,主要是为了代码复用,减少代码冗余,比如,公共请求封装,公共分页属性,公共查询跳转等都可以。

mixin的混合策略可以简单理解为以下几点

1. 数据对象,data中的属性,会被递归合并,类似于es6的扩展运算符,如果mixin中存在,则泽一组件定义的数据优先。

2、同名的钩子函数会合并链表,比如mounted,如果组件和mixin都定义了,就会执行,组件中的定义会被前置。 即先执行混入的代码。

3.同名函数将被覆盖。 与data中的属性类似,组件中的函数和mixin中的函数会递归合并,同名的会被覆盖。 这个和es5类似,同名函数会被覆盖,组件中的函数会覆盖混合函数。

12 vue如何获取dom元素

jQuery时代的核心是获取dom元素并进行一系列操作,但是如果vue数据驱动视图时需要获取dom元素(比如获取元素绘制echarts、绘制canvas),如何获取。

vue提供了先在dom元素中编译ref='table'的方式,看起来和设置id或者class类似,只是为了让vue识别。

获取方法也很简单,只需要 this.$refs.table 或 this.$refs['table'] 即可获取dom元素

如果你给一个vue组件设置ref,并使用this.$refs获取这个组件的实例,那么就可以通过这个实例调用组件的内部方法,比如上面提到的表格刷新方法。

即 this.$refs.table.handleResize()

13 为什么vue不触发响应式更新

造成这个问题的原因通常有两个。

1.未设置响应式对象属性的添加和删除

元素高度扭曲怎么办_jquery 元素 高度_js获取元素高度

由于现代 JavaScript 的限制(并且 Object.observe 早已被弃用),Vue 很难衡量对象属性的添加或删除。 由于 Vue 在初始化实例时会对属性执行 getter/setter 转换,因此该属性必须存在于数据对象上,Vue 才能将其转换为响应式。 例如:

var vm = new Vue({  data:{    a:1  }})// `vm.a` 是响应式的vm.b = 2// `vm.b` 是非响应式的

Vue 不允许向已创建的实例动态添加根级响应式属性。 但是,可以使用 Vue.set(object, propertyName, value) 方法向嵌套对象添加反应式属性。 例如,对于:

Vue.set(vm.someObject, 'b', 2)

您还可以使用 vm.$set 实例方法,它也是全局 Vue.set 方法的另一个名称:

this.$set(this.someObject,'b',2)

有时您可能需要为现有对象形式化多个新属性,例如使用 Object.assign() 或 _.extend()。 但是,添加到对象的新属性不会触发更新。 在这些情况下,您应该创建一个具有原始对象和要混合的对象的属性的新对象。

 // 代替 `Object.assign(this.someObject, { a: 1, b: 2 })`  this.someObject = Object.assign({}, this.someObject, { a: 1, b: 2 })

分析:这就是上面讨论的对象复制问题。 如果只是用注解的内容来扩展对象,这里的a和b其实就相当于写this.someObject.a=1,this.someObject.b=2。这里永远不会触发更新。

如果使用下面的形式来编码,实际上就相当于创建了一个新的对象,并且改变了整个响应对象someObject的引用地址。 所以vue重新触发更新。

2.设置数组中的一项索引值或改变链表的宽度

更改链表的宽度或设置一项

var vm = new Vue({  data(){  return{            list:[{id:1,name:’张三’},{id:2,name:’李四’}]        }  }})this.list[1]= {id:3,name:’王五’}
this.list.length = 1
实际输出的效果就是数据变化了但不会更新视图变化

数组问题有两种解决方案

创建一个新的链表来整体替换原来的链表值。

使用Js中的字段操作函数(本质上返回一个新的链表)也是链表的替换原理。 支持的方法有push、pop、shift、unshift、splice、sort、reverse 不支持的方法有filter、concat、slice

因此,当我们再次遇到链表操作时,一般建议创建一个新的链表来操作和更新视图,这里就是上面提到的深拷贝。 因为我们无法保证我们当前操作的链表是否包含对象或者其他引用类型。

最后结合上面提到的精确类型的判断,实现了一个递归调用的深拷贝功能

function  typeOf (obj) {  const  toString = Object.prototype.toString  const  map = {    '[object Boolean]': 'boolean',    '[object Number]': 'number',    '[object String]': 'string',    '[object Function]': 'function',    '[object Array]': 'array',    '[object Date]': 'date',    '[object RegExp]': 'regExp',    '[object Undefined]': 'undefined',    '[object Null]': 'null',    '[object Object]': 'object'  }  return map[toString.call(obj)]}// 深拷贝函数function  deepCopy (data) {  const t = typeOf(data)  let o  if (t === 'array') {    o = []  } else if (t === 'object') {    o = {}  } else {    return data  }  if (t === 'array') {    for (let i = 0; i < data.length; i++) {      o.push(deepCopy(data[i]))    }  } else if (t === 'object') {    for (let i in data) {      o[i] = deepCopy(data[i])    }  }  return o}