Vue3 の比較を通じて Reactjs を学ぶ: テンプレート構文と JSX

Vue はHTML ベースのテンプレート構文を使用し、その基礎となるメカニズムでテンプレートを高度に最適化された JavaScript コードにコンパイルします。リアクティブ システムと組み合わせることで、Vue は再レンダリングが必要なコンポーネントの最小数をインテリジェントに推定し、アプリケーションの状態が変化したときに最小限の DOM 操作を適用できます。Vue は jsx 構文もサポートしていますが、jsx 構文はテンプレートと同じレベルのコンパイル時の最適化を享受できないことに注意してください。

JSX は、JavaScript ファイル内に HTML のようなマークアップを記述できるようにする JavaScript の構文拡張機能です。コンポーネントを記述する他の方法もありますが、ほとんどの React 開発者は JSX のシンプルさを好み、ほとんどのコードベースで JSX が使用されます。

テキスト補間

データ バインディングの最も基本的な形式はテキスト補間であり、どちらも JavaScript 式と関数呼び出しをサポートしています。

  • Vue は{{}}(二重中括弧構文)を使用します
<span>Message: {{ msg }}</span>
{{ number + 1 }} 
{{ ok ? 'YES' : 'NO' }} 
{{ message.split('').reverse().join('') }}

<time> {{ formatDate(date) }} </time>
  • JSX の使用法{}(単一中括弧構文)
{ number + 1 } 
<span>Message: { msg }</span>
<h1>To Do List for {formatDate(today)}</h1>

一般的な属性値

Vue では、HTML 属性で二重中括弧を使用できません。属性をリアクティブにバインドするには、 v-bind ディレクティブを使用する必要があります。

  • 単一の動的値をバインドする
<div v-bind:id="dynamicId"></div>

略語

<div :id="dynamicId"></div>
  • 複数の値を動的にバインドする

以下は、複数の属性を持つ JavaScript オブジェクトです。

const objectOfAttrs = {
  id: 'container',
  class: 'wrapper'
}

引数をとらないことにより v-bind、それらを単一の要素にバインドできます。

<div v-bind="objectOfAttrs"></div>

効果は以下と同等です

<div id="container" class="wrapper"></div>

jsx では、属性バインディングは HTML 属性の記述と似ており、動的属性の場合は{}単一

  • 単一の値を動的にバインドする
export default function Avatar() {
  const avatar = 'https://i.imgur.com/7vQD0fPs.jpg';
  const description = 'Gregorio Y. Zara';
  return (
    <img
      className="avatar"
      src={avatar}
      alt={description}
    />
  );
}
  • 複数の値を動的にバインドする

jsx では、オブジェクト内のすべてのプロパティをプロパティとしてコンポーネントに渡したい場合は、次のjavascript構造化構文を使用する必要があります。

const person = {
    name: 'kevin',
    age: 20
}
function Profile() {  
    return (  
        <div className="card">  
            <Avatar {...person} />  
        </div>  
    );  
}

に相当

<Avatar name="kevin" age={20} /> 

この方法は慎重に使用するのが最善です。予期しないエラーが発生する可能性があります。

CSS

CSS とオブジェクトを見てみましょう。属性として渡す場合の違いは何ですか

  • クラス
const isActive = ref(true)
const hasError = ref(false)

<div :class="{ active: isActive, error: hasError }"></div>

最終的には次のようにレンダリングされます

<div class="active"></div>

动态的class,还支持数组

const activeClass = ref('active')
const errorClass = ref('text-danger')
<div :class="[activeClass, errorClass]"></div>

会渲染成

<div class="active text-danger"></div>

还支持以下方式

<div :class="[isActive ? activeClass : '', errorClass]"></div>
<div :class="[{ active: isActive }, errorClass]"></div>
  • style

对于内联样式

<div :style="{ color: 'red', fontSize: '20px' }"></div>

推荐使用 camelCase,但 :style 也支持 kebab-cased 形式的 CSS 属性 key (对应其 CSS 中的实际名称),例如:

<div :style="{ 'font-size': '20px' }"></div>

:style也支持对象格式

const styleObject = reactive({
  color: 'red',
  fontSize: '13px'
})

<div :style="styleObject"></div>

我们还可以给 :style 绑定一个包含多个样式对象的数组。这些对象会被合并后渲染到同一元素上:

<div :style="[baseStyles, overridingStyles]"></div>

jsx中的样式的写法有它自己的一套 css-in-js的方案,如果在jsx中使用简单的classstyle,可以使用下面的方式,在jsx中,class要用className替换,css中的style属性要用camelCase格式

<ul style={{
      backgroundColor: 'black',
      color: 'pink'
}}>

<ul className=""></ul>

条件渲染(if)

在vue中条件渲染需要用到指令有 v-showv-ifv-elsev-else-if

<div v-if="type === 'A'">
  A
</div>
<div v-else-if="type === 'B'">
  B
</div>
<div v-else-if="type === 'C'">
  C
</div>
<div v-else>
  Not A/B/C
</div>

关于v-if v-show v-for之间的关系和区别,会用单独的一篇文章介绍

而在jsx中的条件渲染有以下几种方式

  • if
if (isPacked) {
  return <li className="item">{name} ✔</li>;
}
return <li className="item">{name}</li>;
  • && {cond && <A />}
return (
  <li className="item">
    {name} {isPacked && '✔'}
  </li>
);
  • ? : {cond ? <A /> : <B />}
return (
  <li className="item">
    {isPacked ? name + ' ✔' : name}
  </li>
);

列表渲染(list)

Vue中我们可以使用 v-for 指令基于一个数组来渲染一个列表。有以下几种写法

  • 数组
<li v-for="item in items" :key={}>
  {{ item.message }}
</li>
  • 带索引
<li v-for="(item, index) in items" :key={}>
  {{ parentMessage }} - {{ index }} - {{ item.message }}
</li>
  • 使用析构
<li v-for="{ message } in items" :key={}>
  {{ message }}
</li>

<!-- 有 index 索引时 -->
<li v-for="({ message }, index) in items">
  {{ message }} {{ index }}
</li>
  • 使用 of 代替 in
<div v-for="item of items"></div>
  • 遍历对象

你也可以使用 v-for 来遍历一个对象的所有属性。遍历的顺序会基于对该对象调用 Object.keys() 的返回值来决定。

const myObject = reactive({
  title: 'How to do lists in Vue',
  author: 'Jane Doe',
  publishedAt: '2016-04-10'
})

#1
<ul>
  <li v-for="value in myObject" :key={}>
    {{ value }}
  </li>
</ul>

#2 可以通过提供第二个参数表示属性名 (例如 key):

<li v-for="(value, key) in myObject" :key={}>
  {{ key }}: {{ value }}
</li>

#3 第三个参数表示位置索引:

<li v-for="(value, key, index) in myObject" :key={}>
  {{ index }}. {{ key }}: {{ value }}
</li>

jsx中,需要用到javascript中的数组的方法,常用数组的 map方法

const people = [{
  id: 0,
  name: 'Creola Katherine Johnson',
  profession: 'mathematician',
}, {
  id: 1,
  name: 'Mario José Molina-Pasquel Henríquez',
  profession: 'chemist',
}, {
  id: 2,
  name: 'Mohammad Abdus Salam',
  profession: 'physicist',
}, {
  name: 'Percy Lavon Julian',
  profession: 'chemist',  
}, {
  name: 'Subrahmanyan Chandrasekhar',
  profession: 'astrophysicist',
}];

const chemists = people.filter(person =>
  person.profession === 'chemist'
);
const listItems = chemists.map(person =>
  <li>
     <img
       src={getImageUrl(person)}
       alt={person.name}
     />
     <p>
       <b>{person.name}:</b>
       {' ' + person.profession + ' '}
       known for {person.accomplishment}
     </p>
  </li>
);

不管是在vue还是在jsx,渲染列表时,都需要 key元素,以便它可以跟踪每个节点的标识,从而重用和重新排序现有的元素

おすすめ

転載: juejin.im/post/7246963275955093561