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
中使用简单的class
和style
,可以使用下面的方式,在jsx
中,class
要用className
替换,css中的style属性要用camelCase格式
<ul style={{
backgroundColor: 'black',
color: 'pink'
}}>
<ul className=""></ul>
条件渲染(if)
在vue中条件渲染需要用到指令有 v-show
、v-if
、v-else
、v-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
元素,以便它可以跟踪每个节点的标识,从而重用和重新排序现有的元素