Enseñarle a escribir jsx en vue en detalle

Tabla de contenido

Prefacio:

1. Escribe una página con la función render:

2. Registrar eventos en la función de renderizado

3. ¿Cómo se reemplaza la instrucción vue en la función render?

1、v-si

2, espectáculo en v

3、v-para:

4, modelo v:

5, sincronización

Cuarto, el uso de ranuras en render

1. Ranura predeterminada

 2. Ranura con nombre

 3. Ranuras de alcance

5. Escritura de objetos de parámetros, vinculación de eventos y atributos en línea (objetos de datos en profundidad):

6. Por último, pruébalo con el ejemplo anterior:

¡Vaya aquí primero y actualice después!


Prefacio:

En los últimos años, vue3+tsx se ha vuelto más popular. Creo que el desarrollo de React aún debería entender muy bien la sintaxis de jsx, pero muchos desarrolladores junior e intermedios de Vue aún no saben cómo usar jsx y no saben cómo escribirlo. . A continuación, le enseñaré lentamente (vue2+jsx se usa en el proyecto, porque el tema trata sobre el uso de jsx en vue).

1. Escribe una página con la función render:

En primer lugar, hay una función de representación en vue, que solo admite la devolución de la estructura dom en forma de xml. Pero no puede usar .vue como sufijo de archivo al escribir la página, debe cambiarlo a jsx, si es ts, es tsx.
Aquí hay un hogar.jsx:

export default {
    name:'home',
    components:{},
    props:{},
    data(){
        return {
            info:{
                age:18
            }
        }
    },
    computed:{},
    watch:{},
    mounted(){},
    methods:{},
    render() {
        return <div>我是小明,我今年{this.info.age}岁</div>
    }
}

La página se muestra así:

De hecho, no es difícil escribir jsx en vue, pero la sintaxis es ligeramente diferente. Por ejemplo, en el ejemplo anterior, el sufijo del archivo home.jsx cambió de .vue a .jsx. Internamente, la estructura de la plantilla se mueve a la función de renderizado. Por supuesto, escribir la estructura de plantilla de la plantilla en la función de representación es lo mismo que el método de escritura general, pero todavía hay algunos puntos que necesitan atención.

En el ejemplo anterior, la variable en .vue se escribe así { {info.age}}, las llaves dobles en jsx se vuelven simples y la variable debe ir acompañada de esto.

2. Registrar eventos en la función de renderizado

El evento registrado en la función de renderizado es diferente del v-on:click||@click en la plantilla. Está sesgado hacia el sonido original, como el evento de clic onClick={tins.click}, el evento de entrada onInput= {this.input}, y el método de escritura es el siguiente:

export default {
    name: 'home',
    components: {},
    props: {},
    data() {
        return {
            info: {
                age: 18,
                gender: ''
            },
        }
    },
    computed: {},
    watch: {},
    mounted() {
    },
    methods: {
        Gender() {
            this.info.gender = '男';
        }
    },
    render() {
        return <div className="home">
            <div>我是小明,我今年{this.info.age}岁</div>
            <div>我是{this.info.gender}性</div>
            <button onClick={this.Gender}>查询我的性别</button>
        </div>
    }
}

La página es la siguiente:

3. ¿Cómo se reemplaza la instrucción vue en la función render?

No hay instrucciones en la función de representación, como v-if, v-show, etc. Todas estas son instrucciones personalizadas. Escribir v-if o v-show en vue es así, de la siguiente manera:

1、v-si

v-if en realidad controla el valor de retorno del código dentro de {}. volver dom o volver vacío

export default {
    name: 'home',
    components: {},
    props: {},
    data() {
        return {
            info: {
                age: 18,
                gender: ''
            },
        }
    },
    computed: {},
    watch: {},
    mounted() {
    },
    methods: {
        getGender() {
            this.info.gender = '男';
        },
        genderDom() {
            return this.info.gender ? <div>我是{this.info.gender}性</div> : ''
        }
    },
    render() {
        return <div className="home">
            <div>我是小明,我今年{this.info.age}岁</div>
            {/* 三元表达写法 */}
            {
                this.info.gender ? <div>我是{this.info.gender}性</div> : ''
            }

            {/* 也可以用&&判断写 */}
            {
                this.info.gender && <div>我是{this.info.gender}性</div>
            }

            {/* 函数返回写法 */}
            {
                this.genderDom()
            }
            {/* 错误写法,在render不能直接使用if else */}
            {/* {
                if(this.info.gender){
                    return <div>我是{this.info.gender}性</div>
                }else{
                    return ''
                }
            } */}
            <button onClick={this.getGender}>查询我的性别</button>
        </div>
    }
}

2, espectáculo en v

Todos deberían saber que v-show en vue es solo un bloque none|| que controla la visualización del estilo, por lo que en realidad es muy simple saber esto:

export default {
    name: 'home',
    components: {},
    props: {},
    data() {
        return {
            info: {
                age: 18,
                gender: ''
            },
        }
    },
    computed: {},
    watch: {},
    mounted() {
    },
    methods: {
        getGender() {
            this.info.gender = '男';
        },
        genderDom() {
            return this.info.gender ? <div>我是{this.info.gender}性</div> : ''
        }
    },
    render() {
        return <div className="home">
            <div>我是小明,我今年{this.info.age}岁</div>
            {/* 控制性别这个div的样式即可 */}
            <div style={
   
   { display: this.info.gender ? 'block' : 'none' }}>我是                
            {this.info.gender}性</div>
            <button onClick={this.getGender}>查询我的性别</button>
        </div>
    }
}

Nota: Style= { { display: this.info.gender ? 'block' : 'none' }} en el código anterior ¿se puede escribir así? style={obj}; obj={display: this.info.gender ? 'block' : 'none'}, ¿tiene sentido esto, solo hay un objeto dentro y las variables se colocan entre llaves simples?

3、v-para:

Implemente v-for en jsx, simplemente reemplácelo con .map:

// this.arr = [1,2,3,4,5];

<div>
    {this.arr.map((item,index)=><div key={index}>{item}</div>)}
</div>

4, modelo v:

Cuando se trata de v-model, debe comprender que v-model en vue es en realidad solo un azúcar sintáctico, que es una combinación de dos métodos: valor y @input. Luego escribe en render de la siguiente manera:

índice.jsx

import hobby from './component/hobby';
export default {
    name: 'home',
    components: { hobby },
    props: {},
    data() {
        return {
            info: {
                age: 18,
                gender: '',
                hobby: '我是一个没有爱好的木头人!'
            },
        }
    },
    computed: {},
    watch: {},
    mounted() {
    },
    methods: {
        getGender() {
            this.info.gender = '男';
        },
        genderDom() {
            return this.info.gender ? <div>我是{this.info.gender}性</div> : ''
        }
    },
    render() {
        return <div className="home">
            <div>我是小明,我今年{this.info.age}岁</div>
            {/* 控制性别这个div的样式即可 */}
            <div style={
   
   { display: this.info.gender ? 'block' : 'none' }}>我是        
            {this.info.gender}性</div>
            <button onClick={this.getGender}>查询我的性别</button>
            <hobby value={this.info.hobby} onInput={(value) => { this.info.hobby = 
             value }} />
        </div>
    }
}

Subcomponentes introducidos en index.jsx, hobby.jsx:

export default {
    name: 'hobby',
    components: {},
    props: {
        value: {
            type: String,
            debugger: '我是一个没有爱好的木头人!'
        }
    },
    data() {
        return {
        }
    },
    computed: {},
    watch: {},
    mounted() {
    },
    methods: {
    },
    render() {
        return <div className="hobby">
            我的爱好是:{this.value}
            <input value={this.value} onInput={(e) => { this.$emit('input',             
            e.target.value); }} />
        </div>
    }
}

Es tan problemático que no tomo capturas de pantalla de la página cada vez. ¡Prueba el código que copiaste tú mismo y lo sabrás! 

La entrada en hobby.jsx es en realidad una implementación de v-model, y luego escribe directamente en el componente hobby en index.jsx

v-model, de hecho, hobby acepta un valor y luego usa $emit un evento de entrada para modificar el valor de v-model. Por supuesto, también puede usar el modelo vue para cambiar el valor y la entrada del modelo v. Use un nombre personalizado (porque puede haber un valor o una entrada utilizada por otros parámetros en el desarrollo), por lo que no lo presentaré aquí.

Finalmente, si cree que v-model es demasiado problemático para escribir, desea usar v-model directamente en el renderizado. Entonces no es imposible,

para instalar una dependencia babel-plugin-jsx-v-model. Luego busque babel.config.js en el directorio raíz del proyecto, agregue

¡Puedes usarlo directamente!

5, sincronización

El uso de .sync en la plantilla es así: visible.sync="dialogVisible", pero el uso de .sync en el procesamiento es el siguiente

Componente padre index.jsx:

import hobby from './component/hobby';
import child from './component/child';
export default {
    name: 'home',
    components: { hobby, child },
    props: {},
    data() {
        return {
            info: {
                age: 18,
                gender: '',
                hobby: '我是一个没有爱好的木头人!'
            },
            childData: "父亲传给child的数据",
        }
    },
    computed: {},
    watch: {},
    mounted() {
    },
    methods: {
        getGender() {
            this.info.gender = '男';
        },
        genderDom() {
            return this.info.gender ? <div>我是{this.info.gender}性</div> : ''
        }
    },
    render() {
        return <div className="home">
            <div>我是小明,我今年{this.info.age}岁</div>
            {/* 控制性别这个div的样式即可 */}
            <div style={
   
   { display: this.info.gender ? 'block' : 'none' }}>我是 
            {this.info.gender}性</div>
            <button onClick={this.getGender}>查询我的性别</button>
            {/* <hobby value={this.info.hobby} onInput={(value) => {             
             this.info.hobby = value }} /> */}
            <hobby value={this.info.hobby} onInput={(value) => { this.info.hobby = 
             value }} />
            <div>模拟.sycn</div>
            {this.childData}
            
            <child
                {...{
                    props: {
                        value: this.childData
                    },
                    on: {
                        'update:value': (val) => {
                            console.log(val)
                            this.childData = val;
                        },
                    }
                }}
            />
        </div>
    }
}

En pocas palabras, puede darse tal situación, es decir, escribió un componente jsx, pero su colega no conoce jsx. Pero quiere usar el componente jsx que escribió y luego usar .sync, por lo que su colega escribió <child value.sync='value' /> así. Entonces no sabe cómo aceptarlo y cambiar el valor en value.sync='value'? De hecho, .sycn es solo un azúcar gramatical como el modelo V. Consiste en el nombre de la variable delante de .sycn, es decir, el método de vincular un valor (nombre personalizado) y en un nombre de 'actualización: valor'.

Cuarto, el uso de ranuras en render

1. Ranura predeterminada

Use la ranura predeterminada en la plantilla:

// 父组件
<template>
    <child>
    我是插入的内容
    </child>
</template>


// 子组件 child

<template>
    <div>
        <slot />
    </div>
</template>

Use la ranura predeterminada en render: 

// 父组件
render(){
    return <div>
        <child>
            默认插槽
        </child>
    </div>
}

// 父组件也可以这样写

render(){
    return <div>
        <child {
            ...{
                scopedSlots: {
                    default:()=>'默认插槽'
                }
            }
        }/>
    </div>
}

// child 子组件
render(){
    return <div>
        {this.$scopedSlots.default()}
    </div>
}

 2. Ranura con nombre

render(){
    return <div>
        <child {
            ...{
                scopedSlots: {
                    soltName:()=>'具名插槽'
                }
            }
        }/>
    </div>
}

// child 子组件
render(){
    return <div>
        {this.$scopedSlots.soltName()}
    </div>
}

 3. Ranuras de alcance

// 父组件
render(){
    return <div>
        <child {
            ...{
                scopedSlots: {
                    soltName:(scope)=><div>
                        child对我说:{scope}
                    </div>
                }
            }
        }/>
    </div>
}

// child 子组件
render(){
    return <div>
        {this.$scopedSlots.soltName('我是child,我要告诉你我的真心话!')}
    </div>
}

5. Escritura de objetos de parámetros, vinculación de eventos y atributos en línea (objetos de datos en profundidad):

Creo que mucha gente puede no entender la forma de pasar parámetros en el ejemplo anterior, de hecho, necesitas entender las diferencias entre los atributos props, attrs, on... del nodo dom. Es solo una forma diferente de escribir:

// template 中 你使用组件可能是这样写的
<child :value='value' @click="click" style="width=100px" calss='class'/>

// 上面给 child组件传了一个value,绑定了一个点击事件,加了一个行内样式,绑定了一个样式

// jsx中可以这样写

<child {...{
    props:{
        value:value,
    },
    on:{
        click:click
    },
    attrs:{
        style="width=100px",
        class="class"
    }
}}/>

// 这样写是不是看的更明白了?
const obj = {
    props:{
        value:value,
    },
    on:{
        click:click
    },
    attrs:{
        style="width=100px",
        class="class"
    }
}
<child {...obj}/>



 Nota:

on: es el evento vinculado. Por ejemplo, si necesita vincular el evento de entrada, solo necesita agregar un valor en forma de clave:valor al objeto on. La clave es el nombre de su evento, y el valor es la función que vinculas.

props: De hecho, son los props aceptados por el subcomponente, que tiene casi la forma de clave:valor como en.

attrs: los atributos en línea que deben vincularse al dominio actual, como clase, estilo, tipo, nombre, id, etc., se pueden ver en la consola.

Aprende de la introducción oficial, puedes ver: 

{
  // 与 `v-bind:class` 的 API 相同,
  // 接受一个字符串、对象或字符串和对象组成的数组
  'class': {
    foo: true,
    bar: false
  },
  // 与 `v-bind:style` 的 API 相同,
  // 接受一个字符串、对象,或对象组成的数组
  style: {
    color: 'red',
    fontSize: '14px'
  },
  // 普通的 HTML attribute
  attrs: {
    id: 'foo'
  },
  // 组件 prop
  props: {
    myProp: 'bar'
  },
  // DOM property
  domProps: {
    innerHTML: 'baz'
  },
  // 事件监听器在 `on` 内,
  // 但不再支持如 `v-on:keyup.enter` 这样的修饰器。
  // 需要在处理函数中手动检查 keyCode。
  on: {
    click: this.clickHandler
  },
  // 仅用于组件,用于监听原生事件,而不是组件内部使用
  // `vm.$emit` 触发的事件。
  nativeOn: {
    click: this.nativeClickHandler
  },
  // 自定义指令。注意,你无法对 `binding` 中的 `oldValue`
  // 赋值,因为 Vue 已经自动为你进行了同步。
  directives: [
    {
      name: 'my-custom-directive',
      value: '2',
      expression: '1 + 1',
      arg: 'foo',
      modifiers: {
        bar: true
      }
    }
  ],
  // 作用域插槽的格式为
  // { name: props => VNode | Array<VNode> }
  scopedSlots: {
    default: props => createElement('span', props.text)
  },
  // 如果组件是其它组件的子组件,需为插槽指定名称
  slot: 'name-of-slot',
  // 其它特殊顶层 property
  key: 'myKey',
  ref: 'myRef',
  // 如果你在渲染函数中给多个元素都应用了相同的 ref 名,
  // 那么 `$refs.myRef` 会变成一个数组。
  refInFor: true
}

6. Por último, pruébalo con el ejemplo anterior:

índice.jsx

import child from './component/child';
export default {
    name: 'Test',
    components: { child },
    props: {},
    data() {
        return {
            age: 17,
            arr: [{ name: '小明', age: 16 }, { name: '小明妈妈', age: 40 }, { name: '小明爸爸', age: 46 }]
        }
    },
    computed: {
        setOptions() {
            return {
                //插槽属性
                scopedSlots: {
                    default: (scope) => <div>我是默认插槽,{this.showScope(scope)} 
                    </div>,
                    slotsName: (scope) => <div>我是具名插槽,我的名字叫slotsName, 
                    {this.showScope(scope)}</div>,
                },
                props: {
                    age: this.age,
                },
                attrs: {
                    style: 'width:100%;height:200px;background-color:red'
                },
                on: {
                    ageAdd: () => { this.age++ },
                    input: (count) => { this.age = count }
                }
            }
        }
    },
    watch: {},
    mounted() {
    },
    methods: {
        showScope(scope) {
            return `子组件传给我的参数是:${scope}`
        }
    },
    render() {
        return <div class="Test">
            <div>父组件</div>
            我的年龄是:{this.age}
            <div>子组建</div>
            <child {...this.setOptions} />
            <div>小明全家</div>
            <ul>
                {
                    this.arr.map((item, index) => <div key={index}>
                        {item.name}:{item.age}
                    </div>)
                }
            </ul>
            {/* <child {...this.setOptions} v-model={this.age}/> */}
        </div>
    }
}

niño.jsx

export default {
    name: 'child',
    components: {},
    // model: {
    //     prop: "inputValue",
    //     event: "up",
    // },
    props: ['age'],
    data() {
        return {
        }
    },
    computed: {},
    watch: {},
    mounted() {
        console.log(this.$attrs, this.$listeners)
    },
    methods: {
    },
    render() {
        return <div class="child">
            <button onClick={() => { this.$emit('ageAdd') }}>老一岁</button>
            <div>
                修改年纪:
                <input value={this.age} onInput={(e) => { this.$emit('input',     
                 e.target.value) }} />
                {/* <input value={this.$attrs.inputValue} onInput={(e) => { 
                 this.$emit('up', e.target.value) }} /> */}
            </div>
            <div>插槽</div>
            {this.$scopedSlots.default&&this.$scopedSlots.default(666)}
            {this.$scopedSlots.slotsName&&this.$scopedSlots.slotsName(789)}
        </div>
    }
}

 Puede probarlo, el método debe usarse de manera flexible en el desarrollo y la lógica es clara.

De hecho, la introducción oficial es bastante detallada : función de renderizado y JSX — Vue.js

¡Vaya aquí primero y actualice después!

Supongo que te gusta

Origin blog.csdn.net/WEBYANGxw/article/details/128189456
Recomendado
Clasificación