Vue3+Vite+Ts project combat 02 configuración VueRouter, configuración Pinia y breve introducción, configuración SCSS

Configurar el enrutador Vue

El proyecto creado por Vite no integra Vue Router, y la integración debe instalarse manualmente.

Vue 3 utiliza la última versión de Vue Router v4.x.

# 安装
npm install vue-router@4

Cree un archivo de configuración de enrutamiento:

<!-- src\views\home\index.vue -->
<template>
  <div>
    首页
  </div>
</template>

<script setup lang="ts">
</script>

<style scoped>
</style>

<!-- src\views\login\index.vue -->
<template>
  <div>
    登录
  </div>
</template>

<script setup lang="ts">
</script>

<style scoped>
</style>

<!-- src\App.vue -->
<template>
  <router-view />
</template>

<script setup lang="ts">
</script>

// src\router\index.ts
import {
    
     createRouter, createWebHistory, RouteRecordRaw } from 'vue-router'

const routes:RouteRecordRaw[] = [
  {
    
    
    path: '/',
    name: 'home',
    component: () => import('@/views/home/index.vue')
  },
  {
    
    
    path: '/login',
    name: 'login',
    component: () => import('@/views/login/index.vue')
  }
]

const router = createRouter({
    
    
  // history: createWebHashHistory(), // hash 路由模式
  history: createWebHistory(), // history 路由模式
  routes // 路由规则
})

export default router

// src\main.ts
import {
    
     createApp } from 'vue'
import App from './App.vue'
import router from './router'

createApp(App)
  .use(router)
  .mount('#app')

Configurar administrador de estado Pinia

Introducción

Los proyectos creados por Vite no tienen una herramienta de gestión de estado integrada de forma predeterminada.

Antes de Vue 3, éramos más Vuex. La última versión de Vuex es la versión x4.x compatible con Vue2 y Vue3, pero la biblioteca de gestión estatal oficial de Vue3 se ha cambiado a Pinia (mantenida por el equipo central de Vue), y la El sitio web oficial de Vuex también emitió una declaración.

La razón de esto es que la API de Pinia es casi idéntica a lo que se describe en Vuex 5 RFC y lo hace mejor:

De hecho, Pinia es un producto originalmente destinado a explorar la próxima versión de Vuex, incorporando muchas de las ideas del equipo central para Vuex 5. Finalmente, nos dimos cuenta de que Pinia ya implementó la mayor parte de lo que queríamos ofrecer en Vuex 5 y decidimos convertirlo en nuestra nueva recomendación oficial.

En comparación con Vuex, Pinia proporciona una API más concisa y directa, y proporciona una API de estilo combinado y, lo que es más importante, proporciona una muy buena deducción de tipos cuando se usa TypeScript.

Pinia integrada

Instalar y registrar Pinia

Instalación | Pinia (vuejs.org)

npm install pinia

Cree la tienda raíz y pásela a la aplicación (tenga en cuenta que Pinia no define el contenido de inicialización al crear la instancia de la tienda):

// src\main.ts
import {
    
     createApp } from 'vue'
import App from './App.vue'
import router from './router'
import {
    
     createPinia } from 'pinia'

createApp(App)
  .use(router)
  .use(createPinia())
  .mount('#app')

Definir tienda

Definición de una tienda | Pinia (travel.org)

Pinia defineStore()define las tiendas usando , que devuelve una función para crear instancias de tiendas:

  • defineStore()Requiere un único name(también conocido como id) pasado como primer parámetro (obligatorio)
  • defineStore()Convención para usar use...como nombre de función (por ejemplo useCartStore, )
  • La tienda definida por defineStore()es equivalente al Módulo en Vuex.
// src\store\index.ts
import {
    
     defineStore } from 'pinia'

const useStore = defineStore('main', {
    
    
  state: () => ({
    
    
    count: 0
  }),
  getters: {
    
    
    doubleCount(state) {
    
    
      return state.count * 2
    }
  },
  actions: {
    
    
    increment() {
    
    
      this.count++
    }
  }
})

export default useStore

usar

Una vez que se crea una instancia de la tienda, se puede acceder a ella directamente state, gettersy actions.

Pinia no tiene Mutaciones de Vuex y puede usar directamente métodos sincrónicos y asincrónicos en Acciones.

<!-- src\views\home\index.vue -->
<template>
  <div>
    首页
    <button @click="store.increment">
      {
   
   { store.count }} => {
   
   { store.doubleCount }}
    </button>
  </div>
</template>

<script setup lang="ts">
import useStore from '@/store'

const store = useStore()
</script>

usar sintaxis de desestructuración

Tenga en cuenta que storees un reactiveobjeto envuelto con , lo que significa que no necesita escribir al acceder statey , al igual que en , no podemos desestructurarlo directamente:getters.valuesetupprops

<!-- src\views\home\index.vue -->
<template>
  <div>
    首页
    <button @click="store.increment">
      {
   
   { store.count }} => {
   
   { store.doubleCount }}
    </button>

    <div>count 永远是 0:{
   
   { count }}</div>
    <div>doubleCount 永远是 0:{
   
   { doubleCount }}</div>
  </div>
</template>

<script setup lang="ts">
import useStore from '@/store'

const store = useStore()

const {
      
       count, doubleCount } = store
// 在 script-setup 中使用解构赋值要通过 defineExpose 暴漏出去
defineExpose({
      
      
  count
})
</script>

Si desea utilizar la desestructuración y retener la reactividad, debe utilizar sotreToRefs()el método:

<!-- src\views\home\index.vue -->
<template>
  <div>
    首页
    <button @click="store.increment">
      {
   
   { store.count }} => {
   
   { store.doubleCount }}
    </button>

    <div>count 将会同步更新:{
   
   { count }}</div>
    <div>doubleCount 将会同步更新:{
   
   { doubleCount }}</div>
  </div>
</template>

<script setup lang="ts">
import useStore from '@/store'
import {
      
       storeToRefs } from 'pinia'

const store = useStore()

const {
      
       count, doubleCount } = storeToRefs(store)

defineExpose({
      
      
  count,
  doubleCount
})
</script>

Nota: se pueden desestructurar directamente storedesde actions, ya que están vinculados a storesí mismos ( thisapuntan internamente a store).

Una breve introducción a Pinia

Nota sobre la inferencia de tipo TS en Pinia

Pinia proporciona una buena compatibilidad con TypeScript de forma predeterminada, pero para obtener una inferencia de tipo completa, debe seguir algunas sugerencias de uso:

1. Declaración stateSe recomienda utilizar la función flecha, que inferirá automáticamente el tipo de atributo

Si usa una función que no sea de flecha, gettersuse el parámetro para stateacceder a la propiedad que TypeScript no reconoce

const useStore = defineStore('main', {
    
    
  // 使用非箭头函数定义
  state() {
    
    
    return {
    
    
      count: 0
    }
  },
  getters: {
    
    
    // 使用 state 访问状态
    doubleCount(state) {
    
    
      // IDE 提示:类型“{} & {}”上不存在属性“count”。ts(2339)
      return state.count * 2
    }
  },
  actions: {
    
    
    increment() {
    
    
      // IDE 提示:类型“{} & {}”上不存在属性“count”。ts(2339)
      this.count++
    }
  }
})

2. Para declarar la propiedad Getters, se recomienda usar stateparámetros para acceder al estado (función flecha o función no flecha). Aunque se pueden usar funciones no flecha this, el tipo no se inferirá automáticamente (cuando no statese definan parámetros formales). declarado, o el estado se define usando una función sin flecha)

  • Para evitar el uso this, la recomendación oficial es usar funciones de flecha.
  • storeSe recomienda usar solo cuando necesita obtener el valor completo this, pero debe definir explícitamente el tipo de retorno de la función, TypeScript no inferirá automáticamente
  • Se recomienda no declarar parámetros formales thisal utilizarstate
const useStore = defineStore('main', {
    
    
  state: () => ({
    
    
    count: 0
  }),
  getters: {
    
    
    // 没有声明 `state` 形参
    // IDE 提示:由于“doubleCount'”不具有返回类型批注并且在它的一个返回表达式中得到直接或间接引用,因此它隐式具有返回类型 "any"。ts(7023)
    doubleCount() {
    
    
      // IDE 提示:类型“{ doubleCount(): any; }”上不存在属性“count”。ts(2339)
      return this.count * 2
    },
    // 解决办法1
    doubleCount2(state) {
    
    
      return this.count * 2
    },
    // 解决办法2
    doubleCount3():number {
    
    
      return this.count * 2
    }
  },
  actions: {
    
    
    increment() {
    
    
      this.count++
    }
  }
})

Características básicas de Pinia

  • Estado
    • De forma predeterminada, a través storedel acceso a la instancia state, puede leer y escribir directamente, como@click="store.count++"
    • store.$reset()El método se puede utilizar para staterestablecer el valor inicial.
    • Además de storela modificación directa, statetambién se pueden enviar store.$patch()múltiples cambios a través del método, la principal diferencia es que se pueden agrupar múltiples cambios en una entrada en devtools y se admite el viaje en el tiempo.
    • Puede store.$subscribe()suscribirse a los cambios en el estado, y la suscripción solo se activará una vez que se modifiquen los parches. De forma predeterminada, las suscripciones están vinculadas al componente que lo agregó, se eliminan automáticamente cuando se desmonta el componente o se pueden configurar para conservarlas.
  • captadores
    • El valor de la propiedad Getters es una función que acepta statecomo primer argumento, para fomentar el uso de funciones de flecha
    • Las funciones que no son de flecha estarán vinculadas thisy se recomienda usarlas solo en storeescenarios en los que se deba obtener la instancia completa y el tipo de retorno de la función se deba definir explícitamente.
  • Comportamiento
    • Al igual que Gettes, se puede acceder thisa toda la storeinstancia a través de
    • Las acciones pueden ser asíncronas o síncronas, de cualquier manera se devuelve una Promesa
    • Las acciones pueden establecer parámetros libremente y devolver contenido, todo se inferirá automáticamente, sin necesidad de definir el tipo TS (¡guapo!)
    • Al igual que Estado, puede store.$onAction()suscribirse a Acciones a través de , la devolución de llamada se activará antes de la ejecución, y puede pasar los parámetros after()y onError()permitir que la función se ejecute después de la resolución y el rechazo de la Acción. De manera similar, la suscripción está vinculada al componente actual.

Gestión de estilo CSS

Función - CSS | Vite Documentación oficial en chino

  • Vite proporciona una versión mejorada @importque permite el uso de alias de Vite
  • Vite tiene PostCSS incorporado, si necesita una configuración adicional, solo proporcione postcss.config.jsel archivo
  • Cualquier archivo CSS .module.csscon un sufijo se considera un archivo de módulos CSS . La importación de dicho archivo devuelve un objeto de módulo correspondiente.
  • Vite proporciona soporte integrado para .scss, .sass, y archivos. No es necesario instalar complementos de Vite específicos para ellos, pero sí deben instalarse las dependencias de preprocesador correspondientes..less.styl.stylus

Instale Sass e inicialice la estructura de directorios

Este ejemplo usa Sass:

npm i -D sass

Cree la estructura de directorios de estilo:

styles
├─ index.scss # 统一导出
├─ common.scss # 全局公共样式
├─ mixin.scss # 全局 mixin
├─ transition.scss # 全局过渡动画样式
└─ variables.scss # 全局 Sass 变量
// src\styles\variables.scss
$red: red;
$pink: pink;

// src\styles\common.scss
body {
    
    
  background-color: $pink;
}

// src\styles\index.scss
@import './variables.scss';
@import './mixin.scss';
@import './transition.scss';
@import './common.scss';

Uso de variables de estilo global en componentes de un solo archivo

Las variables globales no se pueden usar directamente en componentes de un solo archivo y los archivos deben importarse manualmente:

<style lang="scss" scoped>
@import '@/styles/variables.scss';

div {
      
      
  color: $red;
}
</style>

Es demasiado engorroso importar manualmente cada archivo. Puede usar la herramienta de compilación Vite para inyectar automáticamente variables globales en los módulos de estilo de los componentes de un solo archivo.

El elemento de configuración de Vite css.preprocessorOptions se usa para especificar las opciones que se pasan al preprocesador de CSS.

// vite.config.ts
...

export default defineConfig({
    
    
  ...
  css: {
    
    
    preprocessorOptions: {
    
    
      // 给 sass-loader 传递选项
      scss: {
    
    
        // additionalData 的值就是要注入的字符串
        additionalData: '@import "@/styles/variables.scss";'
      }
    }
  }
})

Ahora el componente de un solo archivo se puede cambiar a:

<style lang="scss" scoped>
div {
      
      
  color: $red;
}
</style>

Usando variables de estilo en Vue3

<style>Vue 3 admite el enlace dinámico de variables de estilo en componentes de un solo archivo .

Variables que se pueden exponer a través de v-bindcomponentes vinculantes, el principio es que cuando el compilador SFC detecta tales variables CSS, v-bindlas reescribirá como nativas con nombres de variables Hash var().

La definición de las variables de estilo css nativo se insertará en stylelas propiedades de cada elemento DOM de nivel superior del componente.

<template>
  <h1 class="title">Hello World</h1>
  <p class="content">The content color is red</p>
</template>

<script setup lang="ts">
const theme = {
      
      
  color: 'red',
  fontSize: '30px'
}
</script>
<style>
.title {
      
      
  color: v-bind('theme.color');
}
.content {
      
      
  font-size: v-bind('theme.fontSize');
}
</style>

El DOM renderizado final del ejemplo anterior es el siguiente:

<h1 class="title" style="--5954443c-theme_color:red; --5954443c-theme_fontSize:30px;"> Hello World </h1>
<p class="content" style="--5954443c-theme_color:red; --5954443c-theme_fontSize:30px;"> The content color is red </p>

<style>
.title {
      
      
  color: var(--5954443c-theme_color);
}
.content {
      
      
  font-size: var(--5954443c-theme_fontSize);
}
</style>

No hay una introducción oficial a esta función, consulte rfcs/0043-sfc-style-variables para obtener más detalles.

Supongo que te gusta

Origin blog.csdn.net/u012961419/article/details/124300035
Recomendado
Clasificación