【好记忆不如烂笔头】学习Vue3

通过看小满zs学习Vue3知识点,将知识点记录下来。
更新中,未学完

了解UI库的使用

方便开发者快速开发

ElementUI安装方法

# NPM
$ npm install element-plus --save
# Yarn
$ yarn add element-plus
# pnpm
$ pnpm install element-plus

在mian.ts完整引入

import { createApp } from 'vue'
import './assets/css/reset.less'
import App from './App.vue'
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'

const app = createApp(App)
app.use(ElementPlus)
app.mount('#app')

Scoped和样式穿透

Scoped原理

vue中的Scoped是通过在DOM结构以及css样式上加唯一不重复的标记:data-v-hash,以保证唯一(由PostCSS转移实现),达到样式私有模块化。

样式穿透

Vue3推荐使用:deep(.el-input-inner){...}来修改组件库的样式

CSS新特性

插槽选择器

默认情况下,作用域样式不会影响到渲染出来的内容,他们被认为是父组件所持有并传递进来的。解决方案::slotted(.a){...}

全局选择器

解决方案:global(.a){...}

动态修改样式

<script setup lang="ts">
let valChangeStyle = ref({
  color: "red",
  background: "blue",
});
</script>

<template>
  <div class="val">动态修改样式</div>
</template>

<style lang="less" scoped>
.val {
  color: v-bind("valChangeStyle.color");
  background-color: v-bind("valChangeStyle.background");
}
</style>

css module

<script setup lang="ts">
const appCss = useCssModule("app");
// useCssModule可以帮助我们把样式名转为哈希值以保证样式的唯一性,在写render、ts的时候会好用一些。
console.log(appCss);
// { app: "_app_15pag_1", color: "_color_15pag_7", background: "_background_15pag_10" }
</script>

<template>
  <div :class="[app.color, app.background]">动态修改样式</div>
</template>

<style lang="less" module="app">
.color {
  color: green;
}
.background {
  background-color: pink;
}
</style>

Vue3集成Tailwind Css

Tailwind Css是一个由Js编写的css框架,基于 PostCss 解析的。

安装Tailwind以及其他依赖项

目前我安装的tailwind是3.x版本

$ npm install -D tailwindcss@latest postcss@latest autoprefixer@latest

生成配置文件

$ npx tailwindcss init -p

修改配置

tailwind.config.cjs

/** @type {import('tailwindcss').Config} */
module.exports = {
  content: ["./index.html", "./src/**/*.{vue,js,ts,jsx,tsx}"],
  theme: {
    extend: {},
  },
  plugins: [],
};

新建一个index.css

/* index.css */
@tailwind base;
@tailwind components;
@tailwind utilities;

在main.ts引入

import './index.css'

接入unoCss,自定义CSS原子化

什么叫CSS原子化

简单来说,就是以视觉效果命名,一眼看上去就知道这个样式代表什么。

为什么用

  1. 我们可以使用自定义规则进行rule校验,增加个人开发的方式。
  2. Tailwind生成的 CSS 文件会有数 MB 的大小。只有在生产构建下Tailwind 才会通过 PurgeCSS 来删除你不需要的规则,将CSS文件缩减到几KB,在开发环境下不符合按需加载的理念。

安装

$ npm i -D unocss

配置项

在vite.config.ts中配置如下:

import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import vueJsx from '@vitejs/plugin-vue-jsx';
import unoCss from 'unocss/vite'
import { presetIcons, presetAttributify, presetUno } from 'unocss'

export default defineConfig({
  plugins: [unoCss({
    // rules为二维数组,在rules中自定义规则,全局可用
    rules: [
      ['flex', { display: 'flex' }],
      ['bg-black', { background: 'black' }],
      // 动态原子化
      [/^m-(\d+)$/, ([, d]) => ({ margin: `${Number(d) * 10}px` })], // m-1即margin: 10px
    ],
    shortcuts: {
      // 组合样式
      block: ['flex', 'bg-black']
    },
    // presetIcons 预设图标
    // presetAttributify 预设class 引入这个写样式可以写成
    // presetUno 插件自带的预设类像使用tailwind一样 如bg-red-500
    presets: [presetIcons(), presetAttributify(), presetUno()]
  })],
})

在main.ts中配置如下:

import 'uno.css'

Event Loop 和 nextTick

同步任务

代码从上到下按顺序执行

异步任务

  1. 宏任务
    script(整体代码)、setTimeout、setlnterval、Ul交互事件、postMessage、Ajax
  2. 微任务
    Promise.then catch finally、MutaionObserver、.process.nextTick(Node.js环境)

运行机制

所有的同步任务都是在主进程执行的形成一个执行栈,主线程之外,还存在一个"任务队列”,异步任务执行队列中先执行宏任务,然后清空当次宏任务中的所有微任务,然后进行下一个tick,如此形成循环。nextTick就是创建一个异步任务,等到同步任务执行完成后才执行。

口诀

同步进程有任务,先宏后微。同步完成到异步。

Vue3开发移动端

移动端适配

安装依赖

目前我安装的postcss-px-to-viewport是1.1.1版本

$ npm install postcss-px-to-viewport -D

vite.config.ts配置

import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import vueJsx from '@vitejs/plugin-vue-jsx';
import px2ViewPort from 'postcss-px-to-viewport'
import { fileURLToPath, URL } from 'url';

// https://vitejs.dev/config/
export default defineConfig({
  css: {
    postcss: {
      plugins: [
        px2ViewPort({
          unitToConvert: 'px',//要转化的单位
          viewportwidth: 750,//UI设计為的宽度
          // 通常配置上面那两行就够了
          unitPrecision: 6,//转换后的精度,即小数点位数
          propList: ['*'], //指定转换的css属性的单位,*代表全部css属性的单位都进行转换
          viewportUnit: 'vw',//指定需要传换成的视窗单位,默认vw
          fontViewportUnit: 'vw', // 指定字体需要转换成的视窗单位,默认vw
          selectorBlackList: ['ignore-'],//指定不转换为视窗单位的英名,
          minPixelValue: 1,//默认值1,小于或等于1px则不进行转换
          mediaQuery: true,//是否在媒体查询的css代码中进行转换,默认false
          replace: true, // 是否转换后直接更换属性值
          landscape: false // 是否处理横屏情况
        })
      ]
    }
  },
  resolve: {
    alias: {
      '@': fileURLToPath(new URL('./src', import.meta.url))
    }
  }
})

如何将我们的vue项目打包成app

我先跳过。

使用Pinia替代Vuex

安装

$ npm install pinia

main.ts配置

import { createApp } from 'vue'
import App from './App.vue'
import { createPinia } from 'pinia'

const app = createApp(App)
const store = createPinia()

app.use(store)
app.mount('#app')

初始化仓库Store

Pinia抛弃了mutations状态,

  1. src下新建文件夹store
  2. 新建命名空间文件xxx.ts
// 命名空间枚举值
export const enum Names {
  USERSTORE = 'USERSTORE'
}
  1. 在文件夹下新建{name}.ts
import { defineStore } from "pinia";
// 导入命名空间
import { Names } from "./name-space";


// 定义初始化的值
export const userStore = defineStore(Names.USERSTORE, {
  // state、getters 和 actions 并且可以安全地假设这些概念等同于组件中的“数据”、“计算”和“方法”。
  state: () => {
    return {
      username: 'van'
    }
  }
})

如何使用

<script setup lang="ts">
import { userStore } from "./store/index";
const user = userStore();
</script>

<template>
  <div>状态:{{ user.username }}</div>
</template>

State

在Pinia中允许直接修改值,在Vuex不被允许。

<script setup lang="ts">
import { userStore } from "./store/index";
const user = userStore();

// 如何使用state?
// 1. 直接修改
// user.username + '123'
// 2. 通过patch+对象修改
// user.$patch({})
// 3. 通过patch+工厂函数修改,好处是在里面写逻辑
// user.$patch((state) => {
//   state.username = "哥哥最爱穿丝袜啦";
// });
// 4. 使用user.$state修改会修改到整个对象
// user.$state = {
//   username: "66666666666",
// };
// 5. 调用actions方法修改
// store/index.ts
// actions: {
//   setUserName() {
//     this.username = '9999999'
//   }
// }
// 页面调用 user.setUserName()
</script>

<template>
  <div>状态:{{ user.username }}</div>
</template>

<style lang="less" module="app">
html,
body,
#app {
  height: 100%;
  overflow: hidden;
}
</style>

结构不具有响应式怎么解决

和Vue3的toRefs用法差不多。
源码观看:

/**
 * Creates an object of references with all the state, getters, and plugin-added
 * state properties of the store. Similar to `toRefs()` but specifically
 * designed for Pinia stores so methods and non reactive properties are
 * completely ignored.
 *
 * @param store - store to extract the refs from
 */
function storeToRefs(store) {
    // See https://github.com/vuejs/pinia/issues/852
    // It's easier to just use toRefs() even if it includes more stuff
    if (isVue2) {
        // @ts-expect-error: toRefs include methods and others
        return toRefs(store);
    }
    else {
        store = toRaw(store);
        const refs = {};
        for (const key in store) {
            const value = store[key];
            if (isRef(value) || isReactive(value)) {
                // @ts-expect-error: the key is state or getter
                refs[key] =
                    // ---
                    toRef(store, key);
            }
        }
        return refs;
    }
}

原理:

  1. 转化为原始对象,把proxy解除掉,目的是防止重复引用到proxy。store=toRaw(store)
  2. 遍历对象,拷贝对象属性值,toRef(store,key)
import { userStore } from "./store/index";
import { storeToRefs } from "pinia";

const user = userStore();
const { username } = storeToRefs(user);

getters、actions

在Pinia中的actions可以同步、异步修改state,而Vuex需要通过mutations。

你可能感兴趣的:(蓝白的一些学习笔记,学习,typescript,vue.js)