vue3 语法糖<script setup>

news2024/11/19 2:33:52

在 Vue 3 中,<script setup>是一种新的语法糖,它极大地简化了组件的编写方式。

<script setup> 是在单文件组件 (SFC) 中使用组合式 API 的编译时语法糖。当同时使用 SFC 与组合式 API 时该语法是默认推荐。

基本概念

  • 简洁的语法<script setup>允许在<script>标签中直接使用组合式 API(Composition API),无需显式地返回一个对象(不需要使用return语句显示的暴露数据、方法)。
  • 自动注册:在<script setup>中定义的变量、函数和导入的组件会自动在模板中可用,无需手动注册。
  • 响应式声明:可以直接使用refreactive等函数来创建响应式数据,无需在setup函数中进行额外的处理。

基本语法

要启用该语法,需要在 <script> 代码块上添加 setup 属性:

<script setup>
  console.log('hello script setup')
</script>

里面的代码会被编译成组件 setup() 函数的内容。

  • 普通的 <script> 只在组件被首次引入的时候执行一次
  • <script setup> 中的代码会在每次组件实例被创建的时候执行

定义在顶层的变量和函数会被暴露给模板

当使用 <script setup> 时,任何在 <script setup> 声明的顶层的绑定 (包括变量,函数声明,以及 import 导入的内容) 都能在模板中直接使用:

<template>
  <div>{{ count }}</div>
  <button @click="increment">点击count+1</button>
</template>

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

const count = ref(10);
const increment = () => {
  count.value++;
};
</script>

在这个例子中,定义了一个响应式变量count和一个函数increment,它们可以直接在模板中使用。
不需要使用return显示的暴露。

import 导入的内容也会被暴露给模板

可以直接导入其他组件,并在模板中使用它们。导入的的组件会自动注册,不需要在components选项中进行显式注册。

<template>
  <div>
    <Child ref="cihldRef" />
  </div>
</template>

<script setup lang="ts">
import Child from './Child.vue';
</script>

在这个例子中,导入了一个名为Child的组件,并在模板中直接使用它。
<script setup> 范围里的值也能被直接作为自定义组件的标签名使用。
这里 Child 应当被理解为像是在引用一个变量。

可以在模板表达式中直接使用导入的 helper 函数,而不需要通过 methods 选项来暴露它:

<template>
  <div>{{ capitalize('hello') }}</div>
</template>
<script setup>
import { capitalize } from './helpers'
</script>

使用动态组件

动态组件是指在运行时根据条件动态地切换不同的组件进行渲染。
在 Vue 中,可以使用<component>标签结合:is属性来实现动态组件。

由于组件是通过变量引用而不是基于字符串组件名注册的,在 <script setup> 中要使用动态组件的时候,应该使用动态的 :is 来绑定:

<template>
  <component :is="Foo" />
  <component :is="someCondition ? Foo : Bar" />
</template>
<script setup>
import Foo from './Foo.vue'
import Bar from './Bar.vue'
</script>

可以使用响应式变量来控制动态组件的切换:

<template>
  <component :is="currentComponent" />
  <button @click="toggleComponent">切换组件</button>
</template>
<script setup>
import { ref } from 'vue'
import Foo from './Foo.vue'
import Bar from './Bar.vue'

const currentComponent = ref(ComponentA);
const toggleComponent = () => {
  currentComponent.value =
    currentComponent.value === Bar ? Foo : Bar;
};
</script>

可以为导入的组件添加别名:

import { Recur as RecursiveComponent } from './components'

使用递归组件

递归组件是指一个组件在其自身的模板中调用自身的组件。
在 Vue 3 中使用递归组件,在组件的模板(template)中直接调用自身,即可实现递归渲染。
例如:名为 RecursiveComponent.vue 的组件可以在其模板中用 <RecursiveComponent /> 引用它自己。

<template>
  <div>
    <!-- 这里是组件的当前层级内容 -->
    <div v-for="item in data" :key="item.id">
      {{ item.name }}
      <RecursiveComponent v-if="item.children" :data="item.children" />
    </div>
  </div>
</template>

在这个模板中,当 当前层级的数据存在子节点(item.children)时,就递归地调用自身(<RecursiveComponent />)来渲染子节点。

注意:name 属性的重要性

  • 唯一标识:递归组件必须要有 name 属性。
    • 因为 name 属性为组件提供了一个唯一的标识。在递归调用中,Vue 需要通过这个唯一标识来正确地识别和处理组件。
  • 错误提示和调试
    • 如果没有 name 属性,Vue 在运行时可能会抛出错误,难以确定是哪个组件出现了问题。

在设计递归组件时,一定要确保有明确的终止条件,以避免无限递归导致栈溢出等问题。

使用命名空间组件

在大型 Vue 3 项目中,命名空间组件可以帮助更好地组织和管理组件。
可以使用<Foo.Bar>这样的带 . 的组件标签来引用嵌套在对象属性中的组件。
这里的Foo是一个包含Bar组件的对象或者模块。

例如,有一个名为MyNamespace的对象,其中包含一个名为NestedComponent的组件,可以在模板中这样引用:<MyNamespace.NestedComponent />

// MyNamespace.js
import NestedComponent from './NestedComponent.vue';

export default {
  NestedComponent,
};

在组件中使用:

<template>
  <div>
    <MyNamespace.NestedComponent />
  </div>
</template>

<script setup>
import MyNamespace from './MyNamespace';
</script>

对于具有相似功能但来自不同模块的组件,可以通过命名空间进行区分,避免名称冲突。

使用自定义指令

自定义指令是一种在 Vue 中扩展 HTML 元素行为的方式。可以通过自定义指令来实现对 DOM 元素的操作,例如添加事件监听器、修改样式等。
全局注册的自定义指令将正常工作。
本地的自定义指令在 <script setup> 中不需要显式注册,但必须遵循 vNameOfDirective 这样的命名规范:

<template>
  <h1 v-my-directive>This is a Heading</h1>
</template>
<script setup>
const vMyDirective = {
  beforeMount: (el) => {
    // 在元素上做些操作
    el.style.backgroundColor = 'lightblue';
  }
}
</script>

在这个例子中:

  • <script setup> 中,定义了一个名为 vMyDirective 的常量,它实际上是一个对象,代表自定义指令的定义。
  • 对象vMyDirective包含一个 beforeMount 钩子函数,该函数会在指令所绑定的元素挂载到 DOM 之前被调用。
  • beforeMount 函数中,可以接收一个参数 el,它代表被绑定指令的 DOM 元素。在这里可以对这个元素进行各种操作,比如添加事件监听器、修改样式、设置属性等。

defineProps()defineEmits()

在 Vue 3 的 <script setup> 中,defineProps()defineEmits() 是用于定义组件的 propsemits 的函数。

  • defineProps() 用于定义组件接收的外部传入的属性(props)。它可以明确组件的输入参数。
  • defineEmits() 用于定义组件可以触发的自定义事件(emits)。它允许组件向父组件传递数据或通知父组件发生了某些事件。

示例:

<template>
  <div>{{ message }}</div>
  <button @click="emitEvent">触发事件</button>
</template>

<script setup>
// 调用 `defineProps()`,并传入一个对象来定义 `props` 的类型和默认值
const props = defineProps({
  message: {
    type: String,
    default: 'Hello, Vue 3!',
  },
});

// 调用 `defineEmits()`,并传入一个数组来定义可以触发的事件名称
const emit = defineEmits(['customEvent']);

const emitEvent = () => {
  emit('customEvent', 'Some data');
};
</script>

在这个例子中:

  • 定义了一个名为 messageprop,类型为字符串,默认值为 'Hello, Vue 3!'。在模板中可以直接使用 message 变量来显示传入的 prop 值。
  • 定义了一个名为 customEvent 的自定义事件。当按钮被点击时,调用 emitEvent 方法,触发 customEvent 事件并传递一些数据。

注意

  • definePropsdefineEmits 都是只能在 <script setup> 中使用的编译器宏。它们不需要导入,且会随着 <script setup> 的处理过程一同被编译掉。

    • 在 Vue 3 的 <script setup> 中,definePropsdefineEmits 被称为编译器宏。它们是一种在编译阶段由编译器处理的特殊语法结构,用于特定的目的,在这个场景下,分别用于定义组件的 propsemits
  • defineProps 接收与 props 选项相同的值。

    • 可以使用对象的形式来定义 props 的类型、默认值等属性,就像在传统的组件选项中一样。
    • 例如:defineProps({ propName: String, propWithDefault: { type: Number, default: 0 } })
  • defineEmits 接收与 emits 选项相同的值。

    • defineEmits 接收与传统的 emits 选项相同的值,通常是一个数组,列出组件可以触发的自定义事件名称。
    • 例如:defineEmits(['eventName1', 'eventName2'])
  • definePropsdefineEmits 在选项传入后,会提供恰当的类型推导。

    • 例如,如果定义了一个 propNameprop 为字符串类型,在使用这个 prop 时,编辑器可以自动识别其类型为字符串,并提供相应的类型提示。
  • 传入到 definePropsdefineEmits 的选项会从 setup 中提升到模块的作用域。因此,传入的选项不能引用在 setup 作用域中声明的局部变量。这样做会引起编译错误。但是,它可以引用导入的绑定,因为它们也在模块作用域内。

<script setup>
const localVar = 'some value';
defineProps({ propName: localVar }); // 这会导致编译错误,因为 localVar 是 setup 作用域的局部变量

import { importedValue } from './someModule';
defineProps({ propName: importedValue }); // 这是合法的,因为 importedValue 在模块作用域内
</script>

针对类型的 props/emit 声明

propsemit 也可以通过给 definePropsdefineEmits 传递纯类型参数的方式来声明:

const props = defineProps<{
  foo: string
  bar?: number
}>()

const emit = defineEmits<{
  (e: 'change', id: number): void
  (e: 'update', value: string): void
}>()

// 3.3+:另一种更简洁的语法
const emit = defineEmits<{
  change: [id: number] // 具名元组语法
  update: [value: string]
}>()
  • definePropsdefineEmits 要么使用运行时声明,要么使用类型声明。同时使用两种声明方式会导致编译报错。

  • 使用类型声明的时候,静态分析会自动生成等效的运行时声明,从而在避免双重声明的前提下确保正确的运行时行为。

    • 在开发模式下,编译器会试着从类型来推导对应的运行时验证。例如这里从 foo: string 类型中推断出 foo: String。如果类型是对导入类型的引用,这里的推导结果会是 foo: null (与 any 类型相等),因为编译器没有外部文件的信息。

    • 在生产模式下,编译器会生成数组格式的声明来减少打包体积 (这里的 props 会被编译成 ['foo', 'bar'])。

  • 在 3.2 及以下版本中,defineProps() 的泛型类型参数只能使用类型字面量或者本地接口的引用。

  • 这个限制已经在 3.3 版本中解决。最新版本的 Vue 支持在类型参数的位置引用导入的和有限的复杂类型。

使用类型声明时的默认 props 值

在使用针对类型的 defineProps 声明时,它没有可以给 props 提供默认值的方式。
当需要为 props 提供一些初始值或者在没有外部传入值时使用特定的默认值时,使用withDefaults 编译器宏。
withDefaults 编译器宏允许在使用类型声明的同时为 props 设置默认值。

<script setup>
import { withDefaults } from 'vue';

const props = withDefaults(defineProps({
  message: String,
  count: Number,
}), {
  message: 'Hello, Vue 3!',
  count: 0,
});
</script>

也可以换一种写法:

export interface Props {
  msg?: string
  labels?: string[]
}

const props = withDefaults(defineProps<Props>(), {
  msg: 'hello',
  labels: () => ['one', 'two']
})

上面代码会被编译为等价的运行时 propsdefault 选项。此外,withDefaults 辅助函数提供了对默认值的类型检查,并确保返回的 props 的类型删除了已声明默认值的属性的可选标志。

defineModel()

这个宏可以用来声明一个双向绑定 prop,通过父组件的 v-model 来使用。

defineModel 允许在组件中轻松创建双向绑定的变量。这意味着当父组件传递一个值给子组件,并且子组件可以修改这个值时,父组件也会自动更新这个值。

在子组件的 <script setup> 中,可以使用 defineModel 来定义一个双向绑定的变量。

<template>
  <input v-model="modelValue" />
</template>

<script setup>
import { defineModel } from 'vue';

const modelValue = defineModel();
</script>

modelValue 是一个双向绑定的变量,可以在输入框中使用 v-model 指令进行绑定。

在父组件中,可以将一个值传递给子组件,并使用 v-model 指令来实现双向绑定。

<template>
  <div>
    <Child ref="cihldRef" v-model="parentValue" />
  </div>
</template>

<script setup lang="ts" name="Person">
import { ref } from "vue";
import Child from './Child.vue';
const parentValue = ref('Initial value')
</script>

parentValue 是一个响应式变量,通过 v-model 指令传递给子组件 ChildComponent。当子组件中的输入框的值发生变化时,parentValue 也会自动更新。
在这里插入图片描述
使用 defineModel 可以使双向绑定的实现更加简洁和直观,无需手动处理 input 事件和 update:propName 事件。

如果为 defineModel prop 设置了一个 default 值且父组件没有为该 prop 提供任何值,会导致父组件与子组件之间不同步。
在子组件中:

<script setup lang="ts">
import { defineModel } from 'vue';
const modelValue = defineModel({default: 'value'}); // 设置一个默认值
</script>

在父组件中:

<script setup lang="ts" name="Person">
import { ref } from "vue";
import Child from './Child.vue';
const parentValue = ref()   // parentValue 是undefined
</script>

初始化后,parentValuemodelValue 不同步:
在这里插入图片描述
在这里插入图片描述
当子组件中的输入框的值发生变化时,parentValue 也会自动更新。
在这里插入图片描述

解构defineModel()返回值

defineModel()函数在 Vue 3 的 <script setup>中用于处理v-model双向绑定。它返回一个包含两个元素的数组:

  • 第一个元素是双向绑定的值,通常用于在组件内部进行操作和展示。
  • 第二个元素是一个对象,包含了使用v-model指令时可能设置的修饰符。

通过解构赋值的方式,可以方便地将这两个返回值分别提取到独立的变量中。
例如:const [modelValue, modelModifiers] = defineModel()
这样,modelValue就代表了双向绑定的值,而modelModifiers则是包含修饰符的对象。

在代码中,可以通过检查modelModifiers对象的属性来确定是否存在特定的修饰符。
例如,if (modelModifiers.trim) { //... }这段代码就是在检测是否存在trim修饰符。如果存在,就可以执行相应的逻辑。

const [modelValue, modelModifiers] = defineModel()

// 对应 v-model.trim
if (modelModifiers.trim) {
  // ...
}

当存在修饰符时,需要在读取或将其同步回父组件时对其值进行转换。可以通过使用 getset 转换器选项来实现:

const [modelValue, modelModifiers] = defineModel({
  get() {
    // 在这里可以对读取的值进行转换或处理
    return modelValue + ' (processed on get)';
  },
  set(value) {
    // 对设置的值进行处理,如果有修饰符可以在这里应用
    // 如果使用了 .trim 修饰符,则返回裁剪过后的值
    if (modelModifiers.trim) {
      return value.trim()
    }
    if (modelModifiers.uppercase) {
      return value.toUpperCase();
    }
    // 否则,原样返回
    return value
  }
})

在这个例子中:

  • get 方法在读取 modelValue 时被调用。get 方法可以用于在读取双向绑定的值时进行特定的处理或转换。
  • set 方法用于在设置双向绑定的值时进行特定的处理或转换。
    • set 方法接收一个参数 value,代表要设置的值。根据不同的修饰符情况对这个值进行处理。
    • 如果存在 trim 修饰符,就对值进行去空格处理。
    • 如果存在 uppercase 修饰符,就将值转换为大写字母。
    • 如果没有任何修饰符,直接返回传入的值。

在 TypeScript 环境下,defineModel可以接收一个类型参数来明确指定双向绑定的值的类型。

// 表示双向绑定的值为字符串类型。
// modelValue 被推断为 Ref<string | undefined>,响应式应用,可能包含字符串值或者为undefined。
const modelValue = defineModel<string>()

// 如果不想modelValue 为undefined,设置required: true
// modelValue 被推断为 Ref<string>
const modelValue = defineModel<string>({ required: true })

// 可以同时指定第二个类型参数来明确修饰符的类型
// modelValue 被推断为 Ref<string | undefined>
// 修饰符被指定为只能是"trim"或者"uppercase"这两种字符串字面量类型之一。
// modifiers 被推断为 Record<'trim' | 'uppercase', true | undefined>
// 表示modifiers是一个对象,键为指定的修饰符类型,值为true或undefined,表示该修饰符是否被应用。
const [modelValue, modifiers] = defineModel<string, "trim" | "uppercase">()

defineExpose()

在 Vue 3 的 <script setup> 中,defineExpose 是一个用于明确指定组件实例对外暴露哪些属性和方法的函数。
使用 <script setup> 的组件是默认关闭的——即通过模板引用或者 $parent 链获取到的组件的公开实例,不会暴露任何在 <script setup> 中声明的绑定。
defineExpose 允许开发者精确地控制哪些属性和方法可以被父组件通过模板引用访问到。

在子组件的 <script setup> 中,可以调用 defineExpose 并传入一个对象,该对象包含要暴露的属性和方法。

<template>
  <div>
    <div>count: {{ count }}</div>
    <button @click="addCount">点击 count+1</button>
  </div>
</template>
<script setup lang="ts">
import { ref } from 'vue';

let count = ref(0);

const addCount = () => {
  count.value++;
};

// 把属性count、方法addCount暴露给父组件
defineExpose({
  count,
  addCount
});
</script>

在这个例子中,子组件定义了一个内部的响应式数据 count和一个方法 addCount,然后通过 defineExpose 将它们暴露出去。

在父组件中,可以通过模板引用获取子组件的实例,并访问通过 defineExpose 暴露出来的属性和方法。

<template>
 <ChildComponent ref="childRef" />
  <button @click="accessChildComponent">Access child component</button>
</template>

<script setup>
import { ref } from 'vue';
import ChildComponent from './ChildComponent.vue';

const childRef = ref(null);

const accessChildComponent = () => {
  if (childRef.value) {
    console.log(childRef.value.count);
    childRef.value.addCount();
  }
};
</script>

在这个例子中,父组件通过模板引用 childRef 获取子组件的实例,并在按钮的点击事件中访问子组件暴露出来的 count 和调用 addCount

defineOptions()

defineOptions 是一个用于定义组件选项的函数。
这个宏可以用来直接在 <script setup> 中声明组件选项,而不必使用单独的 <script> 块:

<script setup>
defineOptions({
  inheritAttrs: false,
  customOptions: {
    /* ... */
  }
})
</script>

这是一个宏定义,选项将会被提升到模块作用域中,无法访问 <script setup> 中不是字面常数的局部变量。

可以用来直接在 <script setup> 中声明组件选项,比如 nameinheritAttrs 等。

使用 defineOptions 来明确指定组件的名称:

<script setup>
import { defineOptions } from 'vue';

defineOptions({
  name: 'MyComponent',
});
</script>

在这个例子中,明确指定了组件的名称为 MyComponent

inheritAttrs 选项决定了组件是否继承未被识别的属性并将其应用到根元素上。默认情况下,组件会继承这些属性。
使用 defineOptions 设置 inheritAttrs: false 时,组件不会继承未被识别的属性:

<script setup>
import { defineOptions } from 'vue';

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

在这个例子中,设置 inheritAttrsfalse,表示组件不继承未被识别的属性。

使用defineOptions 设置emits属性(替代defineEmits),定义组件可以触发的自定义事件:

<script setup>
import { defineOptions } from 'vue';

defineOptions({
  emits: ['customEvent1', 'customEvent2'],
});
</script>

使用defineOptions 设置props属性(替代defineEmits),定义组件接收的外部传入的属性:

<script setup>
import { defineOptions } from 'vue';

defineOptions({
  props: {
    propName1: String,
    propName2: {
      type: Number,
      default: 0,
    },
  },
});
</script>

可以用来对组件的 setup 函数进行一些额外的配置:

<script setup>
import { defineOptions } from 'vue';

defineOptions({
  setup() {
    // 一些特殊的 setup 配置逻辑
    return {
      // 返回一些特定的值或对象
    };
  },
});
</script>

虽然可以使用 defineOptions 来配置这些属性,但在很多情况下,使用专门的函数如 definePropsdefineEmits 等可能会更加简洁和直观。

defineSlots()

  • defineSlots 是一个用于定义组件插槽的函数。
  • defineSlots 允许开发者在 <script setup> 语法中明确地定义组件的插槽。
  • defineSlots() 只接受类型参数,没有运行时参数。
    • 类型参数应该是一个类型字面量,其中属性键是插槽名称,值类型是插槽函数。
    • 函数的第一个参数是插槽期望接收的 props,其类型将用于模板中的插槽 props。返回类型目前被忽略,可以是 any
  • 返回 slots 对象,该对象等同于在 setup 上下文中暴露或由 useSlots() 返回的 slots 对象。
<script setup lang="ts">
const slots = defineSlots<{
  default(props: { msg: string }): any
}>()
</script>

可以使用 defineSlots 来定义一个名为 default 的插槽:

<script setup>
import { defineSlots } from 'vue';

const slots = defineSlots({
  default: () => null,
});
</script>

在这个例子中,定义了一个默认插槽,其函数返回值为 null,表示插槽的默认内容为空。
在模板中,可以使用 <slot> 标签来渲染插槽内容:

<template>
  <div>
    <slot />
  </div>
</template>

useSlots()useAttrs()

<script setup> 使用 slotsattrs 的情况应该是相对来说较为罕见的,因为可以在模板中直接通过 $slots$attrs 来访问它们。在需要使用它们的罕见场景中,可以分别用 useSlotsuseAttrs 两个辅助函数:

  • useSlots 函数用于访问组件的插槽内容。它返回一个对象,其中包含了组件所定义的各个插槽的内容。
    • 通过 useSlots,可以在组件的逻辑部分动态地处理插槽内容,根据不同的条件渲染不同的插槽内容,或者对插槽内容进行进一步的加工和处理。
<script setup>
import { useSlots } from 'vue';

const slots = useSlots();
console.log(slots.default());
</script>

在这个例子中,useSlots 返回的对象被赋值给 slots。然后,可以通过 slots.default() 来访问默认插槽的内容。如果组件有多个插槽,可以通过相应的属性名来访问,比如 slots.slotName

  • useAttrs 函数用于访问组件上未被识别的属性(即没有被组件的 props 定义的属性)。它返回一个包含这些属性的对象。
<script setup>
import { useAttrs } from 'vue';

const attrs = useAttrs();
console.log(attrs.class);
</script>

在这个例子中,useAttrs 返回的对象被赋值给 attrs。可以通过 attrs 对象访问组件上的属性,比如 attrs.class 访问 class 属性。

与普通的 <script> 一起使用

<script setup> 可以和普通的 <script> 一起使用。普通的 <script> 在有这些需要的情况下或许会被使用到:

  • 声明无法在 <script setup> 中声明的选项,例如 inheritAttrs 或插件的自定义选项 (在 3.3+ 中可以通过 defineOptions 替代)。
  • 声明模块的具名导出 (named exports)。
  • 运行只需要在模块作用域执行一次的副作用,或是创建单例对象。
<script>
// 普通 <script>,在模块作用域下执行 (仅一次)
runSideEffectOnce()

// 声明额外的选项
export default {
  inheritAttrs: false,
  customOptions: {}
}
</script>

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

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

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

相关文章

使用Qg波形快速提取模型参数的新方法以准确捕获SiC MOSFET在不同负载条件下的开关特性

来源&#xff1a;Novel Methodology for Fast Model Parameter Extracting Using Qg Waveforms to Accurately Capture Switching Characteristics of SiC MOSFET Under Various Load Conditions&#xff08;ISPSD 24年&#xff09; 摘要 本文提出了一种快速提取模型参数的方…

类和对象(高级)

类和对象&#xff08;高级&#xff09; 一、运算符重载 运算符重载是对已有的运算符 指定新功能。不能创建新运算。 运算符重载关键字operator 思路&#xff1a; 1、弄懂运算符的运算对象的个数。&#xff08;个数决定了 重载函数的参数个数&#xff09; 2、识别运算符左边的…

【css】伪元素实现跟随鼠标移动的渐变效果

主要功能是在按钮上实现鼠标跟随渐变效果。每当用户将鼠标移动到按钮上时&#xff0c;按钮会显示一个以鼠标位置为中心的渐变效果。 1. 核心部分: 监听鼠标在元素内移动 监听鼠标在元素内移动&#xff0c;并触发该事件。 const handleMouseMove (e: MouseEvent) > {if (…

C#知识|语法拾遗:数据类型转换

哈喽&#xff0c;你好啊&#xff0c;我是雷工&#xff01; 其实关于数据转换在任何语言中都会涉及&#xff0c;无论是PLC编程语言&#xff0c;还是SCADA开发中的脚本语言&#xff0c;都会涉及&#xff0c;在前边学习JavaScript的内容时&#xff0c;也看过相关内容&#xff1a; …

[RAG]喂饭教程!Neo4J可视化GraphRAG索引

GraphRAG通过结合知识图谱&#xff0c;增加RAG的全局检索能力。今天我将讲解如何使用Neo4J可视化GraphRAG索引的结果&#xff0c;以便进一步的处理、分析&#xff0c;以小说提取的实体《仙逆》为例&#xff0c;一图胜千言。本文分为4小节&#xff0c;安装neo4j、导入GraphRAG索…

如何做服务端渲染?

node server 接收客户端请求&#xff0c;得到当前的请求url 路径&#xff0c;然后在已有的路由表内查找到对应的组件&#xff0c;拿到需要请求的数据&#xff0c;将数据作为 props、context或者store 形式传入组件 然后基于 react 内置的服务端渲染方法 renderToString()把组件…

vue一键打不同环境的包

1.配置package.json 主要看的是 "build:all": "vue-cli-service build && vue-cli-service build --mode test && vue-cli-service build --mode development", "scripts": {"dev": "vue-cli-service serve"…

【SpringBoot源码】SpringBoot监听机制分析

目录 一、简介 二、SpringBoot事件监听机制 1)加载ApplicationListener监听器实现类 2)获取运行监听器EventPublishingRunListener 3)发布事件 4)Spring事件发布multicastEvent() 一、简介 接下来我们分析下SpringBoot的事件监听机制的源码。 二、SpringBoot事件监…

Android系统安全 — 1-OpenSSL支持的常用加解密算法介绍

常用加解密算法介绍 1. 哈希算法 常见的函数包含MD系列、SHA-1、SHA-2家族、SHA-3家族、SM3等。 1.1 MD5&#xff08;单向散列算法&#xff09; 全称是Message-Digest Algorithm 5&#xff08;信息-摘要算法&#xff09;&#xff0c;经MD2、MD3和MD4发展而来。MD5算法的使用…

线索精细化管理实践:线上推广渠道线索管理的8个要点

在如今线索获取成本越来越高的情况下&#xff0c;如何获取增量线索、经营好存量线索、实现精细化、高效率线索管理对于企业来说至关重要。获取线索是一切行动的开始&#xff0c;与其建立起稳定、持续的信任关系&#xff0c;达成合作甚至引导复购&#xff0c;是整个线索管理链路…

泛微eteams OA对接金蝶云星空写入数据

需求&#xff1a; 公司需要先在OA上对准备生产的订单进行一次量产评审&#xff0c;所有相关人员评审通过后才可以进行生产&#xff0c;导致下工单的人员每次需要把OA上的信息复制到ERP进行审批。 为什么不直接在ERP上审批呢&#xff1f; 首先该节点涉及到很多不用ERP的用户&am…

盘点八月份最好用的五款报表制作工具,涵盖各功能,你都听说过吗?

一、报表制作软件的重要性 在现代企业运营中&#xff0c;数据的处理和分析是至关重要的。如何将复杂的数据信息以直观、易懂的方式展现出来&#xff0c;是提升决策效率和准确性的关键。因此报表制作软件成为企业必备的工具之一&#xff0c;它们通过图表化的方式&#xff0c;帮…

加速网络体验,Squid缓存代理:让浏览如飞,畅享无限网络速度!

作者简介&#xff1a;我是团团儿&#xff0c;是一名专注于云计算领域的专业创作者&#xff0c;感谢大家的关注 座右铭&#xff1a; 云端筑梦&#xff0c;数据为翼&#xff0c;探索无限可能&#xff0c;引领云计算新纪元 个人主页&#xff1a;团儿.-CSDN博客 目录 前言: squ…

低代码表单引擎的核心不仅仅是拖拉拽,深入解析表单的高级功能

作为一名专业的低代码产品经理&#xff0c;我们主要以 to B 的企业级系统为配置化对象&#xff0c;我深知在构建高效、用户友好的企业应用系统时&#xff0c;表单引擎扮演着核心基础的角色。当然拖拉拽快速创建页面是最简单直接的用户体验&#xff0c;然而&#xff0c;在享受拖…

Maven: 更新依赖索引清理maven仓库

文章目录 更新依赖索引清理maven仓库 更新依赖索引 有时候给 idea 配置完 maven 仓库信息后&#xff0c;在 idea 中依然搜索不到仓库中的 jar 包。这是因为仓库中的 jar 包索引尚未更新到 idea 中。这个时候我们就需要更新 idea 中 maven 的索引了&#xff0c;具体做法如下&am…

企业如何防止重要数据泄露?10个重要的小技巧!

在当今数字化时代&#xff0c;企业数据已成为其最宝贵的资产之一&#xff0c;但同时也面临着前所未有的泄露风险。数据泄露不仅可能导致财务损失&#xff0c;还可能损害企业声誉和客户信任。因此&#xff0c;采取有效措施防止重要数据泄露至关重要。以下是十个重要的小技巧&…

武威市旅游资源管理系统/旅游网站的设计与实现

摘要 经济快速发展带动下的旅游产业发展&#xff0c;在我国越来越被更多的人所追求。人们对获取旅游信息有很高的需求&#xff0c;在互联网发达的今天&#xff0c;制作一个旅游资源管理十分有必要。该设计根据基于jsp技术和MySQL数据库设计一个武威市旅游资源管理系统。系统的前…

自动化持续测试策略

目录 重新确定手动测试和自动化测试的关系 充分考虑自动化的可测性 尽量将自动化测试的粒度做细 策略实施的关键点 1.跨职能团队合作 2.持续学习 3.自动化测试的可测性 4.测试优化 在持续测试中&#xff0c;我们希望将每个测试分层上的测试都用自动化的方式来进行&…

C语言-内存管理

内存区间 在C语言中&#xff0c;内存被划分为以下几个区间&#xff1a; 栈&#xff08;stack&#xff09;&#xff1a;用于存储局部变量和函数的参数。栈是由编译器自动分配和释放的&#xff0c;栈的大小通常是固定的。 堆&#xff08;heap&#xff09;&#xff1a;用于存储动…

【Qt】输入类控件QComboBox

目录 输入类控件QComboBox 例子&#xff1a;使用下拉框模拟点餐 例子&#xff1a;从文件中加载下拉框的选项 输入类控件QComboBox QComboBox表示下拉框 核心属性 属性说明 currentText 当前选中的⽂本 currentIndex 当前选中的条⽬下标. 从 0 开始计算. 如果当前没有条…