首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >前端常见vue面试题(必备)_2023-03-01

前端常见vue面试题(必备)_2023-03-01

原创
作者头像
用户10358241
发布于 2023-03-01 01:40:16
发布于 2023-03-01 01:40:16
9950
举报
文章被收录于专栏:前端面试题3前端面试题3

v-if和v-for哪个优先级更高

  • 实践中不应该把v-forv-if放一起
  • vue2中,v-for的优先级是高于v-if,把它们放在一起,输出的渲染函数中可以看出会先执行循环再判断条件,哪怕我们只渲染列表中一小部分元素,也得在每次重渲染的时候遍历整个列表,这会比较浪费;另外需要注意的是在vue3中则完全相反,v-if的优先级高于v-for,所以v-if执行时,它调用的变量还不存在,就会导致异常
  • 通常有两种情况下导致我们这样做:
    • 为了过滤列表中的项目 (比如 v-for="user in users" v-if="user.isActive")。此时定义一个计算属性 (比如 activeUsers),让其返回过滤后的列表即可(比如users.filter(u=>u.isActive)
    • 为了避免渲染本应该被隐藏的列表 (比如 v-for="user in users" v-if="shouldShowUsers")。此时把 v-if 移动至容器元素上 (比如 ulol)或者外面包一层template即可
  • 文档中明确指出永远不要把 v-ifv-for 同时用在同一个元素上,显然这是一个重要的注意事项
  • 源码里面关于代码生成的部分,能够清晰的看到是先处理v-if还是v-for,顺序上vue2vue3正好相反,因此产生了一些症状的不同,但是不管怎样都是不能把它们写在一起的

vue2.x源码分析

在vue模板编译的时候,会将指令系统转化成可执行的render函数

编写一个p标签,同时使用v-ifv-for

代码语言:html
AI代码解释
复制
<div id="app">
  <p v-if="isShow" v-for="item in items">
    {{ item.title }}
  </p>
</div>

创建vue实例,存放isShowitems数据

代码语言:javascript
AI代码解释
复制
const app = new Vue({
  el: "#app",
  data() {
    return {
      items: [
        { title: "foo" },
        { title: "baz" }]
    }
  },
  computed: {
    isShow() {
      return this.items && this.items.length > 0
    }
  }
})

模板指令的代码都会生成在render函数中,通过app.$options.render就能得到渲染函数

代码语言:javascript
AI代码解释
复制
ƒ anonymous() {
  with (this) { return 
    _c('div', { attrs: { "id": "app" } }, 
    _l((items), function (item) 
    { return (isShow) ? _c('p', [_v("\n" + _s(item.title) + "\n")]) : _e() }), 0) }
}
  • _lvue的列表渲染函数,函数内部都会进行一次if判断
  • 初步得到结论:v-for优先级是比v-if高
  • 再将v-forv-if置于不同标签
代码语言:html
AI代码解释
复制
<div id="app">
  <template v-if="isShow">
    <p v-for="item in items">{{item.title}}</p>
  </template>
</div>

再输出下render函数

代码语言:javascript
AI代码解释
复制
ƒ anonymous() {
  with(this){return 
    _c('div',{attrs:{"id":"app"}},
    [(isShow)?[_v("\n"),
    _l((items),function(item){return _c('p',[_v(_s(item.title))])})]:_e()],2)}
}

这时候我们可以看到,v-forv-if作用在不同标签时候,是先进行判断,再进行列表的渲染

我们再在查看下vue源码

源码位置:\vue-dev\src\compiler\codegen\index.js

代码语言:javascript
AI代码解释
复制
export function genElement (el: ASTElement, state: CodegenState): string {
  if (el.parent) {
    el.pre = el.pre || el.parent.pre
  }
  if (el.staticRoot && !el.staticProcessed) {
    return genStatic(el, state)
  } else if (el.once && !el.onceProcessed) {
    return genOnce(el, state)
  } else if (el.for && !el.forProcessed) {
    return genFor(el, state)
  } else if (el.if && !el.ifProcessed) {
    return genIf(el, state)
  } else if (el.tag === 'template' && !el.slotTarget && !state.pre) {
    return genChildren(el, state) || 'void 0'
  } else if (el.tag === 'slot') {
    return genSlot(el, state)
  } else {
    // component or element
    ...
}

在进行if判断的时候,v-for是比v-if先进行判断

最终结论:v-for优先级比v-if

vue3.0 特性你有什么了解的吗?

Vue 3.0 正走在发布的路上,Vue 3.0 的目标是让 Vue 核心变得更小、更快、更强大,因此 Vue 3.0 增加以下这些新特性:

(1)监测机制的改变

3.0 将带来基于代理 Proxy 的 observer 实现,提供全语言覆盖的反应性跟踪。这消除了 Vue 2 当中基于 Object.defineProperty 的实现所存在的很多限制:

  • 只能监测属性,不能监测对象
  • 检测属性的添加和删除;
  • 检测数组索引和长度的变更;
  • 支持 Map、Set、WeakMap 和 WeakSet。

新的 observer 还提供了以下特性:

  • 用于创建 observable 的公开 API。这为中小规模场景提供了简单轻量级的跨组件状态管理解决方案。
  • 默认采用惰性观察。在 2.x 中,不管反应式数据有多大,都会在启动时被观察到。如果你的数据集很大,这可能会在应用启动时带来明显的开销。在 3.x 中,只观察用于渲染应用程序最初可见部分的数据。
  • 更精确的变更通知。在 2.x 中,通过 Vue.set 强制添加新属性将导致依赖于该对象的 watcher 收到变更通知。在 3.x 中,只有依赖于特定属性的 watcher 才会收到通知。
  • 不可变的 observable:我们可以创建值的“不可变”版本(即使是嵌套属性),除非系统在内部暂时将其“解禁”。这个机制可用于冻结 prop 传递或 Vuex 状态树以外的变化。
  • 更好的调试功能:我们可以使用新的 renderTracked 和 renderTriggered 钩子精确地跟踪组件在什么时候以及为什么重新渲染。

(2)模板

模板方面没有大的变更,只改了作用域插槽,2.x 的机制导致作用域插槽变了,父组件会重新渲染,而 3.0 把作用域插槽改成了函数的方式,这样只会影响子组件的重新渲染,提升了渲染的性能。

同时,对于 render 函数的方面,vue3.0 也会进行一系列更改来方便习惯直接使用 api 来生成 vdom 。

(3)对象式的组件声明方式

vue2.x 中的组件是通过声明的方式传入一系列 option,和 TypeScript 的结合需要通过一些装饰器的方式来做,虽然能实现功能,但是比较麻烦。3.0 修改了组件的声明方式,改成了类式的写法,这样使得和 TypeScript 的结合变得很容易。

此外,vue 的源码也改用了 TypeScript 来写。其实当代码的功能复杂之后,必须有一个静态类型系统来做一些辅助管理。现在 vue3.0 也全面改用 TypeScript 来重写了,更是使得对外暴露的 api 更容易结合 TypeScript。静态类型系统对于复杂代码的维护确实很有必要。

(4)其它方面的更改

vue3.0 的改变是全面的,上面只涉及到主要的 3 个方面,还有一些其他的更改:

  • 支持自定义渲染器,从而使得 weex 可以通过自定义渲染器的方式来扩展,而不是直接 fork 源码来改的方式。
  • 支持 Fragment(多个根节点)和 Protal(在 dom 其他部分渲染组建内容)组件,针对一些特殊的场景做了处理。
  • 基于 treeshaking 优化,提供了更多的内置功能。

vue 中使用了哪些设计模式

1.工厂模式 - 传入参数即可创建实例

虚拟 DOM 根据参数的不同返回基础标签的 Vnode 和组件 Vnode

2.单例模式 - 整个程序有且仅有一个实例

vuex 和 vue-router 的插件注册方法 install 判断如果系统存在实例就直接返回掉

3.发布-订阅模式 (vue 事件机制)

4.观察者模式 (响应式数据原理)

5.装饰模式: (@装饰器的用法)

6.策略模式 策略模式指对象有某个行为,但是在不同的场景中,该行为有不同的实现方案-比如选项的合并策略

Vue 模板编译原理

Vue 的编译过程就是将 template 转化为 render 函数的过程 分为以下三步

代码语言:txt
AI代码解释
复制
第一步是将 模板字符串 转换成 element ASTs(解析器)
第二步是对 AST 进行静态节点标记,主要用来做虚拟DOM的渲染优化(优化器)
第三步是 使用 element ASTs 生成 render 函数代码字符串(代码生成器)

相关代码如下

代码语言:javascript
AI代码解释
复制
export function compileToFunctions(template) {
  // 我们需要把html字符串变成render函数
  // 1.把html代码转成ast语法树  ast用来描述代码本身形成树结构 不仅可以描述html 也能描述css以及js语法
  // 很多库都运用到了ast 比如 webpack babel eslint等等
  let ast = parse(template);
  // 2.优化静态节点
  // 这个有兴趣的可以去看源码  不影响核心功能就不实现了
  //   if (options.optimize !== false) {
  //     optimize(ast, options);
  //   }

  // 3.通过ast 重新生成代码
  // 我们最后生成的代码需要和render函数一样
  // 类似_c('div',{id:"app"},_c('div',undefined,_v("hello"+_s(name)),_c('span',undefined,_v("world"))))
  // _c代表创建元素 _v代表创建文本 _s代表文Json.stringify--把对象解析成文本
  let code = generate(ast);
  //   使用with语法改变作用域为this  之后调用render函数可以使用call改变this 方便code里面的变量取值
  let renderFn = new Function(`with(this){return ${code}}`);
  return renderFn;
}

为什么在 Vue3.0 采用了 Proxy,抛弃了 Object.defineProperty?

Object.defineProperty 本身有一定的监控到数组下标变化的能力,但是在 Vue 中,从性能/体验的性价比考虑,尤大大就弃用了这个特性。为了解决这个问题,经过 vue 内部处理后可以使用以下几种方法来监听数组

代码语言:txt
AI代码解释
复制
push();
pop();
shift();
unshift();
splice();
sort();
reverse();

由于只针对了以上 7 种方法进行了 hack 处理,所以其他数组的属性也是检测不到的,还是具有一定的局限性。

Object.defineProperty 只能劫持对象的属性,因此我们需要对每个对象的每个属性进行遍历。Vue 2.x 里,是通过 递归 + 遍历 data 对象来实现对数据的监控的,如果属性值也是对象那么需要深度遍历,显然如果能劫持一个完整的对象是才是更好的选择。 Proxy 可以劫持整个对象,并返回一个新的对象。Proxy 不仅可以代理对象,还可以代理数组。还可以代理动态增加的属性。

diff算法

代码语言:javascript
AI代码解释
复制
<details open=""><summary><b>答案</b></summary>
<p>
</p><p><strong>时间复杂度:</strong> 个树的完全<code> diff</code> 算法是一个时间复杂度为<code> O(n*3</code> ,vue进行优化转化成<code> O(n)</code></p>
<p><strong>理解:</strong></p>
<ul>
<li>
<p>最小量更新,<code> key</code> 很重要。这个可以是这个节点的唯一标识,告诉<code> diff</code> 算法,在更改前后它们是同一个DOM节点</p>
<ul>
<li>扩展<code> v-for</code> 为什么要有<code> key</code> ,没有<code> key</code> 会暴力复用,举例子的话随便说一个比如移动节点或者增加节点(修改DOM),加<code> key</code> 只会移动减少操作DOM</li>
</ul>
</li>
<li>
<p>只有是同一个虚拟节点才会进行精细化比较,否则就是暴力删除旧的,插入新的。</p>
</li>
<li>
<p>只进行同层比较,不会进行跨层比较。</p>
</li>
</ul>
<p><strong>diff算法的优化策略</strong>:四种命中查找,四个指针</p>
<ol>
<li>
<p>旧前与新前(先比开头,后插入和删除节点的这种情况)</p>
</li>
<li>
<p>旧后与新后(比结尾,前插入或删除的情况)</p>
</li>
<li>
<p>旧前与新后(头与尾比,此种发生了,涉及移动节点,那么新前指向的节点,移动到旧后之后)</p>
</li>
<li>
<p>旧后与新前(尾与头比,此种发生了,涉及移动节点,那么新前指向的节点,移动到旧前之前)</p>
</li>
</ol>
<p></p>
</details>

--- 问完上面这些如果都能很清楚的话,基本O了 ---

以下的这些简单的概念,你肯定也是没有问题的啦😉

Vue 组件间通信有哪几种方式?

代码语言:txt
AI代码解释
复制
Vue 组件间通信是面试常考的知识点之一,这题有点类似于开放题,你回答出越多方法当然越加分,表明你对 Vue 掌握的越熟练。Vue 组件间通信只要指以下 3 类通信:父子组件通信、隔代组件通信、兄弟组件通信,下面我们分别介绍每种通信方式且会说明此种方法可适用于哪类组件间通信。

(1)props / $emit 适用 父子组件通信

这种方法是 Vue 组件的基础,相信大部分同学耳闻能详,所以此处就不举例展开介绍。

(2)ref$parent / $children 适用 父子组件通信

  • ref:如果在普通的 DOM 元素上使用,引用指向的就是 DOM 元素;如果用在子组件上,引用就指向组件实例
  • $parent / $children:访问父 / 子实例

(3)EventBus ($emit / $on) 适用于 父子、隔代、兄弟组件通信

这种方法通过一个空的 Vue 实例作为中央事件总线事件中心),用它来触发事件和监听事件,从而实现任何组件间的通信,包括父子、隔代、兄弟组件。

(4)$attrs/$listeners 适用于 隔代组件通信

  • $attrs:包含了父作用域中不被 prop 所识别 (且获取) 的特性绑定 ( class 和 style 除外 )。当一个组件没有声明任何 prop 时,这里会包含所有父作用域的绑定 ( class 和 style 除外 ),并且可以通过 v-bind="$attrs" 传入内部组件。通常配合 inheritAttrs 选项一起使用。
  • $listeners:包含了父作用域中的 (不含 .native 修饰器的) v-on 事件监听器。它可以通过 v-on="$listeners" 传入内部组件

(5)provide / inject 适用于 隔代组件通信

祖先组件中通过 provider 来提供变量,然后在子孙组件中通过 inject 来注入变量。 provide / inject API 主要解决了跨级组件间的通信问题,不过它的使用场景,主要是子组件获取上级组件的状态,跨级组件间建立了一种主动提供与依赖注入的关系。

(6)Vuex 适用于 父子、隔代、兄弟组件通信

Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。每一个 Vuex 应用的核心就是 store(仓库)。“store” 基本上就是一个容器,它包含着你的应用中大部分的状态 ( state )。

  • Vuex 的状态存储是响应式的。当 Vue 组件从 store 中读取状态的时候,若 store 中的状态发生变化,那么相应的组件也会相应地得到高效更新。
  • 改变 store 中的状态的唯一途径就是显式地提交 (commit) mutation。这样使得我们可以方便地跟踪每一个状态的变化。

Vue3.0 和 2.0 的响应式原理区别

Vue3.x 改用 Proxy 替代 Object.defineProperty。因为 Proxy 可以直接监听对象和数组的变化,并且有多达 13 种拦截方法。

相关代码如下

代码语言:javascript
AI代码解释
复制
import { mutableHandlers } from "./baseHandlers"; // 代理相关逻辑
import { isObject } from "./util"; // 工具方法

export function reactive(target) {
  // 根据不同参数创建不同响应式对象
  return createReactiveObject(target, mutableHandlers);
}
function createReactiveObject(target, baseHandler) {
  if (!isObject(target)) {
    return target;
  }
  const observed = new Proxy(target, baseHandler);
  return observed;
}

const get = createGetter();
const set = createSetter();

function createGetter() {
  return function get(target, key, receiver) {
    // 对获取的值进行放射
    const res = Reflect.get(target, key, receiver);
    console.log("属性获取", key);
    if (isObject(res)) {
      // 如果获取的值是对象类型,则返回当前对象的代理对象
      return reactive(res);
    }
    return res;
  };
}
function createSetter() {
  return function set(target, key, value, receiver) {
    const oldValue = target[key];
    const hadKey = hasOwn(target, key);
    const result = Reflect.set(target, key, value, receiver);
    if (!hadKey) {
      console.log("属性新增", key, value);
    } else if (hasChanged(value, oldValue)) {
      console.log("属性值被修改", key, value);
    }
    return result;
  };
}
export const mutableHandlers = {
  get, // 当获取属性时调用此方法
  set, // 当修改属性时调用此方法
};

vue 中使用了哪些设计模式

1.工厂模式 - 传入参数即可创建实例

虚拟 DOM 根据参数的不同返回基础标签的 Vnode 和组件 Vnode

2.单例模式 - 整个程序有且仅有一个实例

vuex 和 vue-router 的插件注册方法 install 判断如果系统存在实例就直接返回掉

3.发布-订阅模式 (vue 事件机制)

4.观察者模式 (响应式数据原理)

5.装饰模式: (@装饰器的用法)

6.策略模式 策略模式指对象有某个行为,但是在不同的场景中,该行为有不同的实现方案-比如选项的合并策略

...其他模式欢迎补充

Vue 的生命周期方法有哪些 一般在哪一步发请求

beforeCreate 在实例初始化之后,数据观测(data observer) 和 event/watcher 事件配置之前被调用。在当前阶段 data、methods、computed 以及 watch 上的数据和方法都不能被访问

created 实例已经创建完成之后被调用。在这一步,实例已完成以下的配置:数据观测(data observer),属性和方法的运算, watch/event 事件回调。这里没有$el,如果非要想与 Dom 进行交互,可以通过 vm.$nextTick 来访问 Dom

beforeMount 在挂载开始之前被调用:相关的 render 函数首次被调用。

mounted 在挂载完成后发生,在当前阶段,真实的 Dom 挂载完毕,数据完成双向绑定,可以访问到 Dom 节点

beforeUpdate 数据更新时调用,发生在虚拟 DOM 重新渲染和打补丁(patch)之前。可以在这个钩子中进一步地更改状态,这不会触发附加的重渲染过程

updated 发生在更新完成之后,当前阶段组件 Dom 已完成更新。要注意的是避免在此期间更改数据,因为这可能会导致无限循环的更新,该钩子在服务器端渲染期间不被调用。

beforeDestroy 实例销毁之前调用。在这一步,实例仍然完全可用。我们可以在这时进行善后收尾工作,比如清除计时器。

destroyed Vue 实例销毁后调用。调用后,Vue 实例指示的所有东西都会解绑定,所有的事件监听器会被移除,所有的子实例也会被销毁。 该钩子在服务器端渲染期间不被调用。

activated keep-alive 专属,组件被激活时调用

deactivated keep-alive 专属,组件被销毁时调用

异步请求在哪一步发起?

可以在钩子函数 created、beforeMount、mounted 中进行异步请求,因为在这三个钩子函数中,data 已经创建,可以将服务端端返回的数据进行赋值。

如果异步请求不需要依赖 Dom 推荐在 created 钩子函数中调用异步请求,因为在 created 钩子函数中调用异步请求有以下优点:

  • 能更快获取到服务端数据,减少页面 loading 时间;
  • ssr 不支持 beforeMount 、mounted 钩子函数,所以放在 created 中有助于一致性;

Vue中组件生命周期调用顺序说一下

组件的调用顺序都是先父后子,渲染完成的顺序是先子后父

组件的销毁操作是先父后子,销毁完成的顺序是先子后父

加载渲染过程

代码语言:txt
AI代码解释
复制
父beforeCreate->父created->父beforeMount->子beforeCreate->子created->子beforeMount- >子mounted->父mounted

子组件更新过程

代码语言:txt
AI代码解释
复制
父beforeUpdate->子beforeUpdate->子updated->父updated

父组件更新过程

代码语言:txt
AI代码解释
复制
父 beforeUpdate -> 父 updated

销毁过程

代码语言:txt
AI代码解释
复制
父beforeDestroy->子beforeDestroy->子destroyed->父destroyed

你有对 Vue 项目进行哪些优化?

(1)代码层面的优化

  • v-if 和 v-show 区分使用场景
  • computed 和 watch 区分使用场景
  • v-for 遍历必须为 item 添加 key,且避免同时使用 v-if
  • 长列表性能优化
  • 事件的销毁
  • 图片资源懒加载
  • 路由懒加载
  • 第三方插件的按需引入
  • 优化无限列表性能
  • 服务端渲染 SSR or 预渲染

(2)Webpack 层面的优化

  • Webpack 对图片进行压缩
  • 减少 ES6 转为 ES5 的冗余代码
  • 提取公共代码
  • 模板预编译
  • 提取组件的 CSS
  • 优化 SourceMap
  • 构建结果输出分析
  • Vue 项目的编译优化

(3)基础的 Web 技术的优化

  • 开启 gzip 压缩
  • 浏览器缓存
  • CDN 的使用
  • 使用 Chrome Performance 查找性能瓶颈

了解nextTick吗?

异步方法,异步渲染最后一步,与JS事件循环联系紧密。主要使用了宏任务微任务(setTimeoutpromise那些),定义了一个异步方法,多次调用nextTick会将方法存入队列,通过异步方法清空当前队列。

Vuex中action和mutation的区别

mutation中的操作是一系列的同步函数,用于修改state中的变量的的状态。当使用vuex时需要通过commit来提交需要操作的内容。mutation 非常类似于事件:每个 mutation 都有一个字符串的 事件类型 (type) 和 一个 回调函数 (handler)。这个回调函数就是实际进行状态更改的地方,并且它会接受 state 作为第一个参数:

代码语言:javascript
AI代码解释
复制
const store = new Vuex.Store({
  state: {
    count: 1
  },
  mutations: {
    increment (state) {
      state.count++      // 变更状态
    }
  }
})

当触发一个类型为 increment 的 mutation 时,需要调用此函数:

代码语言:javascript
AI代码解释
复制
store.commit('increment')

而Action类似于mutation,不同点在于:

  • Action 可以包含任意异步操作。
  • Action 提交的是 mutation,而不是直接变更状态。
代码语言:javascript
AI代码解释
复制
const store = new Vuex.Store({
  state: {
    count: 0
  },
  mutations: {
    increment (state) {
      state.count++
    }
  },
  actions: {
    increment (context) {
      context.commit('increment')
    }
  }
})

Action 函数接受一个与 store 实例具有相同方法和属性的 context 对象,因此你可以调用 context.commit 提交一个 mutation,或者通过 context.state 和 context.getters 来获取 state 和 getters。

所以,两者的不同点如下:

  • Mutation专注于修改State,理论上是修改State的唯一途径;Action业务代码、异步请求。
  • Mutation:必须同步执行;Action:可以异步,但不能直接操作State。
  • 在视图更新时,先触发actions,actions再触发mutation
  • mutation的参数是state,它包含store中的数据;store的参数是context,它是 state 的父级,包含 state、getters

请说出vue cli项目中src目录每个文件夹和文件的用法

  • assets文件夹是放静态资源;
  • components是放组件;
  • router是定义路由相关的配置;
  • view视图;
  • app.vue是一个应用主组件;
  • main.js是入口文件

computed 的实现原理

computed 本质是一个惰性求值的观察者。

computed 内部实现了一个惰性的 watcher,也就是 computed watcher,computed watcher 不会立刻求值,同时持有一个 dep 实例。

其内部通过 this.dirty 属性标记计算属性是否需要重新求值。

当 computed 的依赖状态发生改变时,就会通知这个惰性的 watcher,

computed watcher 通过 this.dep.subs.length 判断有没有订阅者,

有的话,会重新计算,然后对比新旧值,如果变化了,会重新渲染。 (Vue 想确保不仅仅是计算属性依赖的值发生变化,而是当计算属性最终计算的值发生变化时才会触发渲染 watcher 重新渲染,本质上是一种优化。)

没有的话,仅仅把 this.dirty = true。 (当计算属性依赖于其他数据时,属性并不会立即重新计算,只有之后其他地方需要读取属性的时候,它才会真正计算,即具备 lazy(懒计算)特性。)

了解nextTick吗?

异步方法,异步渲染最后一步,与JS事件循环联系紧密。主要使用了宏任务微任务(setTimeoutpromise那些),定义了一个异步方法,多次调用nextTick会将方法存入队列,通过异步方法清空当前队列。

Vue中v-html会导致哪些问题

  • 可能会导致 xss 攻击
  • v-html 会替换掉标签内部的子元素
代码语言:javascript
AI代码解释
复制
let template = require('vue-template-compiler'); 
let r = template.compile(`<div v-html="'<span>hello</span>'"></div>`) 

// with(this){return _c('div',{domProps: {"innerHTML":_s('<span>hello</span>')}})} 
console.log(r.render);

// _c 定义在core/instance/render.js 
// _s 定义在core/instance/render-helpers/index,js
if (key === 'textContent' || key === 'innerHTML') { 
    if (vnode.children) vnode.children.length = 0 
    if (cur === oldProps[key]) continue // #6601 work around Chrome version <= 55 bug where single textNode // replaced by innerHTML/textContent retains its parentNode property 
    if (elm.childNodes.length === 1) { 
        elm.removeChild(elm.childNodes[0]) 
    } 
}

v-model 的原理?

我们在 vue 项目中主要使用 v-model 指令在表单 input、textarea、select 等元素上创建双向数据绑定,我们知道 v-model 本质上不过是语法糖,v-model 在内部为不同的输入元素使用不同的属性并抛出不同的事件:

  • text 和 textarea 元素使用 value 属性和 input 事件;
  • checkbox 和 radio 使用 checked 属性和 change 事件;
  • select 字段将 value 作为 prop 并将 change 作为事件。

以 input 表单元素为例:

代码语言:javascript
AI代码解释
复制
<input v-model='something'>

相当于

<input v-bind:value="something" v-on:input="something = $event.target.value">

如果在自定义组件中,v-model 默认会利用名为 value 的 prop 和名为 input 的事件,如下所示:

代码语言:javascript
AI代码解释
复制
父组件:
<ModelChild v-model="message"></ModelChild>

子组件:
<div>{{value}}</div>

props:{
    value: String
},
methods: {
  test1(){
     this.$emit('input', '小红')
  },
},

Vue 组件间通信有哪几种方式?

Vue 组件间通信是面试常考的知识点之一,这题有点类似于开放题,你回答出越多方法当然越加分,表明你对 Vue 掌握的越熟练。Vue 组件间通信只要指以下 3 类通信:父子组件通信、隔代组件通信、兄弟组件通信,下面我们分别介绍每种通信方式且会说明此种方法可适用于哪类组件间通信。

(1)props / $emit 适用 父子组件通信 这种方法是 Vue 组件的基础,相信大部分同学耳闻能详,所以此处就不举例展开介绍。

(2)ref 与 $parent / $children适用 父子组件通信

  • ref:如果在普通的 DOM 元素上使用,引用指向的就是 DOM 元素;如果用在子组件上,引用就指向组件实例
  • $parent / $children:访问父 / 子实例

(3)EventBus ($emit / $on) 适用于 父子、隔代、兄弟组件通信 这种方法通过一个空的 Vue 实例作为中央事件总线(事件中心),用它来触发事件和监听事件,从而实现任何组件间的通信,包括父子、隔代、兄弟组件。

(4)$attrs/$listeners适用于 隔代组件通信

  • $attrs:包含了父作用域中不被 prop 所识别 (且获取) 的特性绑定 ( class 和 style 除外 )。当一个组件没有声明任何 prop 时,这里会包含所有父作用域的绑定 ( class 和 style 除外 ),并且可以通过v-bind="$attrs" 传入内部组件。通常配合 inheritAttrs 选项一起使用。
  • $listeners:包含了父作用域中的 (不含 .native 修饰器的) v-on事件监听器。它可以通过 v-on="$listeners"传入内部组件

(5)provide / inject适用于 隔代组件通信 祖先组件中通过 provider 来提供变量,然后在子孙组件中通过 inject来注入变量。 provide / inject API主要解决了跨级组件间的通信问题,不过它的使用场景,主要是子组件获取上级组件的状态,跨级组件间建立了一种主动提供与依赖注入的关系。 (6)Vuex适用于 父子、隔代、兄弟组件通信 Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。每一个 Vuex 应用的核心就是 store(仓库)。“store” 基本上就是一个容器,它包含着你的应用中大部分的状态 ( state )。

  • Vuex 的状态存储是响应式的。当 Vue 组件从 store 中读取状态的时候,若 store 中的状态发生变化,那么相应的组件也会相应地得到高效更新。
  • 改变 store 中的状态的唯一途径就是显式地提交 (commit) mutation。这样使得我们可以方便地跟踪每一个状态的变化。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
linux下rsync+inotify实时同步
1、在A、B、C三台机器上分别执行yum -y install rsync xinetd
dogfei
2020/07/31
1.2K0
Centos下SFTP双机高可用环境部署记录
SFTP(SSH File Transfer Protocol),安全文件传送协议。有时也被称作 Secure File Transfer Protocol 或 SFTP。它和SCP的区别是它允许用户中断传输, SCP拷贝速度稍快一些。SFTP可以为传输文件提供一种安全的加密方法。 SFTP与FTP有着几乎一样的语法和功能。SFTP 为 SSH的一部分,是一种传输档案至Blogger伺服器的安全方式。其实在SSH软件包中,已经包含了一个叫作SFTP的 安全文件传输子系统,SFTP本身没有单独的守护进程,它必
洗尽了浮华
2018/01/23
3.4K0
常用rsync命令操作梳理
作为一个运维工程师,经常可能会面对几十台、几百台甚至上千台服务器,除了批量操作外,环境同步、数据同步也是必不可少的技能。 说到“同步”,不得不提的利器就是rsync。rsync不但可以在本机进行文件同步,也可以作为远程同步工具。 前面提到了rsync+inotify实时同步方案部署,下面结合本人近几年运维工作中对这一工具使用的经验,简单在此梳理下: rsync同步命令中常用的几个参数说明: -a, --archive 归档模式,表示以递归方式传输文件,并保持所有文件属性,等于-rlptgoD -v, --
洗尽了浮华
2018/01/22
1.9K0
使用 inotify 和 rsync 实现文件实时同步
在生产中有一种需求是,当目录下的文件数据发生变化时,就将数据备份到备份服务器上。实现这样的需求需要做到以下两点:
:Darwin
2023/07/05
2.1K0
CentOS7下Rsync+sersync实现数据实时同步
1、sersync是基于Inotify开发的,类似于Inotify-tools的工具
拓荒者
2019/03/11
1.3K0
CentOS7下Rsync+sersync实现数据实时同步
大点干!早点散----------rsync+inotify实现远程实时同步
rsync是linux系统下的数据镜像备份工具,使用快速增量备份工具remote sync可以远程同步,可以在不同主机之间进行同步,可以实现全量备份与增量备份,保持链接和权限,且采用优化的同步算法,传输前执行压缩,因此非常适合用于架构集中式的备份或异地备份等应用。同时rsync支持本地复制,或者与其他ssh、rsync主机同步。
不吃小白菜
2020/09/15
7820
基于rsync+inotify实现数据实时同步传输
前言 与传统的cp、tar备份方式相比,rsync具有安全性高、备份迅速、支持增量备份等优点, 通过rsync可以解决对实时性要求不高的数据备份需求,但随着文件数量的增大和实时同步的要求,rsync已不能满足需求,随之 rsync+inotify便应运而生。本文将讲解rsync的基础知识和如何基于rsync+inotify实现数据实时同步传输。 rsync相关介绍 rsync(remote sync)是一款快速增量备份工具(远程同步),支持本地复制,或者与其他SSH(安全传输)、rsync主机同步。
小小科
2018/05/02
1.6K0
基于rsync+inotify实现数据实时同步传输
rsync+inotify实现远程实时同步
rsync,英文全称是remote synchronize,是一款实现远程同步功能的免费软件,它在同步文件的同时,可以保持原来文件的权限、时间、软硬链接等附加信息。 rsync提供了一个客户机和远程文件服务器的文件同步的快速方法,而且可以通过ssh方式来传输文件。甚至还可以实现只同步一个文件里有变化的内容部分,所以可以实现快速的同步备份数据。同时,rsync还可以实现同步本地数据、删除文件和目录的功能。
星哥玩云
2022/07/14
8010
rsync+inotify实现远程实时同步
Linux 环境下实战 Rsync 备份工具及配置 rsync+inotify 实时同步
Rsync 是一个开源的快速备份工具,是Linux和UNIX操作系统默认安装的组件之一,可在不同主机间镜像同步整个目录,并支持增量备份文件传输,保持链接和权限,采用优化的同步算法,传输前执行压缩,适用于异地备份,镜像服务器等应用。
杰哥的IT之旅
2020/06/18
2.1K0
采用Rsync与Inotify实时同步文件目录
描述: Rsync(remote synchronize)是一个提供快速增量文件传输的开源实用程序, rsync是根据GNU通用公共许可证免费提供的,目前由Wayne Davison维护。
全栈工程师修炼指南
2022/09/28
3.5K0
采用Rsync与Inotify实时同步文件目录
配置rsync+inotify实现站点文件实时同步
rsync /etc/fstab /opt rsync -rl /etc/fstab /boot/grub /opt
星哥玩云
2022/07/14
1.1K0
Linux服务器使用rsync+inotify实现实时同步
rsync是linux系统下的数据镜像备份工具。使用快速增量备份工具Remote Sync可以远程同步,支持本地复制,或者与其他SSH、rsync主机同步。
西门呀在吹雪
2020/11/09
7.3K0
inotify+rsync数据的实时同步
inotify可以监控同步数据服务器目录中信息的变化,采用异步的文件系统事件监控机制,利用事件驱动机制,而无须通过诸如cron等的轮询机制来获取事件,linux内核从2.6.13起支持 inotify,通过inotify可以监控文件系统中添加、删除,修改、移动等各种事件。
用户9949933
2023/02/24
6360
rsync+inotify实现数据单向实时同步
主服务器端,向从服务器端实时同步数据 master端IP地址:192.168.1.39(node1) slave端IP地址:192.168.1.40 (node2) 一、配置从服务器 在从服务器安装rsync,创建并配置rsync文件。
星哥玩云
2022/07/04
5060
inotify 高效改进版 sersync 结合 rsync 实现数据实时增量同步
sersync主要用于服务器同步,web镜像等功能。基于boost1.43.0,inotify api,rsync command.开发。
为为为什么
2022/08/06
2.3K0
Linux之rsync数据同步服务
1.Rsync基本概述 Rsync是开源多功能同步工具,支持多种操作系统 Rsync支持本地复制(优于scp,cp)与远程同步 Rsync支持全量备份,增量备份 Rsync基于C/S架构,默认监听tcp873端口
星哥玩云
2022/07/14
2.1K0
Linux下rsync+inotfy/sersync实现数据实时同步
导读:本文主要讲解了如何利用 rsync+inotfy/sersync 实现数据实时同步的操作过程和部分原理、参数。
开心分享
2020/08/11
1.4K0
Linux下rsync+inotfy/sersync实现数据实时同步
使用rsync+inotify实现nginx配置实时同步
源服务器的密码文件不用指定用户名,用户名在使用同步命令的时候才用到,目前源服务器的准备工作已经完成了。
御坂妹
2024/01/17
7210
rsync+inotify实时同步
1.rsync 与传统的cp、tar备份方式相比,rsync具有安全性高、备份迅速、支持增量备份的优点,通过rsync可以解决对实时性要求不高的数据备份需求,例如定期的备份文件服务器数据到远端服务器,对本地磁盘定期做数据镜像等。 随着应用系统规模不断的扩大,对数据安全性和可靠性也提出了更高的要求,rsync在高端业务中也逐渐暴露出许多不足。首先,rsync实时同步时,需要扫描所有的文件进行比对,进行差量传输。如果文件数量打到了百万甚至千万量级,扫描所有的文件是非常耗时的,而且正在发生变化的往往是其中很少一部
用户1173509
2018/01/17
1.5K0
linux实时文件事件监听--inotify
inotify是Linux内核2.6.13 (June 18, 2005)版本新增的一个子系统(API),它提供了一种监控文件系统(基于inode的)事件的机制,可以监控文件系统的变化如文件修改、新增、删除等,并可以将相应的事件通知给应用程序。该机制由著名的桌面搜索引擎项目beagle引入用于替代此前具有类似功能但存在诸多缺陷的dnotify。
sunsky
2020/08/20
13.9K1
推荐阅读
相关推荐
linux下rsync+inotify实时同步
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档