比较vue和react框架(一)

2 篇文章 0 订阅
1 篇文章 0 订阅

我最近在学习vue,之前用的是react,就想对两个流行的前端框架进行一些对比,可能写的不够完善,还请各位大佬不吝赐教。

一般要学习一个框架或是库,首先应该知道它做了什么。以及研究它提供的 API。并不一定每一个 API 都会经常使用,但了解这些会为我们开发过程中解决问题提供思路。官方的 demo 也要好好钻研。我是想以一个全新的思路去了解一下这两种框架。正在做尝试。

vue

我们引入 vue 包时,会在 window 上挂载 Vue 对象。

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
</head>
<body>
  <div id="root"></div>
</body>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
  console.log(window)
</script>
</html>

Vue.compile:在 render 函数中编译模板字符串。只有在独立构建是才有效。

Vue.extend: 使用基础 Vue 构造器,创建一个“子类”。参数是一个包含组件选项的对象。目前并没有想到这种方式有什么好处。

Vue.filter: 注册或获取全局过滤器。

Vue.directive: 注册或获取全局指令。

Vue.component: 注册或获取全局组件。注册组件传入一个选项对象 时,会自动调用 Vue.extend。

Vue.delete: 删除对象的属性。如果对象是响应式的,确保删除能触发更新视图。这个方法主要用于避开 Vue 不能检测到属性被删除的限制。创建的实例时可以通过 vm.$delete 调用该方法。

Vue.set: 向响应式对象中添加一个属性,并确保这个新属性同样是响应式的,且触发视图更新。它必须用于向响应式对象上添加新属性,因为 Vue 无法探测普通的新增属性。创建的实例时可以通过 vm.$set 调用该方法。

Vue.mixin: 全局注册一个混入,影响注册之后所有创建的每个 Vue 实例。插件作者可以使用混入,向组件注入自定义的行为。

Vue.nextTick:在下次 DOM 更新循环结束之后执行延迟回调。在修改数据之后立即使用这个方法,获取更新后的 DOM。组件实例的 $nextTick 方法和它一样,不同之处在于回调的 this 自动绑定到调用它的实例上。

Vue.observable: 让一个对象可响应。Vue 内部会用它来处理 data 函数返回的对象。

Vue.options: 截图如下

directives: 包含 Vue 实例可用指令的哈希表。使用 Vue.directive 注册全局指令时,会在该对象中增加可用指令。

filters:包含 Vue 实例可用过滤器的哈希表。使用 Vue.filter 注册全局过滤器时,会在该对象中增加可用过滤器。

components:包含 Vue 实例可用组件的哈希表。使用 Vue.component 全局注册组件时,会在该对象中增加可用组件。

Vue.use: 安装 Vue.js 插件。如果插件是一个对象,必须提供 install 方法。如果插件是一个函数,它会被作为 install 方法。当插件的 install 方法调用时,会将 Vue 作为参数传入。该方法需要在调用 new Vue() 之前被调用。当 install 方法被同一个插件多次调用,插件将只会被安装一次。

Vue.util: 等有时间研究一下它是干嘛的。

Vue.config:  是一个对象,包含 Vue 的全局配置(silent、optionMergeStrategies、devtools、errorHandler、warnHandler、ignoredElements、keyCodes、performance、productionTip)。

创建 Vue 实例

// 以 _ 或 $ 开头的属性 不会 被 Vue 实例代理,
// 因为它们可能和 Vue 内置的属性、API 方法冲突。
// 你可以使用例如 vm.$data._property 的方式访问这些属性。
var data = { a: 1, $a: 'ghj', _ghj: '---'};
var vm = new Vue({
   data: data
})

数据

data:Vue 实例的数据对象。在 created 钩子函数调用之前将此配置项挂载到实例的 _data 属性上。可以通过 vm._data 或 vm.$data 访问。其中的数据会被挂载到实例上。

props: 可以是数组或对象(允许配置高级选项,如类型检测、自定义验证和设置默认值),用于接收来自父组件的数据。在 created 钩子函数调用之前将实例的 props 配置项会挂载到实例的 _props 属性上,在此函数中 this 就是组件实例,可以通过 this._props 或 this.$props 访问。其中的数据会被挂载到实例上。

propsData: 只用于 new 创建的实例中。在 created 钩子函数调用之前会覆盖 props 配置项挂载到 _props 属性上。其中的数据会被挂载到实例上。

computed: 计算属性,其结果会被缓存,只有依赖的响应式属性发生变化时才会重新计算。在created 钩子函数调用之前将其添加到实例的 _watchers 数组中。其属性会被挂载到实例上。

methods: methods 配置项 created 钩子函数调用之前将其属性会被挂载到实例上。

watch:一个对象,键是需要观察的对象,值是对应回调函数。Vue 实例将会在实例化时调用 $watch(),遍历 watch 对象的每一个属性,将其添加到实例的 _watchers 数组中。

DOM

创建实例对象的 DOM 相关配置项在初始化时会挂载到实例对象的 $option 属性上,如果没有设置,则不会挂载在$option 属性上。render 除外。

el: 只在用 new 创建实例时生效。提供一个在页面上已存在的 DOM 元素作为 Vue 实例的挂载目标。可以是 CSS 选择器,也可以是一个 HTMLElement 实例。如果在实例化时存在这个选项,实例将立即进入编译过程,否则,需要显式调用 vm.$mount() 手动开启编译。在实例挂载之后,元素可以用 vm.$el 访问,注释掉 vm.$mount('#root') 时,不会挂载到页面中,vm.$el 为 undefined

如果 render 函数和 template 属性都不存在,挂载 DOM 元素的 HTML 会被提取出来用作模板。此时,必须使用 Runtime + Compiler 构建的 Vue 库。

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
</head>
<body>
  <div id="root">
      <h1>{{ msg }}</h1>
  </div>
  <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</body>
<script>
  console.log(window)
</script>
<script>
  var Comp = Vue.extend({
    props: ['msg'],
    // template: '<div>{{ msg }}</div>'
  })

  var vm = new Comp({
    propsData: {
      msg: 'hello'
    }
  })
  vm.$mount('#root')
  console.log(vm)
  console.log('vm.$el', vm.$el)
</script>
</html>

template: 如果 Vue 选项中包含渲染函数,该模板将被忽略。模板将会 替换 挂载的元素。挂载元素的内容都将被忽略,除非模板的内容有分发插槽。

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
</head>
<body>
  <div id="root">
      <h1>{{ msg }}</h1>
  </div>
  <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</body>
<script type="x-template" id="tem">
    <div>{{ msg }}</div>
</script>
<script>
  var Comp = Vue.extend({
    props: ['msg'],
    template: '#tem'
  })

  var vm = new Comp({
    propsData: {
      msg: 'hello'
    }
  })
  vm.$mount('#root')
  console.log(vm)
  console.log('vm.$el', vm.$el)
</script>
</html>

render: 该渲染函数接收一个 createElement 方法作为第一个参数用来创建 VNode

renderError: 只在开发者环境下工作。当 render 函数遭遇错误时,其错误将会作为第二个参数传递到 renderError。这个功能配合 hot-reload 非常实用。

生命周期相关

创建实例对象的生命周期设置的相关配置项在初始化时会挂载到实例对象的 $option 属性上,如果没有设置,则不会挂载在$option 属性上。

beforeCreate: 在实例初始化之后,数据观测 (data observer) 和 event/watcher 事件配置之前被调用。

created: 在实例创建完成后被立即调用。在这一步,实例已完成以下的配置:数据观测 (data observer),属性和方法的运算,watch/event 事件回调。然而,挂载阶段还没开始,$el 属性目前不可见。

beforeMount: 在挂载开始之前被调用,在不手动挂载,并且没有指定 el 项时,该函数不会触发相关的 render 函数首次被调用。该钩子在服务器端渲染期间不被调用。

mounted: el 被新创建的 vm.$el 替换,并挂载到实例上去之后调用该钩子。如果 root 实例挂载了一个文档内元素,当 mounted 被调用时 vm.$el 也在文档内。

注意 mounted 不会承诺所有的子组件也都一起被挂载。如果你希望等到整个视图都渲染完毕,可以用 vm.$nextTick 替换掉 mounted。

activated:keep-alive 组件激活时调用。该钩子在服务器端渲染期间不被调用。

deactivated:keep-alive 组件停用时调用。该钩子在服务器端渲染期间不被调用。

beforeUpdate:数据更新时调用,发生在虚拟 DOM 打补丁之前,可以在这里访问现有的 DOM。该钩子在服务器端渲染期间不被调用。

updated:数据更新之后调用,组件 DOM 已经更新,可以执行依赖于 DOM 的操作。该钩子在服务器端渲染期间不被调用。

beforeDestroy:实例销毁之前调用,这时实例仍然完全可用。该钩子在服务器端渲染期间不被调用。

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

errorCaptured:当捕获到一个来自子孙组件的错误时被调用。参数是相关错误信息。

资源

如果不设置资源相关配置项,实例资源默认为空,挂在实例对象的 $options 上,用户设置会覆盖默认配置。

directives:在配置项设置的指令只能在该组件实例中使用。

filters: 在配置项设置的过滤器只能在该组件实例中使用。

components: 在配置项设置的组件只能在该组件实例中使用。

组合

parent:该配置项只能时一个 vue 实例,指定已创建的实例之父实例,在两者之间建立父子关系。

mixins:不太熟悉。暂时没理解。

extends:也不太理解。

其他

name:不太熟。

delimiters:这个选项只在完整构建版本中的浏览器内编译时可用。用来改变纯文本插入分隔符。

functional: 用一个简单的 render 函数返回虚拟节点使组件更容易渲染。

model:允许一个自定义组件在使用 v-model 时定制 prop 和 event。

inheritAttrs:没怎么用过。官方是这么介绍的,默认情况下父作用域的不被认作 props 的特性绑定 (attribute bindings) 将会“回退”且作为普通的 HTML 特性应用在子组件的根元素上。当撰写包裹一个目标元素或另一个组件的组件时,这可能不会总是符合预期行为。通过设置 inheritAttrs 到 false,这些默认行为将会被去掉。而通过 (同样是 2.4 新增的) 实例属性 $attrs 可以让这些特性生效,且可以通过 v-bind 显性的绑定到非根元素上。我有点不太理解对这个属性先有个映像,遇到问题时在研究吧。

comments:只在完整构建版本中的浏览器内编译时可用。当设为 true 时,将会保留且渲染模板中的 HTML 注释。

react

当我们引入 react 和 react-dom 包时,会在 window 上挂载 React 和 ReactDOM 两个对象。

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
</head>
<body>
  <div id="like_button_container"></div>
  <script src="https://unpkg.com/react@16/umd/react.development.js" crossorigin></script>
  <script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js" crossorigin></script>
</body>
  <script>
    console.log(window)
  </script>
</html>

创建 react 元素

React.createElement: 用来创建虚拟 dom。当我们使用 JSX 时,需要用  Babel 将其进行转译成该函数的调用。

const element = React.createElement(
    'h1',
     {
       className: 'greeting',
       key: '1',
     },
     'Hello, world!'
   );
const e = <h1 key="1" className="greeting">Hello, world!</h1>
console.log(element)
console.log(e)

React.createFactory: 返回用于生成指定类型 React 元素的函数。此辅助函数已废弃,建议使用 JSX 或直接调用 React.createElement() 来替代它。

创建 react 组件

React.Component:我们一般通过 class Clock extends React.Component 语法糖继承 React.Component 创建有状态组件,React.Component提供了生命周期方法。

React.PureComponent: 用当前与之前 props 和 state 的浅比较覆写了 shouldComponentUpdate() 的实现。

React.memo: 与 React.PureComponen 非常相似,但它只适用于函数组件。通过记忆组件渲染结果的方式来提高组件的性能表现。这意味着在相同 props 的情况下,React 将跳过渲染组件的操作并直接复用最近一次渲染的结果。

转换元素

React.cloneElement: 以 element 元素为样板克隆并返回新的 React 元素。返回元素的 props 是将新的 props 与原始元素的 props 浅层合并后的结果。新的子元素将取代现有的子元素,而来自原始元素的 key 和 ref 将被保留。

React.isValidElement: 验证对象是否为 React 元素,返回值为 true 或 false

React.Children: 提供了用于处理 this.props.children 不透明数据结构的实用方法。

React.Fragment: 在不额外创建 DOM 元素的情况下,让 render() 方法中返回多个元素。

动态加载

React.lazy: 像渲染常规组件一样处理动态引入的组件。

React.Suspense: 使得组件可以“等待”某些操作结束后,再进行渲染。其 fallback 属性接受任何在组件加载过程中你想展示的 React 元素。你可以将 Suspense 组件置于懒加载组件之上的任何位置。

引用相关

React.createRef:创建一个能够通过 ref 属性附加到 React 元素的 ref。

React.forwardRef:创建一个能够将其接受的 ref 属性转发到其组件树下的另一个组件中的 React 组件。

Context

React.createContext:创建一个 Context 对象。每个 Context 对象都会返回一个 Provider React 组件, 允许消费组件订阅 context 的变化。

性能测试相关

React.Profiler: 测量渲染一个 React 应用多久渲染一次以及渲染一次的“代价”。React 会在 profile 包含的组件树中任何组件 “提交” 一个更新的时候调用 onRender 这个函数,其参数描述了渲染了什么和花费了多久。

ReactDOM.render: 用来将虚拟 dom 挂载到真实的 dom 节点上。在提供的 container 里渲染一个 React 元素,并返回对该组件的引用。

ReactDOM.hydrate: 用于在 ReactDOMServer 渲染的容器中对 HTML 的内容进行 hydrate 操作。React 会尝试在已有标记上绑定事件监听器。

ReactDOM.unmountComponentAtNode: 从 DOM 中卸载组件,会将其事件处理器(event handlers)和 state 一并清除。如果指定容器上没有对应已挂载的组件,这个函数什么也不会做。

ReactDOM.findDOMNode: 严格模式下这个方法已弃用。这个不知道该写在哪里,写哪里都报错,如果哪位大佬知道怎么用可以回复一下,非常感谢。

ReactDOM.createPortal:提供一种将子节点渲染到 DOM 节点中的方式,该节点存在于 DOM 组件的层次结构之外。

ReactDOM.unstable_开头的 API 作为试验性功能提供是为了能更快地迭代,更早地推出稳定的功能。

 

 

如果大家觉得有收获的话可以打赏一下。第一次码这么多字不容易。

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值