通过Vue3对比学习Reactjs: 模板语法 vs JSX

Vue 使用一种基于 HTML 的模板语法,在底层机制中,Vue 会将模板编译成高度优化的 JavaScript 代码。结合响应式系统,当应用状态变更时,Vue 能够智能地推导出需要重新渲染的组件的最少数量,并应用最少的 DOM 操作。Vue也支持jsx语法,但请注意,jsx语法将不会享受到和模板同等级别的编译时优化。

JSX是JavaScript的语法扩展,允许您在JavaScript文件中编写类似HTML的标记。尽管还有其他编写组件的方法,但大多数React开发人员更喜欢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 attributes 中使用。想要响应式地绑定一个 attribute,应该使用 v-bind 指令

  • 绑定单个动态值
<div v-bind:id="dynamicId"></div>

简写

<div :id="dynamicId"></div>
  • 动态绑定多个值

有这样的一个包含多个 attribute 的 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>  
    );  
}

等价于

扫描二维码关注公众号,回复: 15370850 查看本文章
<Avatar name="kevin" age={20} /> 

这种方法最好慎用,可能会引起意料之外的错误

CSS

来看一下css和对象,作为属性传递时,这两者有什么区别

  • class
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
今日推荐