Что такое JSX?
JSX — это формат, сочетающий Javascript и XML. React изобрел JSX, используя синтаксис HTML для создания виртуального DOM. Когда он встречает
Почему я должен использовать JSX в vue?
Хочу подкинуть, шучу.Во-первых, потому что я недавно учился реагировать, я испытал в нем jsx-грамматику, и я обнаружил, что не было дискомфортного ощущения, что говорят другие, поэтому я хотел попробовать это в vue, ерунда. Без лишних слов давайте воспользуемся кодом, чтобы увидеть разницу между ними.
ps:Для большинства сцен в Vue не нужно использовать функцию рендеринга, либо шаблон более лаконичен и интуитивно понятен..
использовать шаблон
// item.vue
<template>
<div>
<h1 v-if="id===1">
<slot></slot>
</h1>
<h2 v-if="id===2">
<slot></slot>
</h2>
<h3 v-if="id===3">
<slot></slot>
</h3>
<h4 v-if="id===4">
<slot></slot>
</h4>
</div>
</template>
<script>
export default {
name: "item",
props:{
id:{
type:Number,
default:1
}
}
}
</script>
Компонент элемента должен получать значение идентификатора, переданное родительским компонентом, для отображения различных тегов h, можно сказать, что v-if использует «экстремальный» и записывает множество избыточных слотов.
Использование функции рендеринга и jsx
// item.vue
<script>
export default {
name: "item",
props:{
id:{
type:Number,
default:1
}
},
render(){
const hText=`
<h${this.id}>${this.$slots.default[0].text}</h${this.id}>
`
return <div domPropsInnerHTML={hText}></div>
}
}
</script>
Плюс родительский компонент для управления значением реквизита. Родительский компонент не сравнивает и использует традиционный формат шаблона.
// list.vue
<template>
<div>
<h-title :id="id">Hello World</h-title>
<button @click="next">下一个</button>
</div>
</template>
<script>
import Title from './item'
export default {
name: "list",
data() {
return {
id:1
}
},
components: {
"h-title":Title
},
methods:{
next(){
++this.id
}
}
}
</script>
После запуска страница будет отображать тег h1, h2 или h3, и есть только один слот.Нажмите, чтобы переключить значение реквизита, и также будут отображаться разные теги h. Хотя второй способ написания не очень прямолинеен, он экономит много избыточного кода, а страница становится намного чище.
А если нет v-if, v-for, v-model?
Не волнуйтесь, эти инструкции — просто черная магия, которую легко реализовать с помощью js.
- v-if
render(){
return (
<div>
{this.show?'你帅':'你丑'}
</div>
)
}
Вы можете писать только простые троичные выражения, а if/else используются для сложных выражений.
render(){
let ifText
if(this.show){
ifText=<p>你帅</p>
}else{
ifText=<p>你丑</p>
}
return (
<div>
{ifText}
</div>
)
}
- v-for
data(){
return{
show:false,
list:[1,2,3,4]
}
},
render(){
return (
<div>
{this.list.map((v)=>{
return <p>{v}</p>
})}
</div>
)
}
В jsx {} нет возможности писать операторы if/for, можно писать только выражения, поэтому карта используется как цикл, а троичное выражение используется как суждение.
-
v-model
Недавно я помогал компании проводить собеседования и набирать людей и обнаружил, что многие люди в v-model не знают, что такое синтаксический сахар? Потом некоторые люди говорят, что я могу реализовать это с помощью нативного js, но они даже не знают, как это реализовать в vue, ну и два момента: передача значений и прослушивание событий для изменения значений.
<script>
export default {
name: "item",
data(){
return{
show:false,
list:[1,2,3,4],
text:'',
}
},
methods:{
input(e){
this.text=e.target.value
}
},
render(){
return (
<div>
<input type="text" value={this.text} onInput={this.input}/>
<p>{this.text}</p>
</div>
)
}
}
</script>
Как использовать пользовательские компоненты?
Это очень просто, просто импортируйте, не нужно объявлять в атрибуте components, пишите прямо в jsx, например
<script>
import HelloWolrd from './HelloWorld'
export default {
name: "item",
render(){
return (
<HelloWolrd/>
)
}
}
</script>
Как связать события, класс, стиль, ссылку и т.д.?
Посмотрите на надпись ниже
render (h) {
return (
<div
// normal attributes or component props.
id="foo"
// DOM properties are prefixed with `domProps`
domPropsInnerHTML="bar"
// event listeners are prefixed with `on` or `nativeOn`
onClick={this.clickHandler}
nativeOnClick={this.nativeClickHandler}
// other special top-level properties
class={{ foo: true, bar: false }}
style={{ color: 'red', fontSize: '14px' }}
key="key"
ref="ref"
// assign the `ref` is used on elements/components with v-for
refInFor
slot="slot">
</div>
)
}
Выше следует отметить одну вещь: при привязке событий к пользовательским компонентам используйте nativeOnClick, и используется формат шаблона.@click.native
, Кроме того, когда он используется для привязки событий к функциональным компонентам, это немного ям. О нем поговорим ниже.
Функциональные компоненты в JSX
Функциональные компоненты не имеют состояния и не имеют экземпляра this.В документации vue упоминается следующий отрывок:
Поскольку функциональный компонент — это просто функция, накладные расходы на рендеринг также намного ниже. Однако отсутствие постоянных экземпляров также означает, что функциональные компоненты не отображаются в дереве компонентов Vue devtools.
Я лично понимаю, что из-за отсутствия состояния (данных) обработка намного менее отзывчива, а такие процессы, как жизненный цикл, улучшат скорость и снизят использование памяти, верно?
Функциональные компоненты также могут использоваться в формате шаблона, как это
<template functional>
</template
Как насчет функциональных компонентов в jsx? Это также очень просто, просто добавьте конфигурациюfunctional: true
просто хорошо
Этот функциональный компонент ушелthis
Как экземпляры связывают события и как они получают реквизиты?
Все, что нужно компоненту, передается через контекст, в том числе:
-
props
: объект, предоставляющий все реквизиты -
children
: массив дочерних узлов VNode -
slots
: функция, которая возвращает объект всех слотов -
data
: объект данных передается компоненту, а компонент передается в качестве второго параметра для createElement.
Выше я перечислил лишь некоторые свойства, это вещи для нефункциональных компонентов, для функциональных компонентов
Vue добавляет объект контекста, который необходимо использовать какrender(h,context)
Второй параметр передается,this.$slots.default
обновить доcontext.children
реквизит изначально вешался прямо на это, а теперь становитсяcontext.props
Завис на context.props.this.data
сталcontext.data
Следует отметить, что для функциональных компонентов нет свойства, определяемого как свойство.Не будуАвтоматически добавляется в корневой элемент компонента, а это значит, что нам нужно вручную добавить его в корневой элемент компонента.Рассмотрим пример.
//父组件
...省略无关代码
render(){
return (
<Item data={this.data} class="large"/>
)
}
//Item.vue组件
export default {
functional:true,
name: "item",
render(h,context){
return (
<div class="red" >
{context.props.data}
</div>
)
}
}
Приведенный выше код предполагает, что имя класса .large будет передано корневому элементу Item, но это не так. нам нужно что-то добавить
// Item.vue
export default {
functional:true,
name: "item",
render(h,context){
return (
<div class="red" {...context.data}>
{context.props.data}
</div>
)
}
}
Обратите внимание, что все атрибуты добавляются к корневому элементу через оператор расширения.Этот context.data является атрибутом, который вы добавили к дочернему компоненту в родительском компоненте.Он будет интеллектуально объединен с атрибутами корневого элемента дочернего элемента. Теперь .large Имя класса передается. Это полезно, когда вам нужно привязать события от родительских компонентов к дочерним компонентам. Поговорим о небольшой яме о привязке событий
Передавая context.data в качестве второго параметра createElement, мы передаем все функции и прослушиватели событий выше my-functional-button. На самом деле это очень прозрачно, эти события даже не требуют модификатора .native.
Вышеприведенный абзац с официального сайта Vue, но, прочитав его один раз, я упустил из виду очень важное предложение, которое является последним предложением Он сказал, что модификатор .native не нужен? хорошо посмотри на код
// 父组件
methods:{
show(){
alert('你好')
}
},
render(){
return (
<Item data={this.data} onNativeClick={this.show} class="large"/>
)
}
Приведенный выше код на первый взгляд выглядит нормально. Пользовательский компонент использует onNativeClick, и в результате окно не появляется. Увы, я в итоге несколько раз прочитал объяснение в документе vue, и обнаружил, что исходный функциональный компонент не нуждается в модификаторе .native, и формат шаблона точно отражен, а вот для jsx ну и поставьте вышеуказанноеonNativeClick
изменить наonClick
Достаточно.
Какие функции существующих проектов можно заменить jsx?
На самом деле это очень похоже на пример, который я привел в начале. Я использовал его в своем проекте, чтобы избавиться от полноэкранного режима v-if/v-else. Так как мой бизнес на блокноте, требование состоит в том, чтобы в наборе контрольных работ были десятки вопросов, и только один вопрос должен отображаться на одном экране, а следующий вопрос отображается при нажатии на следующий вопрос. Идея относительно проста:
- Используйте переменную num для представления индекса темы, отображаемой в данный момент.
- num++ каждый раз, когда нажимается кнопка следующего вопроса
- Используйте v-if, чтобы определить num===1 и num===2, чтобы решить, что отображать.
В этом письме очень много шаблонов, так как шаблоны наших вопросов могут быть разными для каждого вопроса, нет возможности зациклиться, поэтому мы можем написать их все только вручную. Раньше я рассматривал возможность использования динамических компонентов для переключения, но отказался от этого, потому что это не интуитивно понятно.
Давайте посмотрим, как оптимизировать его с помощью jsx.
//父组件
export default {
name: "list",
data() {
return {
data:'我是函数式组件',
id:1,
tests:{
1:<div><span>第一道题</span></div>,
2:<div><section>第二道题</section></div>,
3:<div><p>第三道题</p></div>
}
}
},
methods:{
next(){
++this.id
}
},
render(){
return (
<div>
<Item data={this.tests[this.id]} class="large"/>
<button onClick={this.next}>下一题</button>
</div>
)
}
}
Структура каждого из вышеперечисленных вопросов противоречива
//子组件,只接受数据展示,用函数式组件
<script>
export default {
functional:true,
name: "item",
render(h,context){
return (
<div class="red" {...context.data}>
{context.props.data}
</div>
)
}
}
</script>
Вышеупомянутая функция выполняется без каких-либо оценок if/else.Я думаю, что здесь более уместно использовать jsx.Интересно, есть ли у вас какие-либо другие идеи?
Наконец
Подводя итог, мы обычно используем шаблон для разработки, потому что он интуитивно понятен и лаконичен, а различные инструкции очень удобны в использовании.Когда вы чувствуете, что код, написанный в шаблоне, выглядит избыточным, или вы хотите сами контролировать логику рендеринга, например зацикливание, суждение и т. д. Рассмотрите возможность использования JSX. Кроме того, рекомендуется использовать функциональные компоненты для повышения производительности.
Я впервые пишу статью.Я надеюсь, что большие ребята, которые нашли время, чтобы прочитать это, чувствуют, что это не строго и нужно простить.Я приму любые комментарии.