vue完全編程方式與react在書寫和運用上的異同

在構建html元素時,vue傾向于模板方式,而react則完全使用javascript的編程能力,但vue也具備完全編程的能力(與react一樣使用JSX和createElement渲染函數)。所以,當vue使用完全編程方式時,與react可以說是大同小異。

學習react的時候,有一個核心思想:組件就是函數,元素就是值。這對于vue來說也是完全適用的,唯一的區別在于兩者的限制和使用條件不同。

目錄

  • JSX
  • 元素渲染
  • 組件定義
  • 組件傳值
  • 內容分發
  • 數據響應
  • 事件處理

JSX

JSX是JavaScript的一個擴展語法,本質是createElement渲染函數的語法糖。react和vue在JSX語法上幾乎一致,區別在于屬性值的傳入上。

react的JSX語法更接近 JavaScript 而不是 HTML,所以 React DOM 使用 camelCase(小駝峰命名)來定義屬性的名稱,而不使用 HTML 屬性名稱的命名約定。
例如,JSX 里的 class 變成了 className,而 tabindex 則變為 tabIndex

vue的JSX則使用了一個Babel 插件使其更貼近HTML模板語法,vue對大小寫不敏感(實際上vue會將所有屬性值轉換為小寫)。
例如,tabIndex會轉化成tabindexclassName會轉化為classname

特例,對于屬性class,react應寫成className,vue應寫成class

react引入了Fragments使得react可以有多個根元素,vue沒有此功能,只能是單一根元素

元素渲染

react的文檔中提到了

元素是構成 React 應用的最小磚塊。

const element = <h1>Hello, world</h1> // 定義元素...
render () {return <div>{element}</div> // 使用元素
}

react將元素當作值來對待,你可以直接使用,也可以先賦值給某個變量,然后再使用。
這一點在vue的文檔中雖然沒有明確提到,但依然適用,vue也可以先將元素賦值給某個變量,然后在適當的位置使用該變量。

兩者在使用時的區別在于:

  • react可以在任意位置(組件內和組件外)定義元素并使用
  • vue只能在組件內定義元素(只要是組件內,任意位置都可以,render函數內,data數據或者其他位置),在組件外定義則會報錯(h is not defined

報錯原因:網上找到的一個說法是vue中組件外沒有上下文聯系,找不到渲染函數。
思來想去只能歸結于兩者的渲染機制不同(沒有依據,瞎猜的😜:react可能是先賦值后渲染,vue可能是先渲染后賦值)

組件定義

react定義組件有兩種方式,函數組件和class組件,兩者在一定條件下可以相互轉換,函數式組件是無狀態組件,沒有state狀態和生命周期

// 函數組件
cosnt MyComponent = props => {return <div>{props.title}</div>
}// class組件
class MyComponent extends React.Component {static defaultProps = {} // 設置默認傳入值constructor(props) {super()this.state = {} // 設置狀態值}... // 其他組件函數:自定義方法,生命周期方法...render() {return <div>{this.props.title}</div>}
}

vue文檔給出的組件定義只有一種方式(如下),函數式組件(無狀態)是在普通組件的基礎上添加functional標記

Vue.component('my-component', {props: {title:String},...render () {return <div>{this.title}</div>}
})

實際上,上訴方式是官方給出的一種完整使用(組件定義和全局注冊),在實際項目中通常組件定義和注冊都是分開的(即組件的局部注冊)。

而react沒有組件注冊這一說法,只有定義和使用,vue實際上也可以和react一樣,直接定義并使用,前提是使用JSX語法,如果使用createElement渲染函數和模板方式,仍然需要進行組件注冊。

vue定義組件方式如下

// 函數式組件
const MyComponent = {functional: true, // 函數式組件標記,props: {title:String},  // 設置傳入值// 為了彌補缺少的實例,提供第二個參數作為上下文render(h, context) {return <div>{this.props.title}</div>}
}
// 函數式組件的變種寫法 -- 函數方式,對照了react的函數組件的寫法
// vue官方文檔中沒有提到這種寫法,但這種寫法依然生效
// 與react函數式組件的不同之處在于,react函數式組件的傳入值是props,vue函數組件傳入值是context上下文
cosnt MyComponent = context => {return <div>{context.props.title}</div>
}// 普通組件
const MyComponent = {props: {title:String},  // 設置傳入值data () { return { user: '' } }, // 數據computed: {}, // 計算屬性watch: {}, // 監聽屬性methods: {}, // 自定義方法... // 其他生命周期方法,鉤子函數等...render() {return <div>{this.props.title}</div>}
}

從上面react和vue的代碼片段中可以看出,react定義組件用的是class對象,vue定義組件用的是Object對象,兩者的區別在于:

  • class對象方法之間不需要分隔符,Object對象的屬性之間需要逗號,分隔
  • 對于傳入值,兩者都是使用的props,react只能定義默認值,vue則可以限制傳入類型并進行數據驗證(react要實現類型驗證需要引入prop-types
  • 對于狀態值,react將狀態值放入class對象的屬性值state里,并在constructor構造函數中完成數據初始化,vue則將狀態值放入data方法的返回值中
  • 對于自定義方法,react可直接書寫在class對象下,vue則必需放入methods字段中
  • 數據監聽,react在生命周期方法componentDidUpdate中監聽數據變化,vue則提供了更為方便的computedwatch

組件傳值

react和vue的組件傳值都是通過組件屬性進行傳遞的。

  • react,不管是函數式組件還是普通組件,將組件的所有屬性都當作prop傳入;
  • vue,對于函數式組件
    • 版本2.3.0之前,如果一個函數式組件想要接收 prop,則 props 選項是必須的;
    • 版本2.3.0或以上,如果定義了props選項,則只能接收定義的prop
    • 版本2.3.0或以上,如果省略 props 選項,組件上所有的 attribute 都會被自動隱式解析為 prop
  • vue,對于普通組件
    • 特殊屬性class、style,直接掛載到組件根元素上,與組件內的class和style疊加合并;
    • 組件上的屬性如果在props中的定義了,則作為prop傳入;
    • 對于沒有聲明的屬性,默認自動掛載到組件根元素上,并覆蓋原來的屬性值(可通過設置inheritAttrs屬性開關此功能,默認開啟);

內容分發

說完組件傳值,那就不得不說組件的內容分發,這是一種特殊的組件傳值(其本質還是組件傳值)。
在vue中,內容分發使用的是插槽slot,react則稱為組件組合,并且react特意強調了

React 中沒有“槽”這一概念的限制,你可以將任何東西作為 props 進行傳遞

最常見的就是如下以子節點(children)方式

<MyComponent>hello world</MyComponent>
  • react提供了一個特殊的children prop用來接收分發內容,
  • vue函數式組件即可以通過children來接收內容,也可以通過slots().default方式,
  • vue普通組件只能通過$slots.default的方式分發

vue函數式組件和普通組件對插槽slot使用的區別主要式因為函數式組件沒有實列this,而是使用上下文context,詳見vue函數式組件
vue的插槽分為普通插槽slots和作用域插槽scopedSlots,作用域插槽可以完全替代普通插槽,建議使用使用scopedSlots

簡單的示列如下

// react 函數式組件
const MyComponent = props => {return <div>{props.children}</div>
}
// react class組件
class MyComponent extends React.Component {render() {return <div>{this.props.children}</div>}
}// vue 函數式組件
const MyComponent = context => {// children方式分發const { children } = contextreturn <div>{children}</div>// 通過插槽方式分發// const { slots } = context// return <div>{slots().default}</div>
}
// vue 普通組件
const MyComponent = {render () {return <div>{this.$scopedSlots.default()}</div>}
}

多內容分發

  • react只需要傳入對應的prop即可
  • vue使用slotsscopedSlots進行分發
// react
...render () {return (<div><header>{props.header}</header><main>{props.children}</main><footer>{props.footer}</footer></div>)}
...
// react使用
<MyComponentheader='hello world'chilren={<p>Lorem ipsum dolor sit amet</p>}footer='this is footer'
/>// vue
...render () {return (<div><header>{this.$scopedSlots.header()}</header><main>{this.$scopedSlots.default()}</main><footer>{this.$scopedSlots.footer()}</footer></div>)}
...
// vue使用
<MyComponentscopedSlots={{    header: props => `hello, world`,default: props => <p>Lorem ipsum dolor sit amet</p>,footer: props => 'this is footer'}}
/>

對于內容分發,react顯得十分靈活及簡便,vue在使用上相對有部分限制,vue可以使用作用域插槽,react只能通過其他方式實現類似功能。vue插槽的JSX使用方式

實際上,如果vue不使用插槽方式,改用props也可以和react一樣實現內容分發

// vue 使用 props 實現了內容分發,定義和使用方式和 react 幾乎一樣
const MyComponent = {props: ['header', 'children', 'footer'],render () {return (<div><header>{this.header}</header><main>{this.children}</main><footer>{this.footer}</footer></div>)}
}export default {render () {return (<MyComponentheader='hello, world'children={<p>Lorem ipsum dolor sit amet</p>}footer={'this is footer'}/>)}
}

數據響應

響應式數據更新方式是vue與react的一個重要區別之一

  • vue的數據加入到響應式系統中,直接操作數據會同步更新視圖
  • react必需使用setState方法更新數據以便實現視圖的同步更新

事件處理

react的事件處理為了在回調中使用 this,必須為該方法綁定this(在構造函數中綁定或在事件處理程序傳遞參數),vue則不需要這個綁定過程。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/281210.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/281210.shtml
英文地址,請注明出處:http://en.pswp.cn/news/281210.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Solr 配置文件之schema.xml

schema.xml這個配置文件的根本目的是為了通過配置告訴Solr怎樣建立索引。solr的數據結構例如以下&#xff1a;document&#xff1a;一個文檔、一條記錄 field&#xff1a;域、屬性solr通過搜索某個或某些field&#xff0c;返回若干個符合條件的document。或者按搜索的score排序…

wget整站抓取、網站抓取功能;下載整個網站;下載網站到本地

wget -r -p -np -k -E http://www.xxx.com 抓取整站 wget -l 1 -p -np -k http://www.xxx.com 抓取第一級 -r 遞歸抓取-k 抓取之后修正鏈接&#xff0c;適合本地瀏覽 http://blog.sina.com.cn/s/blog_669fb0c3010137bq.html wget -m -e robotsoff -k -E "http://…

Git標簽tag及tag遠程同步

Git給某個歷史版本打上標簽&#xff0c;這樣我們可以快速的眾多歷史版本中找到自己需要的版本&#xff0c;一般打標簽的版本都是發布版本&#xff0c;例如v1.0.0 標簽操作 創建標簽 # 輕量標簽 git tag tagname eg: git tag v1.4# 附注標簽 git tag -a tagname -m tag descr…

妙用SQL Server聚合函數和子查詢迭代求和

先看看下面的表和其中的數據&#xff1a;t_product該表有兩個字段&#xff1a;xh和price&#xff0c; 其中xh是主索引字段&#xff0c;現在要得到如下的查詢結果&#xff1a;從上面的查詢結果可以看出&#xff0c;totalprice字段值的規則是從第1條記錄到當前記錄的price之和。如…

記一次.NET某工控圖片上傳CPU爆高分析

一&#xff1a;背景 1.講故事今天給大家帶來一個入門級的 CPU 爆高案例&#xff0c;前段時間有位朋友找到我&#xff0c;說他的程序間歇性的 CPU 爆高&#xff0c;不知道是啥情況&#xff0c;讓我幫忙看下&#xff0c;既然找到我&#xff0c;那就用 WinDbg 看一下。二&#xff…

微信小程序項目實踐準備工作

微信小程序項目實踐準備工作一、了解微信小程序產品定位及功能介紹微信小程序是一種全新的連接用戶與服務的方式&#xff0c;它可以在微信內被便捷地獲取和傳播&#xff0c;同時具有出色的使用體驗。簡單的說&#xff0c;小程序是微信附屬產品&#xff0c;需要依賴微信&#xf…

VSCode 用戶自定義片段 snippet 基本語法說明

先上一個官方模板&#xff1a; "Print to console": {"prefix": "log","body": ["console.log($1);","$2"],"description": "Log output to console" }prefix 前綴&#xff0c;emmet 觸發條…

Python集合和函數

深淺拷貝&#xff1a;.copy()方法&#xff0c;淺拷貝值拷貝一層。列表中的列表和字典會深拷貝&#xff0c;其他類型會淺拷貝。列表中的列表和字典會隨著副本的修改而改變&#xff0c;其他類型不會隨著副本的改變為改變。ab不是復制&#xff0c;是兩個變量共享同一內存空間&…

從 WinDbg 角度理解 .NET7 的AOT玩法

一&#xff1a;背景 1.講故事前幾天 B 站上有位朋友讓我從高級調試的角度來解讀下 .NET7 新出來的 AOT&#xff0c;畢竟這東西是新的&#xff0c;所以這一篇我就簡單摸索一下。二&#xff1a;AOT 的幾個問題 1. 如何在 .NET7 中開啟 AOT 功能在 .NET7 中開啟 AOT 非常方便&…

.NET Core C#系列之XiaoFeng.ToCast萬能類型轉換器

數據類型相互轉換如&#xff1a;字符串轉整型&#xff0c;字符串轉日期首先要引用 XiaoFeng命名空間下邊三個擴展方法 就是類型轉換的方法最常用的就是 ToCast<T>方法/// <summary> /// 類型相互轉換 /// </summary> /// <typeparam name"T">…

利用 Git OpenSSH 查看/生成 本機 ssh 公鑰

查看本機公鑰 本機公鑰文件一般用戶目錄下的.ssh文件夾&#xff0c;文件夾下有三個文件&#xff0c;分別是 id_rsa 私鑰密碼id_rsa.pub 公鑰內容known_hosts 允許的host地址 使用文本編輯器查看文件id_rsa.pub文件即可 或者使用cat命令查看 # 任意位置打開 Git bash cd ~/.…

高斯消元法

有點線代的知識&#xff1a; const double EPS 1e-8; typedef vector<double> vec; typedef vector<vec> mat; //Ax b vec gauss_jordan(const mat &A, const vec &b) {int n A.size();mat B(n,vec(n1)); //定義大小for(int i0;i < n;i)for(int j0…

判斷對象是否存在某個屬性

JavaScript判斷對象是否存在某個屬性或者方法&#xff0c;常用方法有兩種hasOwnProperty和in hasOwnProperty是Object原型對象上的一個方法&#xff0c;用來判斷對象自身屬性中是否具有指定的屬性。 這個方法可以用來檢測一個對象是否含有特定的自身屬性&#xff1b;和 in 運…

【PPT】適配器模式 和 橋接模式

【PPT】適配器模式 和 橋接模式目錄【PPT】適配器模式 和 橋接模式一、PPT 截圖1.0、封面和目錄1.1、設計模式概述1.2、結構型模式特點1.3、適配器模式1.4、橋接模式二、參考資料及 PPT 獲取方法獨立觀察員 2022 年 11 月 15 日為之前公司準備的分享PPT&#xff0c;后來沒用上。…

Flask 【第七篇】Flask中的wtforms使用

一、簡單介紹flask中的wtforms WTForms是一個支持多個web框架的form組件&#xff0c;主要用于對用戶請求數據進行驗證。 安裝&#xff1a; pip3 install wtforms 二、簡單使用wtforms組件 1、用戶登錄 具體代碼&#xff1a; from flask import Flask,render_template,request,…

CSS自定義滾動條樣式

css通過滾動條偽類來修改滾動條樣式&#xff0c;偽類名稱如下 ::-webkit-scrollbar 滾動條整體部分 ::-webkit-scrollbar-track 滾動條軌道&#xff08;里面裝有滑塊 thumb&#xff09; ::-webkit-scrollbar-thumb 滾動條滑塊 ::-webkit-scrollbar-button 滾動條軌道兩端按鈕 …

為了避免內存攻擊,美國國家安全局提倡Rust、C#、Go、Java、Ruby 和 Swift,但將 C 和 C++ 置于一邊...

本文翻譯自兩篇文章&#xff0c;第一篇是對美國國家安全局在“軟件內存安全”網絡安全信息表的解讀&#xff0c;第二篇是普及什么是內存安全&#xff0c;為什么它很重要&#xff1f;第一篇 為了避免內存攻擊&#xff0c;美國國家安全局提倡Rust、C#、Go、Java、Ruby 和 Swift&a…

自學python(一)

一、入門儀式 學習一門新語言必不可少的一件事&#xff1a; print("Hello world!")二、基礎知識 1、注釋&#xff1a; 單行注釋&#xff1a; 1 print("Hello world!") #輸出Hello world! 多行注釋&#xff1a; 這是多行注釋 這是多行注釋 這是多行注釋…

.NET周報【11月第2期 2022-11-15】

國內文章統一的開發平臺.NET 7正式發布https://www.cnblogs.com/shanyou/archive/2022/11/09/16871945.html在 2020 年規劃的.NET 5功能終于在.NET 7 完成了&#xff0c;為微軟和社區一起為多年來將不同的開發產品統一起來的努力加冕&#xff0c;未來只有一個.NET, 回顧.NET 20…

如何像使用AspNetCore中的Controllers 和 Actions一樣處理MQTT消息

在物聯網項目中&#xff0c; 處理MQTT的topic時費工費力&#xff0c; 代碼一團亂&#xff0c; 什么才是最好的姿勢&#xff1f;這里面我們極力介紹 MQTTnet.AspNetCore.Routing 項目&#xff0c;MQTTnet AspNetCore Routing 是https://github.com/Atlas-LiftTech/MQTTnet.AspN…