vue 2.x 随笔 1-响应式系统

0. 看就完事了

参考阮总博客,还就那个轻松愉快 …
阮一峰 MVC,MVP和MVVM的图示

官方教程,多的不谈
VUE 深入响应式原理

官方API文档
内置的组件

Fundebug .cnblog 偶然看到的
详解Vue中的DOM

边城 .segmentfault 运气好才搜到的
揭密 Vue 的双向绑定

1.vm内置对象

1.1 computed

实现:相当于为该对象的protype声明了一个getter
执行:监听该属性的依赖属性是否变化
缓存:计算属性依赖于响应式依赖进行(像data那样的动态绑定)

1.2 watch

一个好的选择:通过监听状态来减少一个大函数的调用
执行:监听该属性是否变化
当需要侦听this.a.b时,需要这么写:‘a.b’
watch中使用箭头函数时候,this可能为undefined
如果侦听触发时不改变值,只是调用一个过程,可以直接a:‘methods中的方法名’
可选的内置属性:
handler:waitch的默认属性,类型是一个方法(val, oldVal)
deep:支持对对象内部属性的监听
immediate:watch开启时候的初始值赋值,也将触发一次

1.3 filter

实现:基于js原生的filter()方法
执行:每个渲染周期都会重新执行
模板渲染中支持管道符拼接多个filter

1.4 prop

声明时候,注意’-'和驼峰风格的使用

注意单向数据流 & js引用传递 的影响

prop属性中可以设置类型验证、默认、自定义验证函数

有了 inheritAttrs: false 和 $attrs,你就可以手动决定这些 attribute 会被赋予哪个元素

prop适合赋值子组件的初始值,但是该属性并不是只在初始化的生命周期中生效,具备data那样的动态绑定能力

子组件不能给自己的prop赋值,建议通过声明一个中间量(computed、data)

2. 指令

2.1 条件渲染

v-if 成立时渲染,不成立即销毁
v-show 初始化渲染,基于css的样式切换
v-for 拥有较高的渲染优先级

3.Vue内置函数

全局均可以引用(即Vue.xxx()),可简写作$xxx()

3.1 $el

找到dom元素

var data = { a: 1 }
var vm = new Vue({
  el: '#example',
  data: data
})
vm.$data === data // => true
vm.$el === document.getElementById('example') // => true

3.2 $set

vue实例对象(官网写作’vm’)创建之后添加新的属性到实例上,它不会触发视图更新,因此直接使用data.xxx = xxx的赋值方式,并且该属性getter/setter没有被声明时候,这将导致vue的v-vm绑定失败,因此这样修改之后是无法动态响应到view的

vue响应系统 ,把一个普通 Javascript 对象传给 Vue 实例来作为它的 data 选项,Vue 将遍历它的属性,用 Object.defineProperty 将它们转为 getter/setter,如上示例,可以将data在控制台打印出来看

new Vue({
	data:(){
		return {
			queryParam:{},	//这么写,是一个空对象,该对象将自动声明存取器,但是内部属性未显式声明,将不具备存取器
			//queryParam:{time:'',}	//这么写,将自动具备存取器
			},
		};
	},
	mounted:function(){
		this.queryParam.time = xxx;	//这样是无法生效的,因为此时this.queryParam.time对象并没有getter/setter
		this.$set(this.queryParam,'time',xxx);
	},
});

3.3 $nextTick

当赋值数据时候,dom初始化完成。因此对未来(其实就是下一次异步更新队列的执行tick,可见update生命周期)更新后的视图进行操作可以使用这个

dom未初始化,常发生在vue生命周期钩子中

mounted()并不能保证所有的子组件全部完成挂载

new Vue({
	...
  mounted:function() {
    get: function () {
      this.$http.get('/api/article').then(function (res) {
        this.list = res.data.data.list
        // ref  list 引用了ul元素,我想把第一个li颜色变为红色
        this.$refs.list.getElementsByTagName('li')[0].style.color = 'red'
      })
    },
  }
})

3.4 $forceUpdate

强制触发update生命周期,从而刷新视图、数据,

在这里插入图片描述

如果你发现你自己需要在 Vue 中做一次强制更新,99.9% 的情况,是你在某个地方做错了事。

当数据的层次过于复杂时候,可以使用$forceUpdate

3.5 $emit

触发对应事件名(建议使用kebab-case风格命名)的事件。

常用于组件间的事件传递:

子组件命名自定义事件名,并在底层组件(子组件的子组件)的事件回调中emit
父组件则将事件实现赋予(v-on)其子组件的自定义事件中
[实质是将自定义事件(底层事件的具体实现)作为底层事件的回调]	//原谅这波拉跨的表达

类似的$on、$off、$once 就不谈了

3.6 $event

基于js原生的event内置对象,因此vue官方文档说可以用作触发子组件的原生dom事件。

对于event对象的用法,vue一样支持,懒得展开细说了。如需回炉重造,见阮总的js教程。

4.修饰符

组件prop属性的修饰符

4.1 sync

可以实现 看起来像父子组件“双向绑定” 一样的效果,建议子组件在computed中声明一个传递prop值的变量,并重写其get/set(get=>返回prop;set=>this.$emit(‘update:prop’,newValue)),这是“双向绑定”相对(相对于自定义v-model、emit()回调父类事件)优雅的一种实现

5.vm的一些内置属性的加载顺序

见源码:

function initState (vm) {
        vm._watchers = [];
        var opts = vm.$options;
        if (opts.props) { initProps(vm, opts.props); }
        if (opts.methods) { initMethods(vm, opts.methods); }
        if (opts.data) {
            initData(vm);
        } else {
            observe(vm._data = {}, true /* asRootData */);
        }
        if (opts.computed) { initComputed(vm, opts.computed); }
        if (opts.watch && opts.watch !== nativeWatch) {
            initWatch(vm, opts.watch);
        }
    }

6.响应式

6.1 组件内的响应式

当你把一个普通的 JavaScript 对象传入 Vue 实例作为 data 选项,Vue 将遍历此对象所有的 property,并使用 Object.defineProperty 把这些 property 全部转为 getter/setter。

6.2 组件间的响应式

每个组件实例都对应一个 watcher 实例,它会在组件渲染的过程中把“接触”过的数据 property 记录为依赖。之后当依赖项的 setter 触发时,会通知 watcher,从而使它关联的组件重新渲染。

6.3 特殊的响应式处理

由于 JavaScript 的限制,Vue 不能检测数组和对象的变化。尽管如此我们还是有一些办法来回避这些限制并保证它们的响应性。
对象->$set()
数组->slice()
通用、优雅,但是有失性能的深度监听

6.4 虚拟dom

Vue.js通过编译将template 模板转换成渲染函数(render ) ,执行渲染函数就可以得到一个虚拟节点树

在对 Model 进行操作的时候,会触发对应 Dep 中的 Watcher 对象。Watcher 对象会调用对应的 update 来修改视图。这个过程主要是将新旧虚拟节点进行差异对比,然后根据对比结果进行DOM操作来更新视图。

在这里插入图片描述

6.4.1 模板字符串的编译

官方推荐的(默认选项,runtime-only build),模板<template></template>在构建阶段被编译成js,因此打包阶段需要加入运行时的包即可(即官方文档的说法:编译器+运行时)
官方同时提供了完整版的包(编译+运行,compiler-included build),允许用户直接使用模板字符串在客户端(浏览器)直接生成dom并挂载在html标签中
	这是vue 2.x 不同于vue 1.x的一点 => 不推荐走直接挂载dom => 建议走vnode(虚拟dom节点)方式
	如果不嫌麻烦,也可以有替代方案 => vue.render(),使用该方法则不需要完整打包,compile the templates into render functions

6.5 vue建议数据驱动,而不是直接操作dom

这和目前主流所推崇的渲染方式是契合的,并不是vue一意孤行,angular、react都有这种异步的渲染操作。

6.5.1 就vue而言,直接操作dom带来的问题

结构上:破坏组件的封装性,在一个组件的代码中引用另一组件,增加了组件见的耦合

设计上:与vue的响应式相违背,vue的异步更新队列在watch到数据变动后,将开启一个队列缓冲一个tick内的数据变化、dom操作,并在下一个tick中执行。因此绕过数据来操作dom,很可能将导致不可预见的局面。

7.插槽

7.1 概述

插槽在渲染时将对应的模板代码合成为组件的一部分

可以提供一个默认的slot标签子节点作为默认的插槽内容
(后备内容)

父级模板里的所有内容都是在父级作用域中编译的;子模板里的所有内容都是在子作用域中编译的。

7.2 具名插槽

不带 name 的 <slot> 出口会带有隐含的名字“default”

7.2 作用域插槽

允许插槽的模板代码像props那样访问子组件

8.组件

8.1 内置组件

8.1.1 <component>

支持使用key、ref、is属性,甚至可以使用目标组件的prop予其赋值

9. vue devtools

浏览器的扩展商店里面搜索下载即可

可查看组件的属性值的变化
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

肯尼思布赖恩埃德蒙

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值