vue 用key拿对象value_带你了解 vue-next(Vue 3.0)之 初入茅庐【实践】

vue 用key拿对象value_带你了解 vue-next(Vue 3.0)之 初入茅庐【实践】_第1张图片

作者:大转转FE

转发链接:https://mp.weixin.qq.com/s/gZVn9eDruyv7G_UJFTPuGQ

前言

这几天,陆续学习了解了关于vue-next(Vue 3.0)(https://github.com/vuejs/vue-next)的一些新特性,尤其是新的 CompositionAPI的用法。这套新的API中最重要、最核心的部分,恐怕就是实现响应式功能的这一块了。而且,这套响应式API不仅可以在 vue-next环境下使用,也可以独立使用。

笔者在阅读源码看到, vue-next已全部由 TypeScript构建,看来 ts 必学技能。接下来带你了解vue-next。

vue-next计划并已实现的主要架构改进和新功能:

  • 使用模块化架构
  • 优化 "Block tree"
  • 更激进的 static tree hoisting 功能
  • 支持 Source map
  • 内置标识符前缀(又名 "stripWith")
  • 内置整齐打印(pretty-printing)功能
  • 移除 source map 和标识符前缀功能后,使用 Brotli 压缩的浏览器版本精简了大约 10KB

运行时(Runtime)的更新主要体现在以下几个方面:

  • 速度显著提升
  • 同时支持 Composition API 和 Options API,以及 typings
  • 基于 Proxy 实现的数据变更检测
  • 支持 Fragments
  • 支持 Portals
  • 支持 Suspense w/ async setup()

最后,还有一些 2.x 的功能尚未移植过来,如下:

  • SFC compiler
  • Server-side rendering (服务端渲染SSR)

==目前不支持IE11==

vue-next(Vue 3.0) 的源码虽然发布了,但是预计最早也需要等到 2020 年第一季度才有可能发布 3.0 正式版。

目录剖析

代码仓库中有个 packages 目录,里面主要是 vue-next 的相关源码功能实现,具体内容如下所示。

vue 用key拿对象value_带你了解 vue-next(Vue 3.0)之 初入茅庐【实践】_第2张图片
  • compiler-core:平台无关的编译器,它既包含可扩展的基础功能,也包含所有平台无关的插件。暴露了 AST 和 baseCompile 相关的 API,它能把一个字符串变成一棵 AST
  • compiler-dom:基于compiler-core封装针对浏览器的compiler
  • runtime-core:与平台无关的运行时环境。支持实现的功能有虚拟 DOM 渲染器、Vue 组件和 Vue 的各种API, 可以用来自定义 renderer ,vue2中也有
  • runtime-dom:针对浏览器的 runtime。其功能包括处理原生 DOM API、DOM 事件和 DOM 属性等, 暴露了重要的render和createApp方法
const { render, createApp } = createRenderer({  patchProp,  ...nodeOps})export { render, createApp }
  • runtime-test:一个专门为了测试而写的轻量级 runtime。比如对外暴露了renderToString方法,在此感慨和react越来越像了
  • server-renderer:用于 SSR,尚未实现。
  • shared:没有暴露任何 API,主要包含了一些平台无关的内部帮助方法。
  • vue:「完整」版本,引用了上面提到的 runtime 和 compiler目录。入口文件代码如下
'use strict'if (process.env.NODE_ENV === 'production') {  module.exports = require('./dist/vue.cjs.prod.js')} else {  module.exports = require('./dist/vue.cjs.js')}
  • 所以想阅读源码,还是要看构建流程,这个和vue2也是一致的

回顾 Vue2.0 响应式原理机制 - defineProperty

这个原理老生常谈了,就是拦截对象,给对象的属性增加 set 和 get方法,因为核心是 defineProperty所以还需要对数组的方法进行拦截

对对象进行拦截

function observer(target){  // 如果不是对象数据类型直接返回即可  if(typeof target !=='object'){  return target}  // 重新定义key  for(let key in target){    defineReactive(target,key,target[key])  }}function update(){  console.log('update view')}function defineReactive(obj,key,value){  observer(value); // 有可能对象类型是多层,递归劫持  Object.defineProperty(obj,key,{    get(){      // 在get 方法中收集依赖      return value    },    set(newVal){      if(newVal !== value){        observer(value);        update(); // 在set方法中触发更新      }    }  })}const obj ={name:'zhuanzhuan'}observer(obj);obj.name ='new-name';
输出:update view

数组方法劫持

const oldProtoMehtods = Arrayprototypeconst proto = Object.create(oldProtoMehtods)function update(){  console.log('update view')}function defineReactive(obj,key,value){  observer(value) // 有可能对象类型是多层,递归劫持  Object.defineProperty(obj,key,{    get(){      // 在get 方法中收集依赖      return value    },    set(newVal){      if(newVal !== value){        observer(value)        update() // 在set方法中触发更新      }    }  })}['push','pop','shift','unshift'].forEach(method=>{  Object.defineProperty(proto, method,{    get(){      update()      return oldProtoMehtods[method]    }  })})function observer(target){  if(typeof target !== 'object'){    return target  }  // 如果不是对象数据类型直接返回即可  if(Array.isArray(target)){    Object.setPrototypeOf(target, proto)    // 给数组中的每一项进行observr    for(let i = 0 ; i < target.length; i++){      observer(target[i])    }    return  }  // 重新定义key  for(let key in target){    defineReactive(target, key, target[key])  }}let obj = {hobby:[{name:'zhuanzhuan'}]}observer(obj)// 使用['push','pop','shift','unshift'] 方法,更改数组会触发视图更新obj.hobby.push('转转')// 更改数组中的对象也会触发视图更新obj.hobby[0].name = 'new-name'console.log(obj.hobby)
输出:update viewupdate view[ { name: [Getter/Setter] }, '转转' ]

Object.defineProperty缺点:

  • 无法监听数组的变化
  • 需要深度遍历,浪费内存

vue-next 预备知识

无论是阅读这篇文章,还是阅读 vue-next 响应式模块的源码,首先有两个知识点是必备的:

  • Proxy(https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Proxy):对象用于定义基本操作的自定义行为(如属性查找,赋值,枚举,函数调用等)。ES6 中新的代理内建工具类。
  • Reflect(https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Reflect):是一个内置的对象,它提供拦截 JavaScript 操作的方法。这些方法与proxy handlers的方法相同。Reflect不是一个函数对象,因此它是不可构造的。ES6 中新的反射工具类

Proxy

let data=[1,2,3]let p=new Proxy(data,{get(target,key){console.log('获取值:',key)return target[key]},set(target,key,value){console.log('修改值:',key,value)target[key]=valuereturn true}})p.push(4)
输出:获取值: push获取值:length修改值:3 4修改值: length 4

比 defineproperty优秀的 就是数组和对象都可以直接触发 getter和 setter, 但是数组会触发两次,因为获取 push和修改 length的时候也会触发

Proxy 取代 deineProperty 除了性能更高以外,还有以下缺陷,也是为啥会有$set,$delete的原因 :

  1. 属性的新加或者删除也无法监听;
  2. 数组元素的增加和删除也无法监听

Reflect

let data = [1,2,3]let p = new Proxy(data,{get(target,key){    console.log('获取值:',key)    return Reflect.get(target,key)},    set(target,key,value){    console.log('修改值:',key,value)    return Reflect.set(target,key,value)}})p.push(4)
输出:获取值: push获取值: length修改值: 3 4修改值: length 4

多次触发和深层嵌套问题

let data={name:{title:'zhuanzhuan'}}let p= new Proxy(data,{get(target,key){    console.log('获取值:',key)    return Reflect.get(target,key)},    set(target,key,value){    console.log('修改值:',key,value)    return Reflect.set(target,key,value)}})p.name.title = 'xx'
输出:获取值: name

之后会带你看下 vue-next是怎么解决的。

初始化项目

依赖 项目 vue.global.js【推荐】

  1. clone 项目

$ git clone https://github.com/vuejs/vue-next.git

  1. 编辑文件

$ npm run dev

  1. 拷贝文件,运行上面命令后,就会生成 [项目根路径]/packages/vue/dist/vue.global.js 文件

依赖 @vue/composition-api

  1. 安装 vue-cli
$ npm install -g @vue/cli# OR$ yarn global add @vue/cli

2. 创建项目

$ vue create my-project# OR$ vue ui

3. 在项目中安装 composition-api 体验 vue-next 新特性

$ npm install @vue/composition-api --save# OR$ yarn add @vue/composition-api

4. 在使用任何 @vue/composition-api 提供的能力前,必须先通过 Vue.use() 进行安装

import Vue from 'vue'import VueCompositionApi from '@vue/composition-api'Vue.use(VueCompositionApi)

安装插件后,您就可以使用新的 Composition API 来开发组件了。

vue-next 尝鲜

直接拷贝下面代码,去运行看效果吧。推荐使用高版本的chrome浏览器,记得打开F12调试工具哦!

    Title

这个reactive和react-hooks越来越像了, 大家可以去Composition API RFC(https://vue-composition-api-rfc.netlify.com/#api-introduction)这里看细节。

  1. template和之前一样,同样 vue-next也支持手写 render的写法, template和 render同时存在的情况,优先 render。
  2. setup选项是新增的主要变动,顾名思义, setup函数会在组件挂载前( beforeCreate和 created生命周期之间)运行一次,类似组件初始化的作用, setup需要返回一个对象或者函数。返回对象会被赋值给组件实例的 renderContext,在组件的模板作用域可以被访问到,类似 data的返回值。返回函数会被当做是组件的 render。具体可以细看文档。
  3. reactive的作用是将对象包装成响应式对象,通过 Proxy代理后的对象。
  4. 上面的计数器的例子,在组件的 setup函数中,创建了一个响应式对象 state包含一个 age属性。然后创建了一个 increment递增的函数,最后将 state和 increment返回给作用域,这样 template里的 button按钮就能访问到 increment函数绑定到点击的回调, age。我们点击按钮,按钮上的数值就能跟着递增。

推荐React和Vue学习资料文章:

《实践Vue 3.0做JSX(TSX)风格的组件开发》

《一篇文章教你并列比较React.js和Vue.js的语法【实践】》

《手拉手带你开启Vue3世界的鬼斧神工【实践】》

《深入浅出通过vue-cli3构建一个SSR应用程序【实践】》

《怎样为你的 Vue.js 单页应用提速》

《聊聊昨晚尤雨溪现场针对Vue3.0 Beta版本新特性知识点汇总》

《【新消息】Vue 3.0 Beta 版本发布,你还学的动么?》

《Vue真是太好了 壹万多字的Vue知识点 超详细!》

《Vue + Koa从零打造一个H5页面可视化编辑器——Quark-h5》

《深入浅出Vue3 跟着尤雨溪学 TypeScript 之 Ref 【实践】》

《手把手教你深入浅出vue-cli3升级vue-cli4的方法》

《Vue 3.0 Beta 和React 开发者分别杠上了》

《手把手教你用vue drag chart 实现一个可以拖动 / 缩放的图表组件》

《Vue3 尝鲜》

《总结Vue组件的通信》

《手把手让你成为更好的Vue.js开发人员的12个技巧和窍门【实践】》

《Vue 开源项目 TOP45》

《2020 年,Vue 受欢迎程度是否会超过 React?》

《尤雨溪:Vue 3.0的设计原则》

《使用vue实现HTML页面生成图片》

《实现全栈收银系统(Node+Vue)(上)》

《实现全栈收银系统(Node+Vue)(下)》

《vue引入原生高德地图》

《Vue合理配置WebSocket并实现群聊》

《多年vue项目实战经验汇总》

《vue之将echart封装为组件》

《基于 Vue 的两层吸顶踩坑总结》

《Vue插件总结【前端开发必备】》

《Vue 开发必须知道的 36 个技巧【近1W字】》

《构建大型 Vue.js 项目的10条建议》

《深入理解vue中的slot与slot-scope》

《手把手教你Vue解析pdf(base64)转图片【实践】》

《使用vue+node搭建前端异常监控系统》

《推荐 8 个漂亮的 vue.js 进度条组件》

《基于Vue实现拖拽升级(九宫格拖拽)》

《手摸手,带你用vue撸后台 系列二(登录权限篇)》

《手摸手,带你用vue撸后台 系列三(实战篇)》

《前端框架用vue还是react?清晰对比两者差异》

《Vue组件间通信几种方式,你用哪种?【实践】》

《浅析 React / Vue 跨端渲染原理与实现》

《10个Vue开发技巧助力成为更好的工程师》

《手把手教你Vue之父子组件间通信实践讲解【props、$ref 、$emit】》

《1W字长文+多图,带你了解vue的双向数据绑定源码实现》

《深入浅出Vue3 的响应式和以前的区别到底在哪里?【实践】》

《干货满满!如何优雅简洁地实现时钟翻牌器(支持JS/Vue/React)》

《基于Vue/VueRouter/Vuex/Axios登录路由和接口级拦截原理与实现》

《手把手教你D3.js 实现数据可视化极速上手到Vue应用》

《吃透 Vue 项目开发实践|16个方面深入前端工程化开发技巧【上】》

《吃透 Vue 项目开发实践|16个方面深入前端工程化开发技巧【中】》

《吃透 Vue 项目开发实践|16个方面深入前端工程化开发技巧【下】》

《Vue3.0权限管理实现流程【实践】》

《后台管理系统,前端Vue根据角色动态设置菜单栏和路由》

React

《React 函数式组件性能优化知识点指南汇总》

《13个精选的React JS框架》

《深入浅出画图讲解React Diff原理【实践】》

《【React深入】React事件机制》

《Vue 3.0 Beta 和React 开发者分别杠上了》

《手把手深入Redux react-redux中间件设计及原理(上)【实践】》

《手把手深入Redux react-redux中间件设计及原理(下)【实践】》

《前端框架用vue还是react?清晰对比两者差异》

《为了学好 React Hooks, 我解析了 Vue Composition API》

《【React 高级进阶】探索 store 设计、从零实现 react-redux》

《写React Hooks前必读》

《深入浅出掌握React 与 React Native这两个框架》

《可靠React组件设计的7个准则之SRP》

《React Router v6 新特性及迁移指南》

《用React Hooks做一个搜索栏》

《你需要的 React + TypeScript 50 条规范和经验》

《手把手教你绕开React useEffect的陷阱》

《浅析 React / Vue 跨端渲染原理与实现》

《React 开发必须知道的 34 个技巧【近1W字】》

《三张图详细解说React组件的生命周期》

《手把手教你深入浅出实现Vue3 & React Hooks新UI Modal弹窗》

《手把手教你搭建一个React TS 项目模板》

《全平台(Vue/React/微信小程序)任意角度旋图片裁剪组件》

《40行代码把Vue3的响应式集成进React做状态管理》

《手把手教你深入浅出React 迷惑的问题点【完整版】》

作者:大转转FE

转发链接:https://mp.weixin.qq.com/s/gZVn9eDruyv7G_UJFTPuGQ

你可能感兴趣的:(vue,用key拿对象value)