龙空技术网

07>详述vue的生命周期、组件间如何通信?

web前端君 72

前言:

此刻各位老铁们对“兄弟css”大致比较着重,兄弟们都需要知道一些“兄弟css”的相关资讯。那么小编在网摘上网罗了一些对于“兄弟css””的相关文章,希望咱们能喜欢,各位老铁们一起来学习一下吧!

Vue1. Vue的双向数据绑定原理是什么?

答案:

vue.js 是采用数据劫持结合发布者-订阅者模式的方式,通过Object.defineProperty()来劫持各个属性的setter,getter,在数据变动时发布消息给订阅者,触发相应的监听回调。

具体步骤:

第一步:需要observe的数据对象进行递归遍历,包括子属性对象的属性,都加上 setter和getter

这样的话,给这个对象的某个值赋值,就会触发setter,那么就能监听到了数据变化;

第二步:compile解析模板指令,将模板中的变量替换成数据,然后初始化渲染页面视图,并将每个指令对应的节点绑定更新函数,添加监听数据的订阅者,一旦数据有变动,收到通知,更新视图;

第三步:Watcher订阅者是Observer和Compile之间通信的桥梁,主要做的事情是:

1、在自身实例化时往属性订阅器(dep)里面添加自己

2、自身必须有一个update()方法

3、待属性变动dep.notice()通知时,能调用自身的update()方法,并触发Compile中绑定的回调,则功成身退。

第四步:MVVM作为数据绑定的入口,整合Observer、Compile和Watcher三者,通过Observer来监听自己的model数据变化,通过Compile来解析编译模板指令,最终利用Watcher搭起Observer和Compile之间的通信桥梁,达到数据变化 -> 视图更新;视图交互变化(input) -> 数据model变更的双向绑定效果。

2. 请详细说下你对vue生命周期的理解

答案:

总共分为8个阶段创建前/后,载入前/后,更新前/后,销毁前/后。

创建前/后: 在beforeCreated阶段,vue实例的挂载元素$el和数据对象data都为undefined,还未初始化。在created阶段,vue实例的数据对象data有了,$el还没有。

载入前/后:在beforeMount阶段,vue实例的$el和data都初始化了,但还是挂载之前为虚拟的dom节点,data.message还未替换。在mounted阶段,vue实例挂载完成,data.message成功渲染。

更新前/后:当data变化时,会触发beforeUpdate和updated方法。

销毁前/后:在执行destroy方法后,对data的改变不会再触发周期函数,说明此时vue实例已经解除了事件监听以及和dom的绑定,但是dom结构依然存在

3. 封装 vue 组件的过程

答案:

首先,组件可以提升整个项目的开发效率。能够把页面抽象成多个相对独立的模块,解决了我们传统项目开发:效率低、难维护、复用性等问题。

然后,使用Vue.extend方法创建一个组件,然后使用Vue.component方法注册组件。子组件需要数据,可以在props中接受定义。而子组件修改好数据后,想把数据传递给父组件。可以采用emit方法。

4. mvc与mvvm

答案:

MVC

模型-视图-控制器(Model-View-Controller)

Model和View永远不能相互通信,只能通过Controller传递。

Controller可以直接与Model对话(读写调用Model),Model通过Notification和KVO机制与Controller间接通信。

Controller可以直接与View对话,通过outlet,直接操作View,outlet直接对应到View中的控件,View通过action向Controller报告事件的发生(如用户Touch我了)。Controller是View的直接数据源(数据很可能是Controller从Model中取得并经过加工了)。Controller是View的代理(delegate),以同步View与Controller。

MVVM

Model -ViewModel - View

什么是 MVVM:一个 MVC 的增强版,我们正式连接了视图和控制器,并将表示逻辑从 Controller 移出放到一个新的对象里,即 View Model。MVVM 听起来很复杂,但它本质上就是一个精心优化的 MVC 架构

Model层是少不了的了,我们得有东西充当DTO(数据传输对象),当然,用字典也是可以的,编程么,要灵活一些。Model层是比较薄的一层,如果学过Java的小伙伴的话,对JavaBean应该不陌生吧。

ViewModel层,就是View和Model层的粘合剂,他是一个放置用户输入验证逻辑,视图显示逻辑,发起网络请求和其他各种各样的代码的极好的地方。说白了,就是把原来ViewController层的业务逻辑和页面逻辑等剥离出来放到ViewModel层。

View层,就是ViewController层,他的任务就是从ViewModel层获取数据,然后显示。

5. Vue首屏加载非常慢,如何解决?

答案:

Vue首屏加载非常慢

原因: 当打包应用时,将所有JavaScript代码打包在一个文件中,导致js代码非常庞大,严重影响页面加载速度。

解决:

1. 配置打包工具,将组件分别打包到不同的js代码块中

build/webpack.base.conf.js

output:{

path: config.build.assetsRoot,

filename:’[name].js’,

//新增

chunkFilename:”[name].js”,

publicPath: process.env.NODE_ENV===”production”

?config.build.assetsPublicPath

:config.dev.assetsPublicPath

}

2. 当路由请求到该组件时,才动态加载组件的内容

路由字典中,路由配置和以前完全一样

但是在引入组件对象时:

import Index from ‘@/views/Index.vue’

改为

const Index=()=>import(‘@/views/Index.vue’)//仅定义函数

//暂未执行

//暂时不引入Index.vue

当用户在vue中请求当前组件对应的路由地址时,由vue-router自动调用加载函数,动态请求Index.vue组件对象

6. 实现订阅/发布者模式?

答案:

var ublisher = {};

// 定义发布者

publisher.list =[];

// 缓存列表 存放订阅者回调函数

// 增加订阅者

publisher.listen =function(fn){

publisher.list.push(fn);

// 订阅消息添加到缓存列表

}

// 发布消息

publisher.trigger =function(){

for(vari = 0,fn; fn = this.list[i++];){

var that =this

fn.apply(null,arguments);

}

}

7. 什么是虚拟DOM树:

答案:

什么是: 仅包含可能变化的节点和可能变化的属性的树结构

<body>

<div id=”app”>

<img src=”logo.png”> alt title id ….

<h1>{{uname}}</h1>id class title name

<hr>

<h2>{{score}}</h2>

</div>

{

el:”#app”,

children:[

{el:”h1”, innerText:uname},

{el:”h2”,innerText:score}

]

}

为什么: 内容少,便于快速遍历比较不同

如何发挥作用:

当data中模型变量改变时,会通知虚拟DOM树

虚拟DOM树先缓存本次的修改在元素对象上

将一批修改生成新的DOM子树和原虚拟DOM树做对比。

一旦发现不同的元素或内容,就只更新有修改的元素

虚拟DOM树中,封装了传统DOM API: createElement() appendChild() .innerHTML,避免了程序员编写大量重复的代码。

8. Vue 如何去除url中的 #

答案:

vue-router 默认使用 hash 模式,所以在路由加载的时候,项目中的 url 会自带 #。如果不想使用 #, 可以使用 vue-router 的另一种模式 history

new Router({

mode: 'history',

routes: [ ]

})

需要注意的是,当我们启用 history 模式的时候,由于我们的项目是一个单页面应用,所以在路由跳转的时候,就会出现访问不到静态资源而出现 404 的情况,这时候就需要服务端增加一个覆盖所有情况的候选资源:如果 URL 匹配不到任何静态资源,则应该返回同一个 index.html 页面

9. Vue组件间如何通信:

答案:

组件通信

①父组件向子组件通信:

子组件通过 props 属性,绑定父组件数据,实现双方通信;

②子组件向父组件通信:

将父组件的事件在子组件中通过 $emit 触发;

③非父子组件、兄弟组件之间的数据传递:

/*新建一个Vue实例作为中央事件总嫌*/

let event = new Vue();

/*监听事件*/

event.$on('eventName', (val) => {

//......do something

});

/*触发事件*/

event.$emit('eventName', 'this is a message.')

标签: #兄弟css