D32 Vue2 + Vue3 K124-K143

news2024/12/25 12:49:13

D32.Vue

 F21.创建vue3项目(K124-K129)

     该笔记是从vue2过渡到vue3的,所以不会特别详细的介绍某些vue2学过的,主要介绍vue3新增的
  1.Vue3快速上手
  A. Vue3简介
   1)2020年9月18日,Vue.js发布3.0版本,代号:One Piece(海贼王)
   2)耗时2年多、2600+次提交、30+个RFC、600+次PR、99位贡献者
  B. Vue3带来了什么
   1)性能的提升
    a. 打包大小减少41%
    b. 初次渲染快55%, 更新渲染快133%
    c.内存减少54%
    d. …
   2)源码的升级
    a. 使用Proxy代替defineProperty实现响应式
    b. 重写虚拟DOM的实现和Tree-Shaking
    c. …
   3)拥抱TypeScript
    a. Vue3可以更好的支持TypeScript
   4)新的特性
    a. Composition API(组合API)

  • setup配置
  • ref与reactive
  • watch与watchEffect
  • provide与inject
  •    ...

        b. 新的内置组件

  • Fragment
  • Teleport
  • Suspense
  •    ...

        c. 其他改变

  • 新的生命周期钩子
  • data 选项应始终被声明为一个函数
  • 移除keyCode支持作为 v-on 的修饰符
  •    ...

      2.创建Vue3.0工程
      A.使用 vue-cli 创建
       官方文档:https://cli.vuejs.org/zh/guide/creating-a-project.html#vue-create

    ### 查看@vue/cli版本,确保@vue/cli版本在4.5.0以上
    vue --version
    ### 安装或者升级你的@vue/cli
    npm install -g @vue/cli
    ### 创建
    vue create vue_test
    ### 启动
    cd vue_test
    npm run serve
    

      B.使用 vite 创建
       1)官方文档:https://v3.cn.vuejs.org/guide/installation.html#vite
        a. 什么是vite?—— 新一代前端构建工具
        b. 优势如下:

  • 开发环境中,无需打包操作,可快速的冷启动
  • 轻量快速的热重载(HMR)
  • 真正的按需编译,不再等待整个应用编译完成
  • ### 创建工程
    
    ## npm 6.x
    $ npm init vite@latest <project-name> --template vue  
    ### 如: npm init vite@latest vue3-study --template vue
    
    ## npm 7+,需要加上额外的双短横线
    $ npm init vite@latest <project-name> -- --template vue
    
    ### 使用 PNPM:
    pnpm create vite <project-name> -- --template vue
    ## pnpm create vite vite-app -- --template vue
    
    ### 进入工程目录
    cd <project-name>
    ### 安装依赖
    pnpm install
    ### 运行
    pnpm run dev
    

         vite里面导入vue模块要加后缀名,不然会报错
          import Demo from ‘./components/Demo.vue’
      C.命令行界面
       1)在安装了 Vite 的项目中,可以在 npm scripts 中使用 vite 可执行文件,或者直接使用 npx vite 运行它。下面是通过脚手架创建的 Vite 项目中默认的 npm scripts:

    {
      "scripts": {
        "dev": "vite", // 启动开发服务器,别名:`vite dev`,`vite serve`
        "build": "vite build", // 为生产环境构建产物
        "preview": "vite preview" // 本地预览生产构建产物
      }
    }
    

          可以指定额外的命令行选项,如 --port 或 --https。运行 npx vite --help 获得完整的命令行选项列表
      D.常用 Composition API
       1)官方文档: https://v3.cn.vuejs.org/guide/composition-api-introduction.html
      E.Composition API 的优势
       1)Options API 存在的问题
         使用传统OptionsAPI中,新增或者修改一个需求,就需要分别在data,methods,computed里修改
       2)Composition API 的优势
         可以更加优雅的组织我们的代码,函数。让相关功能的代码更加有序的组织在一起
      F.全局API的转移
        a. Vue 2.x 有许多全局 API 和配置
          例如:注册全局组件、注册全局指令等

    //注册全局组件
    Vue.component('MyButton', {
      data: () => ({
        count: 0
      }),
      template: '<button @click="count++">Clicked {{ count }} times.</button>'
    })
    
    //注册全局指令
    Vue.directive('focus', {
      inserted: el => el.focus()
    }
    

        b. Vue3.0中对这些API做出了调整:
          将全局的API,即:Vue.xxx调整到应用实例(app)上
    在这里插入图片描述
      G.其它改变
       1)data选项应始终被声明为一个函数
       2)过度类名的更改:
        a. Vue2.x写法

    .v-enter,
    .v-leave-to {
      opacity: 0;
    }
    .v-leave,
    .v-enter-to {
      opacity: 1;
    }
    

        b. Vue3.x写法

    .v-enter-from,
    .v-leave-to {
      opacity: 0;
    }
    
    .v-leave-from,
    .v-enter-to {
      opacity: 1;
    }
    

       3)移除keyCode作为 v-on 的修饰符,同时也不再支持config.keyCodes
       4)移除v-on.native修饰符
        a. 父组件中绑定事件

    <my-component
      v-on:close="handleComponentEvent"
      v-on:click="handleNativeClickEvent"
    />
    

        b. 子组件中声明自定义事件

    <script>
      export default {
        emits: ['close']
      }
    </script>
    

       5)移除过滤器(filter)
         过滤器虽然这看起来很方便,但它需要一个自定义语法,打破大括号内表达式是 “只是 JavaScript” 的假设,这不仅有学习成本,而且有实现成本!建议用方法调用或计算属性去替换过滤器
       6)…
      H.路径别名
       1)vite.config.ts

    import { resolve } from 'path';
    export default defineConfig({
      resolve: {
        // 配置别名
        alias: {
          '@': path.resolve(__dirname, './src'),
          '@c': path.resolve(__dirname, './src/components'),
          '@v': path.resolve(__dirname, './src/views'),
          '@h': path.resolve(__dirname, './src/hooks'),
          '@s': path.resolve(__dirname, './src/store'),
        },
      },
    });
    
    1.path模块需要 pnpm i @types/node -D
    
    2.tsconfig.node.json文件配置
    
    "compilerOptions": {
    
    "allowSyntheticDefaultImports": true
    
    },
    
    3.tsconfig.json文件配置
    
    "compilerOptions": {
    
    "baseUrl": "./",
    
    "paths": {
    
    "@/*": ["src/*"],
    
    "@h/*": ["src/hooks/*"],
    
    "@s/*": ["src/store/*"]
    
    },
    
    },
    
    解决文件路径红线
    

      I.导入ts文件
       1)当在main.ts文件导入别名的时候报错导入路径不能以“.ts”扩展名结束。考虑改为导入“./utils/Bus.js”
       2)解决方案
         既然不允许用扩展名,那么我省略扩展名好了
          vite.config.ts

    export default defineConfig({
      resolve: {
        alias: {
          '@': path.resolve(__dirname, 'src')
        },
        extensions: ['.ts', '.js', '.mjs', '.jsx', '.tsx', '.json']
      }
    })
    

         这样,扩展名就不需要写了
      J.使用Scss
       1)首先用pnpm i sass -D
       2)在style标签中使用lang='scss’就可以了
       3)注意
         如果像这样,定义了很多scss文件
    在这里插入图片描述
         直接引入是找不到这些文件里面定义的内容的
         会有这样的报错
    在这里插入图片描述

         解决方法
        在src目录中定义sytle.scss文件
    在这里插入图片描述

          style.scss

    @import '@/styles/reset.scss';
    @import '@/styles/variables.scss';
    @import '@/styles/mixins.scss';
    

          然后在vite.config.ts中配置

    import { defineConfig } from 'vite'
    import vue from '@vitejs/plugin-vue'
    
    export default defineConfig({
      // 使用scss
      css: {
        preprocessorOptions: {
          scss: {
            additionalData: `@import "./src/style.scss";`
          },
        },
      },
    })
    

     F22.Vuex(K130-K136)

      1.理解 Vuex
      A.Vuex 是什么
       1)概念:专门在Vue中实现集中式状态(数据)管理的一个Vue插件,对Vue应用中多个组件的共享状态进行集中式的管理(读/写),也是一种组件间通信的方式,且适用于任意组件间通信
      B.什么时候使用 Vuex
       1)多个组件依赖于同一状态
       2)来自不同组件的行为需要变更同一状态
      C.原理图
    在这里插入图片描述

      2.搭建Vuex环境
       1)下载安装 pnpm add vuex@3
       2)创建文件:src/store/index.js

    import Vue from 'vue'
    import Vuex from 'vuex'	// 引入Vuex
    
    Vue.use(Vuex)	// 应用Vuex插件
    
    const actions = {}		// 准备actions——用于响应组件中的动作
    const mutations = {}	// 准备mutations——用于操作数据(state)
    const state = {}			// 准备state——用于存储数据
    
    // 创建并暴露store
    export default new Vuex.Store({
    	actions,
    	mutations,
    	state,
    })
    

       3)在main.js中创建vm时传入store配置项

    import Vue from 'vue'
    import App from './App.vue'
    import store from './store'	// 引入store
    
    Vue.config.productionTip = false
    
    new Vue({
    	el: '#app',
    	render: h => h(App),
    	store,	// 配置项添加store
    	beforeCreate() {
    		Vue.prototype.$bus = this
    	}
    })
    

      3.使用Vuex编写
       1)初始化数据、配置actions、配置mutations,操作文件store.js

    import Vue from 'vue'
    import Vuex from 'vuex'	// 引入Vuex
    
    Vue.use(Vuex)	// 应用Vuex插件
    
    // 准备actions——用于响应组件中的动作
    const actions = {
    	/* jia(context,value){
    		console.log('actions中的jia被调用了')
    		context.commit('JIA',value)
    	},
    	jian(context,value){
    		console.log('actions中的jian被调用了')
    		context.commit('JIAN',value)
    	}, */
    	jiaOdd(context,value){	// context 相当于精简版的 $store
    		console.log('actions中的jiaOdd被调用了')
    		if(context.state.sum % 2){
    			context.commit('JIA',value)
    		}
    	}
    }
    // 准备mutations——用于操作数据(state)
    const mutations = {
    	JIA(state,value){
    		console.log('mutations中的JIA被调用了')
    		state.sum += value
    	},
    	JIAN(state,value){
    		console.log('mutations中的JIAN被调用了')
    		state.sum -= value
    	}
    }
    // 准备state——用于存储数据
    const state = {
    	sum:0 //当前的和
    }
    
    // 创建并暴露store
    export default new Vuex.Store({
    	actions,
    	mutations,
    	state,
    })
    

       2)组件中读取vuex中的数据:$store.state.sum
       3)组件中修改vuex中的数据: $store.dispatch('action中的方法名',数据) $store.commit('mutations中的方法名',数据)
         备注:若没有网络请求或其他业务逻辑,组件中也可以越过actions,即不写dispatch,直接编写commit
        src/components/Count.vue

    <template>
    	<div>
    		<h1>当前求和为:{{ $store.state.sum }}</h1>
    		<select v-model.number="n">
    			<option value="1">1</option>
    			<option value="2">2</option>
    			<option value="3">3</option>
    		</select>
    		<button @click="increment">+</button>
    		<button @click="decrement">-</button>
    		<button @click="incrementOdd">当前求和为奇数再加</button>
    	</div>
    </template>
    
    <script>
    	export default {
    		name:'Count',
    		data() {
    			return {
    				n:1, //用户选择的数字
    			}
    		},
    		methods: {
    			increment(){
                    // commit 是操作 mutations
    				this.$store.commit('JIA',this.n)
    			},
    			decrement(){
                    // commit 是操作 mutations
    				this.$store.commit('JIAN',this.n)
    			},
    			incrementOdd(){
                    // dispatch 是操作 actions
    				this.$store.dispatch('jiaOdd',this.n)
    			},
    		}
    	}
    </script>
    
    <style lang="css">button{margin-left: 5px;}</style>
    

      4.getters 配置项
       1)概念:当state中的数据需要经过加工后再使用时,可以使用getters加工
       2)在store.js中追加getters配置

    ......
    
    const getters = {
    	bigSum(state){
    		return state.sum * 10
    	}
    }
    
    // 创建并暴露store
    export default new Vuex.Store({
    	......
    	getters
    })
    

       3)组件中读取数据:$store.getters.bigSum
      5.四个map方法的使用
       1)mapState方法:用于帮助我们映射state中的数据为计算属性

    computed: {
        //借助mapState生成计算属性:sum、school、subject(对象写法)
         ...mapState({sum:'sum',school:'school',subject:'subject'}),
             
        //借助mapState生成计算属性:sum、school、subject(数组写法)
        ...mapState(['sum','school','subject']),
    },
    

       2)mapGetters方法:用于帮助我们映射getters中的数据为计算属性

    computed: {
        //借助mapGetters生成计算属性:bigSum(对象写法)
        ...mapGetters({bigSum:'bigSum'}),
    
        //借助mapGetters生成计算属性:bigSum(数组写法)
        ...mapGetters(['bigSum'])
    },
    

       3)mapActions方法:用于帮助我们生成与actions对话的方法,即:包含$store.dispatch(xxx)的函数

    methods:{
        //靠mapActions生成:incrementOdd、incrementWait(对象形式)
        ...mapActions({incrementOdd:'jiaOdd',incrementWait:'jiaWait'})
    
        //靠mapActions生成:incrementOdd、incrementWait(数组形式)
        ...mapActions(['jiaOdd','jiaWait'])
    }
    

       4)mapMutations方法:用于帮助我们生成与mutations对话的方法,即:包含$store.commit(xxx)的函数

    methods:{
        //靠mapActions生成:increment、decrement(对象形式)
        ...mapMutations({increment:'JIA',decrement:'JIAN'}),
        
        //靠mapMutations生成:JIA、JIAN(对象形式)
        ...mapMutations(['JIA','JIAN']),
    }
    

         备注:mapActions与mapMutations使用时,若需要传递参数需要:在模板中绑定事件时传递好参数,否则参数是事件对象

    <template>
    	<div>
    		<h1>当前求和为:{{ sum }}</h1>
    		<h3>当前求和的10倍为:{{ bigSum }}</h3>
    		<h3>我是{{ name }},我在{{ school }}学习</h3>
    		<select v-model.number="n">
    			<option value="1">1</option>
    			<option value="2">2</option>
    			<option value="3">3</option>
    		</select>
    		<button @click="increment(n)">+</button>
    		<button @click="decrement(n)">-</button>
    		<button @click="addOdd(n)">当前求和为奇数再加</button>
    		<button @click="addWait(n)">等一等再加</button>
    	</div>
    </template>
    
    <script>
    	import {mapState, mapGetters, mapMutations, mapActions} from 'vuex'	
    
    	export default {
    		name: 'Count',
    		data() {
    			return {
    				n:1, //用户选择的数字
    			}
    		},
      computed: {		
    			...mapState(['sum','school','name']),
    			...mapGetters(['bigSum'])
    		},
    		methods: {
    			...mapMutations({increment:'ADD', decrement:'SUBTRACT'}),
    			...mapActions(['addOdd', 'addWait'])
    		},
    	}
    </script>
    
    <style>
    	button{
    		margin-left: 5px;
    	}
    </style>
    

      6.模块化+命名空间
       1)目的:让代码更好维护,让多种数据分类更加明确
       2)修改store.js 为了解决不同模块命名冲突的问题,将不同模块的namespaced: true,之后在不同页面中引入getter、actions、mutations时,需要加上所属的模块名

    const countAbout = {
      namespaced:true,//开启命名空间
      state:{x:1},
      mutations: { ... },
      actions: { ... },
      getters: {
        bigSum(state){
           return state.sum * 10
        }
      }
    }
    
    const personAbout = {
      namespaced:true,//开启命名空间
      state:{ ... },
      mutations: { ... },
      actions: { ... }
    }
    
    const store = new Vuex.Store({
      modules: {
        countAbout,
        personAbout
      }
    })
    

       3)开启命名空间后,组件中读取state数据:

    //方式一:自己直接读取
    this.$store.state.personAbout.list
    //方式二:借助mapState读取:
    ...mapState('countAbout',['sum','school','subject']),
    

       4)开启命名空间后,组件中读取getters数据:

    //方式一:自己直接读取
    this.$store.getters['personAbout/firstPersonName']
    //方式二:借助mapGetters读取:
    ...mapGetters('countAbout',['bigSum'])
    

       5)开启命名空间后,组件中调用dispatch

    //方式一:自己直接dispatch
    this.$store.dispatch('personAbout/addPersonWang',person)
    //方式二:借助mapActions:
    ...mapActions('countAbout',{incrementOdd:'jiaOdd',incrementWait:'jiaWait'})
    

       6)开启命名空间后,组件中调用commit

    //方式一:自己直接commit
    this.$store.commit('personAbout/ADD_PERSON',person)
    //方式二:借助mapMutations:
    ...mapMutations('countAbout',{increment:'JIA',decrement:'JIAN'}),
    

     F22.vue3自动导入配置(K137-K143)

      1.自动导入组件库组件
       1)unplugin-vue-components
    在这里插入图片描述

       2)安装
         pnpm install unplugin-vue-components -D
          然后将下面的代码添加到 Vite 的配置文件
       3)Vite配置

    // vite.config.js
    import { defineConfig } from 'vite'
    import Components from 'unplugin-vue-components/vite'
    import {
      ElementPlusResolver,
      AntDesignVueResolver,
      VantResolver,
      HeadlessUiResolver,
      ElementUiResolver
    } from 'unplugin-vue-components/resolvers'
    
    export default defineConfig({
      plugins: [
        Components({
          // ui库解析器,也可以自定义
          resolvers: [
            ElementPlusResolver(),
            AntDesignVueResolver(),
            VantResolver(),
            HeadlessUiResolver(),
            ElementUiResolver()
          ]
        })
      ]
    })
    

       4)插件会生成一个ui库组件以及指令路径components.d.ts文件,详情看这个vue3的issue types(defineComponent): support for expose component types

    // components.d.ts
    
    // generated by unplugin-vue-components
    // We suggest you to commit this file into source control
    // Read more: https://github.com/vuejs/vue-next/pull/3399
    
    declare module 'vue' {
      export interface GlobalComponents {
        ElAside: typeof import('element-plus/es')['ElAside']
        ElButton: typeof import('element-plus/es')['ElButton']
        ElContainer: typeof import('element-plus/es')['ElContainer']
        ElDropdown: typeof import('element-plus/es')['ElDropdown']
        ElDropdownItem: typeof import('element-plus/es')['ElDropdownItem']
        ElDropdownMenu: typeof import('element-plus/es')['ElDropdownMenu']
        ElHeader: typeof import('element-plus/es')['ElHeader']
        ElIcon: typeof import('element-plus/es')['ElIcon']
        ElMain: typeof import('element-plus/es')['ElMain']
        ElMenu: typeof import('element-plus/es')['ElMenu']
        ElMenuItem: typeof import('element-plus/es')['ElMenuItem']
        ElResult: typeof import('element-plus/es')['ElResult']
      }
    }
    
    export { }
    

          想了解其他的打包工具(Rollup, Vue CLI),请参考 unplugin-vue-components
       5)自动导入自己的组件
         直接写组件名即可,插件会帮你引入进来 注意别重名

    // vite.config.js
    import { defineConfig } from 'vite'
    import Components from 'unplugin-vue-components/vite'
    
    export default defineConfig({
      plugins: [
        Components({
          // 指定组件位置,默认是src/components
          dirs: ['src/components', 'src/views'],
          // ui库解析器
          // resolvers: [ElementPlusResolver()],
          extensions: ['vue'],
          // 配置文件生成位置
          dts: 'src/components.d.ts'
        })
      ]
    })
    

          插件会生成一个自己组件路径的components.d.ts文件,详情再看这个vue3的issue types(defineComponent): support for expose component types

    // components.d.ts
    
    // generated by unplugin-vue-components
    // We suggest you to commit this file into source control
    // Read more: https://github.com/vuejs/vue-next/pull/3399
    
    declare module 'vue' {
      export interface GlobalComponents {
        BaseFilter: typeof import('./components/Common/BaseFilter.vue')['default']
        BaseHeader: typeof import('./components/Common/BaseHeader.vue')['default']
        BasePagination: typeof import('./components/Common/BasePagination.vue')['default']
        BaseSidebar: typeof import('./components/Common/BaseSidebar.vue')['default']
        BaseTags: typeof import('./components/Common/BaseTags.vue')['default']
        BaseTitle: typeof import('./components/Common/BaseTitle.vue')['default']
      }
    }
    
    export { }
    

      2.自动导入Vue 函数和自己的公用函数
      A.自动导入Vue 函数
       1)自动导入vue3的hooks,借助unplugin-auto-import/vite这个插件
         支持vue, vue-router, vue-i18n, @vueuse/head, @vueuse/core等自动引入
       2)安装

    pnpm i -D unplugin-auto-import
    

       3)Vite配置

    // vite.config.js
    import { defineConfig } from 'vite'
    import AutoImport from 'unplugin-auto-import/vite'
    
    export default defineConfig({
      plugins: [
        AutoImport({
          // Auto import functions from Vue, e.g. ref, reactive, toRef...
          // 自动导入 Vue 相关函数,如:ref, reactive, toRef 等
          imports: ['vue', 'vue-router', ,'vue-i18n', '@vueuse/head', '@vueuse/core',],
          // 可以选择auto-import.d.ts生成的位置,使用ts建议设置为'src/auto-import.d.ts'
           dts: 'src/auto-import.d.ts'
            
        })
      ]
    })
    

       4)原理: 安装的时候会自动生成auto-imports.d文件(默认是在根目录)

    // Generated by 'unplugin-auto-import'
    // We suggest you to commit this file into source control
    declare global {
      const ref: typeof import('vue')['ref']
      const reactive: typeof import('vue')['reactive']
      const computed: typeof import('vue')['computed']
      const createApp: typeof import('vue')['createApp']
      const watch: typeof import('vue')['watch']
      const customRef: typeof import('vue')['customRef']
      const defineAsyncComponent: typeof import('vue')['defineAsyncComponent']
      .
      .
      .
    }
    export {}
    

       5)可以选择auto-import.d.ts生成的位置,使用ts建议设置为src/auto-import.d.ts
          可以选择auto-import.d.ts生成的位置,使用ts建议设置为src/auto-import.d.ts
      B.自动导入自己的公用函数
       1)默认导入axios,分别导入pinia的storeToRefs

    AutoImport({
          // Auto import functions from Vue, e.g. ref, reactive, toRef...
          // 自动导入 Vue 相关函数,如:ref, reactive, toRef 等
          imports: [
            'vue',
            'vue-router',
            {
              axios: [
                // default imports
                ['default', 'axios'], // import { default as axios } from 'axios',
              ],
               pinia: ['storeToRefs'],
                // import { storeToRefs } from 'pinia'
            },
            '@vueuse/core',
          ],
        }),
    

       2)自动导入自己定义的函数

      AutoImport({
        // Auto import for module exports under directories
        // by default it only scan one level of modules under the directory
        dirs: ['./src/utils'],
        // 可以选择auto-import.d.ts生成的位置,使用ts建议设置为'src/auto-import.d.ts'
        dts: 'src/auto-import.d.ts',
        // 在vue模板中使用
        vueTemplate: true,
      }),
    

         观察auto-import.d.ts文件

    export {}
    declare global {
      const axios: typeof import('axios')['default']
      const bus: typeof import('./utils/bus')['bus']
      const diffDays: typeof import('./utils/date')['diffDays']
      const formatDate: typeof import('./utils/date')['formatDate']
      const http: typeof import('./utils/service')['http']
      const isDark: typeof import('./utils/dark')['isDark']
    }
    

      3.自动导入组件库样式

    import { createStyleImportPlugin, ElementPlusResolve  } from 'vite-plugin-style-import';
    
    plugins: [vue(),
     //按需导入element-plus的css样式
         createStyleImportPlugin({
          resolves: [ElementPlusResolve()],
        }),
    ], //查看 插件 API 获取 Vite 插件的更多细节 https://www.vitejs.net/guide/api-plugin.html
    

      4.自动导入icon
       1)安装依赖

    # @iconify-json/ep 是 Element Plus 的图标库
    pnpm i -D unocss @iconify-json/ant-design
    

       2)修改 vite.config.ts 配置

    // vite.config.ts
    import { defineConfig } from 'vite'
    import vue from '@vitejs/plugin-vue'
    import Unocss from 'unocss/vite'
    import {
      presetAttributify,
      presetIcons,
      presetUno,
      transformerDirectives,
      transformerVariantGroup,
    } from 'unocss';
    
    export default defineConfig({
      plugins: [
        vue(),
    
        // 添加以下配置
        Unocss({
          presets: [
            presetUno(),
            presetAttributify(),
            presetIcons({
              scale: 1.2,
              warn: true,
            }),
          ],
          transformers: [transformerDirectives(), transformerVariantGroup()],
        })
      ]
    })
    

       3)修改 main.ts

    // 在 main.ts 里添加以下代码
    import 'uno.css'
    

       4)使用

    // svg图片
    <i
        class="i-ant-design-picture-filled w-330px h-240px"
    />
    // 图标字体
    <i
        i="ant-design-picture-filled"
    />
    

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/341899.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

高性能(一)

思维导图 一、负载均衡 1.概念 将用户请求分摊到不同服务器上处理&#xff0c;以提高系统整体的并发处理能力及可靠性。 如图&#xff1a;我们用到负载均衡&#xff0c;实现访问商品服务的请求的分流。 负载均衡是一种常用且简单的提高系统并发和可靠性的手段&#xff0c;单…

MySQL入门篇-MySQL 二进制日志binlog介绍

MySQl binlog介绍 binlog的作用 逻辑日志,记录的是数据库内部的所有变动&#xff08;sql语句 行的改变&#xff09; server层日志&#xff0c;binlog不仅仅记录innodb的变动&#xff0c;也记录myisam存储引擎的变动。 innodb redo 是存储引擎层&#xff0c;和binlog不是一层&…

spark02-内存数据分区切分原理

代码&#xff1a;val conf: SparkConf new SparkConf().setMaster("local[*]").setAppName("wordcount") val scnew SparkContext(conf) //[1] [2,3] [4,5] val rdd: RDD[Int] sc.makeRDD(List(1,2,3,4,5),3) //将处理的数据保存分区文件 rdd.saveAsText…

【PTA Advanced】1152 Google Recruitment(C++)

目录 题目 Input Specification: Output Specification: Sample Input 1: Sample Output 1: Sample Input 2: Sample Output 2: 思路 代码 题目 In July 2004, Google posted on a giant billboard along Highway 101 in Silicon Valley (shown in the picture below)…

清除 git 所有历史提交记录,使其为新库

清除 git 所有历史提交记录&#xff0c;使其为新库需求方案需求 基于以前的仓库重新开发&#xff0c;这样可保留以前的配置等文件&#xff0c;但是需要删除全部的历史记录、tag、分支等。 方案 创建新的分支 使用 --orphan 选项&#xff0c;可创建1个干净的分支&#xff08;无…

设置测试用例的具体方法

文章目录一、等价类分区/分块的概念等价类的划分二、边界值三、因果图(判定表)四、场景设计法五、错误猜测法总结一、等价类 用户的密码为6~18位,测试的时候使用到的测试数据是什么? 穷举法,6,7,8,9,10…18全部都测试一边,可以 但是将范围改成6~1000位,穷举法就不可取了 分区/…

从零实现高并发WebRTC服务器(五):ICE协议

文章目录零、ICE具体做些什么一、ICE协议是什么二、ICE Candidate2.1 ICE CANDIDATE TYPE2.2 收集candidate零、ICE具体做些什么 收集candidate对不同type的所有candidate pair进行排序&#xff0c;比如优先使用同一内网的host candidate连通性检查 一、ICE协议是什么 ICE,i…

线性杂双功能PEG试剂OPSS-PEG-Acid,OPSS-PEG-COOH,巯基吡啶聚乙二醇羧基

英文名称&#xff1a;OPSS-PEG-COOH&#xff0c;OPSS-PEG-Acid 中文名称&#xff1a;巯基吡啶-聚乙二醇-羧基 OPSS-PEG-COOH是一种具有OPSS和羧基的线性杂双功能PEG试剂。它是一种有用的带有PEG间隔基的交联剂。OPSS代表正吡啶基二硫化物或邻吡啶基二硫代&#xff0c;与硫醇、…

Java 修饰符和运算符,超详细整理,适合新手入门

目录 一、访问控制修饰符 1、访问权限 二、运算符 1、算术运算符 2、关系运算符 3、逻辑运算符 4、赋值运算符 5、三元运算符 一、访问控制修饰符 Java 支持 4 种不同的访问权限&#xff1a; private 私有的 protected 受保护的 public 公共的 default 默认 1、…

程序员必备小众又实用的网站,你知道几个?

程序员是世人眼中的高薪职业&#xff0c;虽然亚历山大&#xff0c;但是年收入非常可观。 职场上的程序员有很多所谓的标签&#xff0c; 比如&#xff1a;秃头&#xff0c;找不到女朋友&#xff0c;和产品经理的斗智斗勇等等.... 可以说&#xff0c;一个程序员的必备素养就是…

【C++11智能指针】unique_ptr

【C11智能指针】unique_ptr 概述 一个 unique_ptr “拥有”它所指向的对象。 与 shared_ptr 不同&#xff0c;某个时刻只能有一个 unique_ptr 指向一个给定对象。 当 unique_ptr 被销毁时&#xff0c;它所指向的对象也被销毁。 初始化 直接初始化 unique_ptr<int> p…

AcWing 166. 数独(DFS + 剪枝优化 + lowbit函数 + 状态压缩)

AcWing 166. 数独&#xff08;DFS 剪枝优化 lowbit函数 状态压缩&#xff09;一、题目二、分析1、状态压缩2、lowbit函数&#xff08;1&#xff09;函数作用&#xff08;2&#xff09;函数实现3、DFS思路4、剪枝优化三、代码一、题目 二、分析 1、状态压缩 那么如果针对某一…

情人节专场即将到来,各大平台各显神通

一年一度的情人节即将到来&#xff0c;情人节除了有情侣、恋人之间表达爱意或者追求浪漫之外&#xff0c;也有很多人想要购买一些特殊的礼物送给自己的爱人或者亲人。对于跨境电商而言&#xff0c;这个时段往往能更好的将品牌与社交媒体上的目标客户建立起联系&#xff0c;同时…

【青训营】分布式定时任务简述

这是我参与「第五届青训营 」伴学笔记创作活动的第 13 天 分布式定时任务简述 定义 定时任务是指系统为了自动完成特定任务&#xff0c;实时、延时、周期性完成任务调度的过程。分布式定时任务是把分散的、可靠性差的定时任务纳入统一平台&#xff0c;并且实现集群管理调度和…

OpenCV-PyQT项目实战(6)项目案例02滚动条应用

欢迎关注『OpenCV-PyQT项目实战 Youcans』系列&#xff0c;持续更新中 OpenCV-PyQT项目实战&#xff08;1&#xff09;安装与环境配置 OpenCV-PyQT项目实战&#xff08;2&#xff09;QtDesigner 和 PyUIC 快速入门 OpenCV-PyQT项目实战&#xff08;3&#xff09;信号与槽机制 …

JumpServer开源堡垒机v3.0版本设计重点解读

编者注&#xff1a;在1月17日的JumpServer开源堡垒机v3.0预发布恳谈会直播中&#xff0c;JumpServer创始人广宏伟与大家分享了JumpServer v3.0版本的设计思路与功能亮点。在v3.0版本正式发布之前&#xff0c;JumpServer开源项目组基于此次直播内容为大家整理总结了JumpServer v…

C++11可变模板参数

C11可变模板参数一、简介二、语法三、可变模版参数函数3.1、递归函数方式展开参数包3.2、逗号表达式展开参数包一、简介 C11的新特性–可变模版参数&#xff08;variadic templates&#xff09;是C11新增的最强大的特性之一&#xff0c;它对参数进行了高度泛化&#xff0c;它能…

STM32单片机红外遥控

红外遥控接口电路STM32单片机红外遥控程序源代码#include "sys.h"#define LED_RED PBout(12) //红色发光二极管控制管脚初始化PB12#define LED_GREEN PBout(13) //绿色发光二极管控制管脚初始化PB13#define LED_YELLOW PBout(14) //黄色发光二极管控制管脚初始化PB14…

反射,枚举,lambda表达式

目录 1、反射 1.1 基本概念 1.2 反射相关的类 1.3 创建 Class 对象 1.4 反射的使用 1.4.1 通过反射创建对象&#xff1a; 1.4.2 获取私有的构造方法 1.4.3 获取私有的成员变量 1.4.4 获取私有的方法 1.5 总结 2、枚举 2.1 认识枚举 2.2 使用枚举 2.3 枚举与反射…

第4章 流程控制-if-else,Switch,For循环(循环守卫,循环步长,倒叙打印),While循环,多重循环...

第 4 章 流程控制-if-else,Switch,For循环(循环守卫&#xff0c;循环步长&#xff0c;倒叙打印)&#xff0c;While循环&#xff0c;多重循环 4.1 分支控制 if-else 让程序有选择的的执行&#xff0c;分支控制有三种&#xff1a;单分支、双分支、多分支 4.1.1 单分支 1)基本语法…