Uso básico de la configuración de Vue3 y azúcar de sintaxis de configuración

¿Cuándo se ejecuta la instalación?

La configuración se usa para escribir API combinadas, desde la perspectiva de la función de enlace del ciclo de vida, es equivalente a reemplazar beforeCreate y se ejecutará antes de crear.

setup(props) {
  console.log("setup", props);
},
beforeCreate() {
  console.log("beforeCreate");
},
created() {
  console.log("created");
},

Después de la ejecución, el resultado de la impresión de configuración siempre está al frente.

Cómo se utilizan los datos y métodos de configuración

Las propiedades y los métodos dentro de la configuración deben exponerse al regresar para montar las propiedades en la instancia; de lo contrario, no hay forma de usarlos:

<template>
  <div class="hello">
    <h1>{
   
   { msg }}</h1>
  </div>
</template>
setup(props) {
  let msg = "hello";
  return {
    msg,
  };
},

¿Hay esto dentro de la configuración?

Imprima esto en la configuración usted mismo, y el resultado devuelto no está definido. Debido a que la configuración se ejecutará una vez antes de beforeCreate, por lo que no está definido, no existe dentro de la configuración y las cosas relacionadas con esto no se pueden montar.

setup(props) {
  console.log("setup", props);
  console.log("setup this", this);
},
beforeCreate() {
  console.log("beforeCreate");
},
created() {
  console.log("created");
},

Cómo usar la función de gancho en la configuración

Vue3 es un método de escritura de estilo de opción que es compatible con vue2, por lo que la función de enlace puede coexistir con la configuración, lo que es equivalente a la API de opciones; pero si hay un conflicto entre las configuraciones de vue2 y vue3, el la configuración de vue3 tiene prioridad.

export default{ 
    setup(){  
        console.log('setup'); 
    }, 
    mounted(){  
        console.log('mounted'); 
    }
}

La nueva función setup() de vue3 se usa para escribir API combinadas, por lo que no se recomienda escribir código como este. Por lo tanto, debe usar la familia de funciones onXXX para registrar la función de enlace. Después de que el registro sea exitoso, se pasa una función de devolución de llamada al llamar.  

import { onMounted } from "vue";
export default{ 
    setup(){  
        const a = 0  
        return{   a  }  
        onMounted(()=>{   
            console.log("执行"); 
        }) 
    }
}

Estas funciones de enlace de ciclo de vida registradas solo se pueden usar de forma sincrónica durante la configuración, ya que dependen del estado interno global para ubicar la instancia del componente actual, y se generará un error cuando no se llame a la función en el componente actual.

Las otras funciones de enlace son las mismas, solo impórtalas según sea necesario.

La relación entre la configuración y la función de gancho

Cuando la configuración se realiza en paralelo con las funciones de enlace, la configuración no puede llamar a funciones relacionadas con el ciclo de vida, pero el ciclo de vida puede llamar a propiedades y métodos relacionados con la configuración.

<template> 
    <button @click="log">点我</button>
</template><script>

export default{ 
    setup(){  
        const a = 0  return{   a  } 
    }, 
    methods:{  
        log(){   
            console.log( this.$options.setup() );//返回一个对象  
        } 
    }
}
</script>

this.$options.setup() devuelve un objeto grande, que contiene todas las propiedades y métodos en la configuración.

parámetro de configuración

Al usar la configuración, recibirá dos parámetros: ** accesorios y contexto. **

accesorios

El primer parámetro es props, lo que significa que el componente principal pasa el valor al componente secundario y la propiedad recibida se declara dentro del componente. Cuando se recibe en el componente secundario, los datos recibidos se empaquetan en un objeto proxy, que puede realizar capacidad de respuesta Al pasar Actualizar automáticamente cuando se importan nuevos accesorios.

export default{ 
    props: {  
        msg: String,  
        ans: String, 
    }, 
    setup(props,context){  
        console.log(props);//Proxy {msg: "着急找对象", ans: "你有对象吗?"} 
    },
}

Debido a que props responde, no se puede usar la deconstrucción de ES6, lo que eliminará la capacidad de respuesta de props. En este caso, es necesario tomar prestada la deconstrucción de toRefs.

import { toRefs } from "vue"; 
export default{  
    props: {   
        msg: String,   
        ans: String,  
    },  
    setup(props,context){   
        console.log(props);   
        const { msg,ans } = toRefs(props)   
        console.log(msg.value); //着急找对象   console.log(ans.value); //你有对象吗?  
    }, 
}

Cuando usamos componentes, a menudo nos encontramos con parámetros opcionales. Algunos lugares necesitan pasar un cierto valor, y otras veces no. ¿Cómo lidiar con eso?

Si ans es un parámetro opcional, no se puede pasar ans en props. En este caso, toRefs no creará una referencia para ans y se debe usar toRef en su lugar.

import { toRef } from "vue";
setup(props,context){ 
    let ans  = toRef(props ,'ans')// 不存在时,创建一个ans 
    console.log(ans.value);
}

contexto

contexto El entorno de contexto, que incluye tres partes: atributos, ranuras y eventos personalizados.

setup(props,context){ 
    const { attrs,slots,emit } = context // attrs 获取组件传递过来的属性值, // slots 组件内的插槽 // emit 自定义事件 子组件
}
  • attrs es un objeto que no responde, que recibe principalmente el atributo no-props pasado desde fuera del componente. A menudo se usa para pasar algunos atributos de estilo, pero los atributos que no están declarados en la configuración de props son equivalentes a; durante la comunicación proceso entre los componentes principal y secundario, el componente principal envía this.$attrsdatos Pasados, si el subcomponente no se recibe con accesorios, aparecerá en attrs, pero no en VM.Si se recibe con accesorios, aparecerá en VM pero no en atributos

  • slots es un objeto proxy, donde slots.default() obtiene una matriz, la longitud de la matriz está determinada por la ranura del componente y el contenido de la ranura está dentro de la matriz.

  • emit: una función que distribuye eventos personalizados, equivalente a this.$emit.

Esto no existe en la configuración, por lo que emit se usa para reemplazar el anterior this.$emit, y se usa cuando el elemento secundario se pasa al elemento principal y se activa el evento personalizado.

<template> 
    <div :style="attrs.style">  
        <slot></slot>    
        <slot name="hh"></slot>  
		<button @click="emit('getVal','传递值')">子向父传值</button>  
	</div> 
</template>

<script>
import { toRefs,toRef } from "vue";
export default{ 
    setup(props,context){  
        const { attrs,slots,emit } = context  // attrs 获取组件传递过来 style 属性     
        console.log('slots',slots.default());//插槽数组 
        console.log('插槽属性',slots.default()[1].props); //获取插槽的属性    
        return{  attrs,  emit   }  
    }, 
}
</script>

Resumen de las funciones de configuración

  • Esta función se ejecutará antes de crearse, como se explicó anteriormente.

  • No hay esto dentro de la configuración, y las cosas relacionadas con esto no se pueden montar.

  • Las propiedades y los métodos dentro de la configuración deben exponerse a través del retorno, de lo contrario, no hay forma de usarlos.

  • Los datos internos de configuración no son reactivos.

  • La configuración no puede llamar funciones relacionadas con el ciclo de vida, pero las funciones del ciclo de vida pueden llamar funciones en la configuración.

Puntos a tener en cuenta: (1) Trate de no mezclar las configuraciones de vue2 y vue3 (2) la configuración no puede ser una función asíncrona, porque el valor devuelto ya no es el objeto devuelto, sino una promesa, y la plantilla no puede ver los atributos en el objeto de retorno. (También puede devolver una instancia de Promise más tarde, pero requiere la cooperación de Suspense y componentes asincrónicos)

// 引入的不再是Vue构造函数了,引入的是一个名为createApp的工厂函数
import { createApp } from 'vue'
import App from './App.vue'

// 创建应用实例对象——app(类似于之前Vue2中的vm,但app比vm更“轻”)
const app = createApp(App)

// 挂载
app.mount('#app')

<configuración de script> azúcar sintáctico

<script setup>Las variables, funciones y contenido introducido por importación que no necesitan ser declarados a cambio se pueden <template/>usar en

<script setup>
import { getToday } from './utils'
// 变量
const msg = 'hello'
// 函数
function log() {
    console.log(msg)
}
</script>

// 在 templete 中直接使用声明的变量、函数以及 import 引入的内容
<template>
    <div @click="log">{
   
   { msg }}</div>
	<p>{
   
   { getToday() }}</p>
</template>

El componente estándar <script> necesita escribir la función de configuración y devolver el retorno

<script>
//import引入的内容
import { getToday } from './utils'  
export default{
 setup(){
    // 变量
    const msg = 'Hello!'
    // 函数
    function log() {
      console.log(msg)
    }
    //想在tempate里面使用需要在setup内return暴露出来
    return{
       msg,
       log,
       getToday 
    }
 }
}
</script>

<template>
  <div @click="log">{
   
   { msg }}</div>
   <p>{
   
   {getToday()}}</p>
</template>

El código en <script setup> azúcar sintáctica se compilará en el contenido de la función setup() del componente, y cualquier vinculación en el nivel superior de la instrucción `<script setup>` (incluidas variables, funciones y el contenido introducido por `import`) será Se puede usar directamente en la plantilla, sin exponer las variables declaradas, funciones y contenido de importación a través de return, se puede usar en <templet>, y no hay necesidad de escribir export default{}, cuando usando `<configuración de script>` .

El código en <script setup> azúcar sintáctico se compilará en el contenido de la función setup() del componente. Esto significa que, a diferencia del <script> normal, que solo se ejecuta una vez cuando se introduce el componente por primera vez, el código dentro de <script setup> se ejecutará cada vez que se cree la instancia del componente.

<script>
  console.log('script');//多次实例组件,只触发一次
  export default {
      setup() {
          console.log('setupFn');//每次实例化组件都触发和script-setup标签一样
      }
  }
  </script>

La etiqueta <script setup> finalmente se compilará en setup()el contenido de la función, y cada vez que se crea una instancia del componente, la función de configuración se instancia una vez. La función de configuración en la etiqueta del script también es la misma. Cada vez que crea una instancia de un componente, crea una instancia de la función de configuración una vez, pero la configuración de la etiqueta del script debe escribirse en el valor predeterminado de exportación{}, y el exterior solo se ejecuta una vez cuando se presenta por primera vez.

<script setup>Los componentes importados se registrarán automáticamente

No es necesario registrar el componente a través de `components:{}` después de importar el componente, se puede usar directamente

<script setup>
import MyComponent from './MyComponent.vue'
//components:{MyComponent}  不需要注册直接使用
</script>

<template>
  <MyComponent />
</template>

Dado que se hace referencia a los componentes como variables en lugar de registrarlos como claves de cadena, <script setup>al usar componentes dinámicos en , debe usar :isenlace dinámico

comunicación de componentes

<script setup>debe usar definePropsuna defineEmitsAPI en lugar de accesorios y emisiones en

`defineProps` y `defineEmits` tienen una inferencia de tipo completa y están directamente disponibles en `<configuración de script>` (después de explorar los Nuggets, descubrí que la mayoría de las demostraciones de artículos aún presentan estas dos API a través de la importación, que es el documento oficial claramente escrito)

defineProps en lugar de props, recibe los datos pasados ​​por el componente principal (el componente principal pasa parámetros al componente secundario)

componente padre:

<template>
  <div>父组件</div>
  <Child :title="msg" />
</template>

<script setup>
import {ref} from 'vue'
import Child from './child.vue'
const msg = ref('父的值')  //自动返回,在template直接解套使用
</script>

Subensamblaje:

  • <template/>Puede usar directamente los accesorios pasados ​​por el componente principal (los accesorios se pueden omitir).

  • <script-setup>Necesita que el componente principal pase los accesorios a través de props.xx

<template>
  <div>子组件</div>
  <div>父组件传递的值:{
   
   {title}}</div>
</template>

<script setup>
//import {defineProps} from 'vue'   不需要引入

//语法糖必须使用defineProps替代props
const  props = defineProps({
  title: {
    type: String
  }
});
//script-setup 需要通过props.xx获取父组件传递过来的props
console.log(props.title) //父的值
</script>

defineEmit reemplaza emit, el componente secundario pasa datos al componente principal (el componente secundario expone datos al exterior)

Código de subcomponente:

<template>
  <div>子组件</div>
  <button @click="toEmits">子组件向外暴露数据</button>
</template>

<script setup>
import {ref} from 'vue'
const name = ref('我是子组件')
//1、暴露内部数据
const  emits = defineEmits(['childFn']);

const  toEmits = () => {
  //2、触发父组件中暴露的childFn方法并携带数据
  emits('childFn',name)
}
</script>

Código del componente principal:

<template>
  <div>父组件</div>
  <Child  @childFn='childFn' />
  <p>接收子组件传递的数据{
   
   {childData}} </p>
</template>

<script setup>
import {ref} from 'vue'
import Child from './child.vue'
    
const childData = ref(null)    
const childFn=(e)=>{
    consloe.log('子组件触发了父组件childFn,并传递了参数e')
    childData=e.value
}    
</script>

<script setup>Es necesario exponer activamente las propiedades del componente secundario al componente principal: defineExpose

<script setup>Para los componentes que usan , el componente principal no puede $parentobtener datos de respuesta, como la referencia del componente secundario a través de ref o , y necesita exponerlo activamente a través de defineExpose

Código de subcomponente:

<script setup>
import { ref } from 'vue'

const a = 1
const b = ref(2)
//主动暴露组件属性
defineExpose({
  a,
  b
})
</script>

Código del componente principal:

<template>
  <div>父组件</div>
  <Child  ref='childRef' />
  <button @click='getChildData'>通过ref获取子组件的属性 </button>
</template>

<script setup>
import {ref} from 'vue'
import Child from './child.vue'
const childRef= ref()  //注册响应数据  
const getChildData =()=>{
  //子组件接收暴露出来得值
  console.log(childRef.value.a) //1
  console.log(childRef.value.b) //2  响应式数据
}    
</script>

Azúcar sintáctico para otras características

`useSlots` y `useAttrs` (** rara vez se usan**, ya que la mayoría de las personas están desarrollando en modo SFC, las ranuras se pueden representar a través de la etiqueta `<slot/>` en `<template/>`)

Si necesita usar `slots` y `attrs` en `script-setup`, debe usar `useSlots` y `useAttrs` en su lugar

Necesito introducir: `import { useSlots ,useAttrs } form 'vue'`

Es más conveniente acceder a través de `$slots` y `$attrs` en `<template/>` (attrs se usa para obtener los parámetros/métodos no accesorios que se pasan al componente secundario en el componente principal, y se usa attrs para obtener parámetros/métodos no props en el componente principal pasados ​​de props a subcomponentes, los atributos se utilizan para obtener parámetros/métodos no props pasados ​​a subcomponentes en el componente principal, las ranuras pueden obtener objetos dom virtuales pasados ​​por ranuras en el componente principal , y no debería ser útil en el modo SFC Grande, se usa más en JSX/TSX)

componente padre:

<template>
  <Child msg="非porps传值子组件用attrs接收" >
    <!-- 匿名插槽 -->
    <span >默认插槽</span>
    <!-- 具名插槽 -->
    <template #title>
      <h1>具名插槽</h1>
    </template>
    <!-- 作用域插槽 -->
    <template #footer="{ scope }">
      <footer>作用域插槽——姓名:{
   
   { scope.name }},年龄{
   
   { scope.age }}</footer>
    </template>
  </Child>
</template>

<script setup>
// 引入子组件
import Child from './child.vue'
</script>

Subensamblaje:

<template>
  <!-- 匿名插槽 -->
  <slot />
  <!-- 具名插槽 -->
  <slot name="title" />
  <!-- 作用域插槽 -->
  <slot name="footer" :scope="state" />
  <!-- $attrs 用来获取父组件中非props的传递到子组件的参数 -->
  <p>{
   
   { attrs.msg == $attrs.msg }}</p>
  <!--true  没想到有啥作用... -->
  <p>{
   
   { slots == $slots }}</p>
</template>

  
<script setup>
import { useSlots, useAttrs, reactive, toRef } from 'vue'
const state = reactive({
  name: '张三',
  age: '18'
})

const slots = useSlots()
console.log(slots.default()); //获取到默认插槽的虚拟dom对象
console.log(slots.title());   //获取到具名title插槽的虚拟dom对象
// console.log(slots.footer()); //报错  不知道为啥有插槽作用域的无法获取
//useAttrs() 用来获取父组件传递的过来的属性数据的(也就是非 props 的属性值)。
const attrs = useAttrs()
</script>

Enrutamiento de acceso en la configuración

Acceder a la información del componente de la instancia de enrutamiento: ruta y enrutador

No se puede acceder a `this` en `setup` y ya no se puede acceder directamente a `this.$router` o `this.$route`. (getCurrentInstance puede reemplazar esto pero no se recomienda)

Recomendación: use la función `useRoute` y la función `useRouter` en lugar de `this.$route` y `this.$router`

<script setup>
import { useRouter, useRoute } from 'vue-router'
    const route = useRoute()
    const router = useRouter()
    
    function pushWithQuery(query) {
      router.push({
        name: 'search',
        query: {
          ...route.query,
        },
      })
    }
<script/>

guardia de navegación

Los protectores de navegación para los componentes de la instancia de ruta aún se pueden usar

import router from './router'
router.beforeEach((to,from,next)=>{

})

También puede usar el protector de navegación de la API combinadaonBeforeRouteLeave, onBeforeRouteUpdate

<script setup>
import { onBeforeRouteLeave, onBeforeRouteUpdate } from 'vue-router'

    // 与 beforeRouteLeave 相同,无法访问 `this`
    onBeforeRouteLeave((to, from) => {
      const answer = window.confirm(
        'Do you really want to leave? you have unsaved changes!'
      )
      // 取消导航并停留在同一页面上
      if (!answer) return false
    })

    const userData = ref()

    // 与 beforeRouteUpdate 相同,无法访问 `this`
    onBeforeRouteUpdate(async (to, from) => {
      //仅当 id 更改时才获取用户,例如仅 query 或 hash 值已更改
      if (to.params.id !== from.params.id) {
        userData.value = await fetchUser(to.params.id)
      }
    })
<script/>

Los protectores de API compuestos también se pueden usar en cualquier componente <router-view>representado , no tienen que usarse directamente en componentes de enrutamiento como lo hacen los protectores en componentes.

Usar con script normal

<script setup> se puede usar con <script> normal. En estos casos, se puede usar <script> ordinario.

  • No se puede usar en <script setup>opciones declaradas, como inheritAttrsopciones personalizadas habilitadas por complementos

  • Declarar exportaciones con nombre

  • Ejecute efectos secundarios o cree objetos que solo necesitan ejecutarse una vez

<script>
    // 普通 <script>, 在模块范围下执行(只执行一次)
    runSideEffectOnce()
    
    // 声明额外的选项
    export default {
      inheritAttrs: false,
      customOptions: {}
    }
</script>

<script setup>
    // 在 setup() 作用域中执行 (对每个实例皆如此)
</script>

Resumen: el azúcar sintáctico de la configuración es un complemento de Vue3, lo que hace que Vue3 sea más completo.

<script setup> es azúcar sintáctico en tiempo de compilación para usar la API de composición en componentes de un solo archivo. Tiene muchas ventajas sobre la sintaxis <script> normal

  • Menos contenido repetitivo, código más conciso
  • Capacidad para declarar accesorios y lanzar eventos usando Typescript puro
  • Mejor rendimiento en tiempo de ejecución (su plantilla se compilará en una función de representación en el mismo ámbito que ella, sin ningún proxy intermedio)
  • Mejor rendimiento de inferencia de tipo IDE (menos trabajo para el servidor de idiomas para extraer tipos del código)

Supongo que te gusta

Origin blog.csdn.net/qq_43641110/article/details/129981821
Recomendado
Clasificación