Skip to content

vue

事件修饰符

https://cn.vuejs.org/guide/essentials/event-handling.html#event-modifiers

.stop.prevent.self.capture.once.passive

v-model

vue
<input :value="text" @input="event => text = event.target.value">
vue
<input v-model="text">

<input><textarea> 绑定 value 监听 input

<input type="checkbox"><input type="radio"> 绑定 checked property , 侦听 change

自定义

vue
<CustomInput
  :model-value="searchText"
  @update:model-value="(newValue) => (searchText = newValue)"
/>

modelValueupdate:modelValue

修饰符 与 自定义修饰符

修饰符

.number 转换为 number

.trim 去两头的空

自定义修饰符

默认的为 modelModifiers

自定义的为 自定义名+Modifiers,如 title 就为 titleModifiers

js
// 这是默认,即 v-model
const [model, modifiers] = defineModel();

// 这是带自定义名 的 v-model:first-name
const [firstName, firstNameModifiers] = defineModel("firstName");

dom

https://cn.vuejs.org/guide/essentials/template-refs.html

setup 需要注意返回

3.5+

vue
<template>
  <input ref="my-input" />
</template>

<script setup>
import { useTemplateRef, onMounted } from "vue";

// 第一个参数必须与模板中的 ref 值匹配
const input = useTemplateRef("my-input");

onMounted(() => {
  input.value.focus();
});
</script>

旧版本

vue
<template>
  <input ref="input" />
</template>

<script setup>
import { ref, onMounted } from "vue";

// 声明一个 ref 来存放该元素的引用
// 必须和模板里的 ref 同名
const input = ref(null);

onMounted(() => {
  input.value.focus();
});
</script>

watch

注意!

参数应该是 ref、reactive、getter。
reactive 应该是整个一起监听,如果是 reactive.xxxx 必须使用 getter!

watchEffect

js
watchEffect(async () => {
  const response = await fetch(
    `https://jsonplaceholder.typicode.com/todos/${todoId.value}`
  );
  data.value = await response.json();
});

回调会立即执行。每当 todoId.value 变化时,回调会再次执行。

watchEffect 的副作用发生期间追踪依赖。它会在同步执行过程中,自动追踪所有能访问到的响应式属性。

其他

immediate 立即执行

js
watch(
  source,
  (newValue, oldValue) => {
    // 立即执行,且当 `source` 改变时再次执行
  },
  { immediate: true }
);

once

js
watch(
  source,
  (newValue, oldValue) => {
    // 当 `source` 变化时,仅触发一次
  },
  { once: true }
);

触发时机

默认是在 父组件更新 (如有) 之后、所属组件的 DOM 更新之前

调整到素有 DOM 之后,flush: 'post'
任何更新之前触发,flush: 'sync'

终止

js
watch(id, (newId) => {
  const controller = new AbortController();

  // 仅在 Vue 3.5+ 中支持,并且不支持异步,即使 await
  fetch(`/api/${newId}`, { signal: controller.signal }).then(() => {});

  onWatcherCleanup(() => {
    // 终止过期请求
    controller.abort();
  });
});

善后

setup 会自动注册和销毁 watchEffect,但是如果是异步中创建的,那就必须自己手动处理。

js
setTimeout(() => {
  const unwatch = watchEffect(() => {});

  // ...当该侦听器不再需要时
  unwatch();
}, 0);

不要异步创建!!!

deep

知道即可 谨慎使用

函数组件

js
import { ref } from "vue";

export default {
  setup() {
    const count = ref(0);
    return { count };
  },
  template: `
    <button @click="count++">
      You clicked me {{ count }} times.
    </button>`,
  // 也可以针对一个 DOM 内联模板:
  // template: '#my-template-element'
};
js
function BaseLayout(slots) {
  return `<div class="container">
      <header>${slots.header}</header>
      <main>${slots.default}</main>
      <footer>${slots.footer}</footer>
    </div>`;
}

props

js
export default {
  props: {
    title: String,
  },
};
html
<!-- 等同于传入 :disabled="true" -->
<MyComponent disabled />

Attributes 透传

禁止透传

vue
<script setup>
defineOptions({ inheritAttrs: false });
</script>

多节点需要自己 设置 Attributes,如:

html
<header>...</header>
<main v-bind="$attrs">...</main>
<footer>...</footer>

访问 Attributes

vue
<script setup>
import { useAttrs } from "vue";

const attrs = useAttrs();
</script>

slot

html
<div class="container">
  <header>
    <slot name="header"></slot>
  </header>
  <main>
    <slot></slot>
  </main>
  <footer>
    <slot name="footer"></slot>
  </footer>
</div>
html
<template v-slot:header>
  <!-- header 插槽的内容放这里 -->
</template>

<!-- 简写 -->
<template #header></template>

父组件 想要 子组件的数据:

html
<MyComponent v-slot="slotProps">
  {{ slotProps.text }} {{ slotProps.count }}
</MyComponent>

<MyComponent v-slot="{ text, count }"> {{ text }} {{ count }} </MyComponent>

<!-- 具名slot -->
<MyComponent>
  <template #header="headerProps"> {{ headerProps }} </template>
</MyComponent>
html
<slot :text="greetingMessage" :count="1"></slot>

需要注意 name 是 vue 特殊的 attribute

provide / inject

vue
<script setup>
import { provide, inject ,readonly} from "vue";

provide(/* 注入名 */ "message", /* 值 */ "hello!");
provide('read-only-count', readonly(count)) // readonly 可以确保值不会被修改

const message = inject("message", "这是默认值");
</script>

provide 值可以是 ref

但是不建议直接修改 provide,而是通过函数闭包实现。

v2 形式
ts
export default {
  // 可以返回函数,如同 data 一样
  provide: {
    message: "hello!",
  },
};
ts
export default {
  inject: ["message"],
  inject: {
    // 本地别名
    ocalMessage: {
      from: "message",
    },
  },
};

setup

组合式函数 https://cn.vuejs.org/guide/reusability/composables.html

setup() https://cn.vuejs.org/api/composition-api-setup.html

script setup https://cn.vuejs.org/api/sfc-script-setup.html

js
export default {
  // 第二是 context
  setup(props, { attrs, slots, emit, expose }) {},
};

深入响应性原理:理解 Vue 响应性系统的底层细节。
状态管理:多个组件间共享状态的管理模式。
测试组合式函数:组合式函数的单元测试技巧。
VueUse:一个日益增长的 Vue 组合式函数集合。源代码本身就是一份不错的学习资料。

toValue

3.3+

js
toValue(1); //       --> 1
toValue(ref(1)); //  --> 1
toValue(() => 1); // --> 1

todo 自定义指令

JSX 函数组件

https://cn.vuejs.org/guide/extras/render-function.html#render-function-recipes

在 jsx 中,事件要用 onXxxx

import type { SetupContext } from 'vue'
type FComponentProps = {
  message: string
}

type Events = {
  sendMessage(message: string): void
}

function FComponent(
  props: FComponentProps,
  context: SetupContext<Events>
) {
  return (
    <button onClick={() => context.emit('sendMessage', props.message)}>
        {props.message} {' '}
    </button>
  )
}

FComponent.props = {
  message: {
    type: String,
    required: true
  }
}

FComponent.emits = {
  sendMessage: (value: unknown) => typeof value === 'string'
}

vue vite less 全局变量

js
  css: {
    preprocessorOptions: {
      less: {
        modifyVars: {
          hack: `true; @import (reference) "${path.resolve('src/assets/global.less')}";`
        },
        javascriptEnabled: true
      }
    }
  }

path.resolve 是 node 的 api

path.resolve 的 参数是全局 less 文件的路径

部署

vite + nginx

https://blog.csdn.net/qq_43519131/article/details/127408209

config 中获取环境

js
export default ({ mode }: ConfigEnv): UserConfig => {
  // 获取 .env 环境配置文件
  const env = loadEnv(mode, process.cwd());
  return {
    base: env.VITE_BASE_PATH,
  };
};
server {
    listen 80;
    listen [::]:80;

    server_name show.q123q.cc;

    location /at {
        alias /myopt/show/at/dist;
        index index.html;
        try_files $uri $uri/ /at/index.html;
    }

    location /api {
       proxy_pass http://172.16.20.30:9905/;
    }

    location / {
        root $my_path/html;
        index /show.html;
    }
}

体积优化

分析工具

sh
npp add rollup-plugin-visualizer -D
ts
// https://vitejs.dev/config/
export default defineConfig({
  plugins: [
    visualizer({
      gzipSize: true,
      brotliSize: true,
      emitFile: false,
      filename: "test.html", //分析图生成的文件名
      open: true, //如果存在本地服务端口,将在打包后自动展示
    }),
  ],
});