vue3.2-setup语法糖、组合式API、状态库Pinia归纳总结

本文详细介绍了Vue3.x的项目创建、页面组件结构、属性方法、定义方法、计算属性、父子组件通信、原型链绑定、mitt.js使用、v-model双向绑定、nextTick、插槽、路由、路由守卫、生命周期、Pinia状态管理等核心概念和实践技巧,涵盖了从基础到高级的完整流程。

创建项目:

vite脚手架创建项目: vue3+vite2+ts

npm create vite@latest 

一.页面组件结构

<template>
    home
</template>
​
<!-- 在script标签上添加setup属性 -->
<script setup lang="ts">
​
</script>
​
<style scoped>
</style> 

二. 页面属性方法

<template>
  <h1>{{ name }}</h1>
  <h1>{{ state.age }}</h1>
  <h1>{{ sex }}</h1>
</template>
     
<script setup lang="ts"> import { reactive, ref, toRefs } from "vue";
// ref声明响应式数据,用于声明基本数据类型
const name = ref("王五");
// 修改 name 值要是用.value
name.value = "张三";
​
// reactive声明响应式数据,用于声明引用数据类型
const state = reactive({
  age: 18,
  sex: "男",
});
// 修改 state.age 值
state.age = 24;
​
// 使用toRefs解构template可直接使用{{name}}、{{sex}}
const { age, sex } = toRefs(state); </script>
​
<style scoped>
​
</style> 

三.定义method

<template>
  <h1>{{ age }}</h1>
  <!-- 调用方法 -->
  <button @click="handleClick"></button>
</template>
     
<script setup lang="ts"> import { reactive,toRefs } from "vue";
​
// reactive声明响应式数据,用于声明引用数据类型
const state = reactive({
  age: 18,
  sex: "男",
});
​
// 使用toRefs解构template可直接使用{{name}}、{{sex}}
const { age, sex } = toRefs(state);
​
// 声明点击事件
const handleClick = () => { 
  state.age++;
}
​ </script>
​
<style scoped>
​
</style> 

四.computed (计算属性)

<template>
  <h1>{{ count }}</h1>
  <h1>{{doubleCount}}</h1>
  <button @click="handleClick()">{{count}}</button>
</template>
​
<script setup lang="ts"> import { ref, computed } from 'vue'
​
// ref声明响应式数据,用于声明基本数据类型
const count = ref(11)
​
//computed 获取双倍 count 值 
const doubleCount = computed(() => {
  return count.value * 2
})
​
const handleClick = () => {
  count.value++
} </script>
   
<style scoped>
​
</style> 

五.父传子

parent.vue

<template>
  <Child :msg="fmsg"></Child>
</template>
​
<script setup lang="ts"> // 引入子组件(组件自动注册)
  import Child from './child.vue';
  const fmsg = '父组件传递的值' </script>
​
<style scoped>
​
</style>
​ 

child.vue

<template>{{props.msg}}
  <!-- 可省略props -->
  <h1>{{ msg }}</h1>
</template>
 
<script setup lang="ts"> // defineProps 和 defineEmits 都是只能在 <script setup> 中使用的编译器宏。他们不需要导入,且会随着 <script setup> 的处理过程一同被编译掉。
  
// 声明props
const props = defineProps({
  msg: {
    type: String,
    default: "",},
}); </script>
​
<style scoped>
​
</style>
​ 

六.子传父

parent.vue

<template>
  <Child :msg="state.msg" @changeMag="changeMag"></Child>
</template>
​
<script setup lang="ts"> import { reactive } from 'vue'
// 引入子组件(组件自动注册)
import Child from './child.vue';
​
const state = reactive({
  msg: '父组件原值'
})
​
const changeMag = (value: any) => {
  state.msg = value
} </script>
​
<style scoped>
​
</style>
​ 

child.vue

<template>{{props.msg}}<!-- 可省略props --><h1>{{ msg }}</h1><!-- 调用子传父事件 --><button @click="handleClick">Click Me</button>
</template>
 
<script setup lang="ts"> // defineProps 和 defineEmits 都是只能在 <script setup> 中使用的编译器宏。他们不需要导入,且会随着 <script setup> 的处理过程一同被编译掉。

// 声明props
const props = defineProps({msg: {type: String,default: "",},
});

// 声明 emit 
const emit = defineEmits(['changeMag'])

const handleClick = () => {emit('changeMag', '我是子组件传过来的值')
} </script>

<style scoped>

</style> 

七.原型链绑定和组件使用

main.ts

// 创建vue实例
const app = createApp(App);
app.mount("#app");
// 获取原型
const prototype = app.config.globalProperties;
// 绑定参数
prototype.$name = "我是挂载在全局上的属性"; 

组件内使用

<template><!-- 方式1:在template模板中使用 -->{{$name}}
</template>
<script setup lang="ts"> import { getCurrentInstance } from "vue";

// 方式2:在setup中使用
// const cns = getCurrentInstance()
// console.log(cns.appContext.config.globalProperties.$name)

// 方式3:在setup中使用
const { proxy } = getCurrentInstance() as any
console.log(proxy.$name) </script>

<style scoped>

</style> 

八.Vue3.x使用mitt.js进行组件通信

安装

npm install --save mitt 

官网地址

mitt - npm (npmjs.com)

九.v-model父子组件双向数据绑定

parent.vue

<template><div>父组件:</div><div>{{state.msg}}</div><input type="text" v-model="state.msg"><Child v-model:msg='state.msg' v-model:age="state.age" />
</template>

<script setup lang="ts"> import { reactive } from "vue";
// 引入子组件(组件自动注册)
import Child from "./child.vue";
const state = reactive({msg: "我是父组件原本的值",age: 11
}); </script>

<style scoped>

</style> 

child.vue

<template><div>子组件:</div><input type="text" v-model="msg" @input="changeMsg"><!-- 可省略props --><h1>msg:{{ msg }}</h1>
</template>

<script setup lang="ts"> // 声明props
const props = defineProps({msg: {type: String,default: "",},age: {type: Number,default: 0,},
});

// 声明emit
const emit = defineEmits(["update:msg", "update:age"]);

const changeMsg = () => { console.log(props.msg);emit('update:msg',props.msg);
} </script>

<style scoped>

</style> 

十.nextTick

parent.vue

<template><Child />
</template>

<script setup lang="ts"> import { nextTick } from "vue";
// 引入子组件(组件自动注册)
import Child from "./child.vue";

nextTick(() => {console.log('父组件调用了:nextTick');
})

nextTick(() => {console.log('父组件调用了:nextTick-1');
})

nextTick(() => {console.log('父组件调用了:nextTick-2');
}) </script>

<style scoped>

</style> 

child.vue

<template>
</template>

<script setup lang="ts"> import { nextTick } from "vue";

nextTick(() => {console.log('子组调用了:nextTick');
})

nextTick(() => {console.log('子组调用了:nextTick-1');
})

nextTick(() => {console.log('子组调用了:nextTick-2');
}) </script>

<style scoped>

</style> 

十一.插槽

parent.vue

<template><Child><!-- 匿名插槽 --><span>我是默认插槽</span><!-- 具名插槽 --><template #title><h1>我是具名插槽1</h1><h1>我是具名插槽2</h1><h1>我是具名插槽3</h1><span>1</span><span>2</span><span>3</span></template><!-- 作用域插槽 --><template #footer="{ scope }"><footer>作用域插槽——姓名:{{ scope.name }},年龄{{ scope.age }}</footer></template></Child>
</template>

<script setup lang="ts"> // 引入子组件(组件自动注册)
import Child from "./child.vue"; </script>

<style scoped>

</style> 

child.vue

<template><!-- 匿名插槽 --><slot /><!-- 具名插槽 --><slot name='title' /><!-- 作用域插槽 --><slot name="footer" :scope="state" />
</template>

<script setup lang="ts"> import { reactive, useSlots } from "vue";

const state = reactive({name: '王五',age: 11
});

const slots = useSlots()

//判断<slot/>是否有传值
const slotDefault = !!useSlots().default;
//判断<slot name="test"/>是否有传值
const slotTest = !!useSlots().test;

// 匿名插槽使用情况,判断 <slot/>是否有传值
const defaultSlot = reactive(slots.default && slots.default().length)
console.log('defaultSlot', defaultSlot) // 1

// 具名插槽使用情况,判断 <slot name='title' />是否有传值
const titleSlot = reactive(slots.title && slots.title().length)
console.log('titleSlot', titleSlot) // 6 </script>

<style scoped>

</style> 

十二.路由useRoute和useRouter

安装

npm install vue-router@4
// yarn add vue-router@4 

安装 | Vue Router (vuejs.org)

新建router/index.ts

import { createRouter, createWebHashHistory, RouteRecordRaw } from 'vue-router';
const routes: Array<RouteRecordRaw> = [{ path: '/',redirect: '/home'},{ path: '/home',name: 'home',component: () => import('../views/home/index.vue'),meta: {showFooter: true,requireAuth: false,}},{ path: '/about',name: 'about',component: () => import( '../views/about/index.vue'),meta: {showFooter: true,requireAuth: false,}},
];
 
const router = createRouter({history: createWebHashHistory(),routes,
});
 
export default router; 

main.ts

//在将路由router注册
import { createApp } from 'vue'
import App from './App.vue'
import router from './router/index'
 
const app=createApp(App)
app.use(router).mount('#app') 

页面打印

//在页面打印结果
 
import { useRouter, useRoute } from "vue-router";
 
// 必须先声明调用
const router = useRouter();
const route = useRoute();
 
// 路由信息
console.log("router", router);
console.log("route",route); 

十三.路由守卫

// 路由守卫
 
router.beforeEach((to, from, next) => {
 console.log("to",to);
 console.log("from",from);
 next()
}) 

十四.生命周期

vue2和vue3对比

  • beforeCreate -> 使用 setup()
  • created -> 使用 setup()
  • beforeMount -> onBeforeMount
  • mounted -> onMounted
  • beforeUpdate -> onBeforeUpdate
  • updated -> onUpdated
  • beforeUnmount -> onBeforeUnmount
  • unmounted -> onUnmounted
  • errorCaptured -> onErrorCaptured
  • renderTracked -> onRenderTracked
  • renderTriggered -> onRenderTriggered
  • activated -> onActivated
  • deactivated -> onDeactivated

十五.Pinia

1:基础使用

安装

npm install pinia -S 

main.ts 引入使用

import { createApp } from 'vue'
import App from './App.vue'
import router from './router/index.ts'
 
// 引入pinia
import { createPinia } from 'pinia'
 
// 创建vue实例
const app=createApp(App)
 
// 创建 Pinia 实例
const pinia = createPinia()
 
// 注册挂载到vue实列
app.use(router).use(pinia).mount('#app') 

创建 store/index.ts

import { defineStore } from "pinia";

export const useMainStore = defineStore("main", {state: () => {return {info: "hello, My Pinia",};},getters: {},actions: {},
}); 

组件内使用

<template><div> <h1>{{ mainStore.info}}</h1></div>
</template>
 
<script setup lang="ts"> import { useMainStore } from "../../store/index.ts";
const mainStore = useMainStore(); </script>
 
<style scoped>
 
</style> 

2:访问state 中的数据

/store/index.ts

import { defineStore } from "pinia";

export const useMainStore = defineStore("main", {state: () => {return {info: "Hello, My Pinia",id:11,count:0,depId:6,userName: "admin"};},getters: {},actions: {},
}); 

组件内使用

<template><h1>{{ mainStore.count }}</h1><h1>{{ mainStore.info }}</h1><hr /><h1>{{ count }}</h1><h1>{{ info }}</h1><p><button @click="refteshData">修改数据count</button></p><br><h1>count1:{{ count1 }}</h1><h1>info1:{{ info1 }}</h1>
</template>
 
<script lang="ts" setup> import { toRefs } from 'vue'
import { storeToRefs } from 'pinia'
import { useMainStore } from "../../store";
const mainStore = useMainStore();
// **** 注意:直接解构处出来的数据,非响应式的
// const { count: count1, info: info1 } = mainStore;

// 转为响应式方法
// 1:使用 toRefs 可以将一个响应式 reactive 对象的所有原始属性转换为响应式的 ref 属性
const { count: count1, info: info1 } = toRefs(mainStore);
// 2. 通过pinia中提供的storeToRefs方法来解决非响应式问题
const { count, info } = storeToRefs(mainStore);

const refteshData = () => {mainStore.count += 10
} </script>
 
<style scoped>

</style> 

2:修改state 中的数据

使用$patch修改数据

<template><h1>{{ mainStore.count }}</h1><h1>{{ mainStore.info }}</h1><hr /><h1>{{ count }}</h1><h1>{{ info }}</h1><p><button @click="refteshData">修改数据count</button></p><br><h1>count1:{{ count1 }}</h1><h1>info1:{{ info1 }}</h1>
</template>
 
<script lang="ts" setup> import { toRefs } from 'vue'
import { storeToRefs } from 'pinia'
import { useMainStore } from "../../store";
const mainStore = useMainStore();
// **** 注意:直接解构处出来的数据,非响应式的
// const { count: count1, info: info1 } = mainStore;

// 转为响应式方法
// 1:使用 toRefs 可以将一个响应式 reactive 对象的所有原始属性转换为响应式的 ref 属性
const { count: count1, info: info1 } = toRefs(mainStore);
// 2. 通过pinia中提供的storeToRefs方法来解决非响应式问题
const { count, info } = storeToRefs(mainStore);

const refteshData = () => {// 方式一: 不推荐// 解构后更改方式// count.value += 10// 结构前更改方式// mainStore.count += 10// 方式二:$patch方法// mainStore.$patch({// count: mainStore.count + 1,// info: "hello"// })// 方式三:通过$patch传递一个函数来实现,这里的state就是useMainStore容器中的state。mainStore.$patch(state => {state.count += 10state.info = "pinia批量更新" + state.count})
} </script>
 
<style scoped>

</style> 

使用actions中的方法修改数据 (推荐)

store/index.ts

import { defineStore } from "pinia";

export const useMainStore = defineStore("main", {state: () => {return {info: "Hello, My Pinia",id: 11,count: 0,depId: 6,userName: "admin",};},getters: {},// Actions 相当于组件中的 methods,用来修改 state 数据actions: {changeState() {this.count += 11;this.info = "actions修改数据";},changeStates(num: number) {this.count += num + 1;this.info = "actions修改数据";},},
}); 

页面使用

<template><h1>{{ mainStore.count }}</h1><h1>{{ mainStore.info }}</h1><hr /><h1>{{ count }}</h1><h1>{{ info }}</h1><p><button @click="refteshData">修改数据count</button></p><br><h1>count1:{{ count1 }}</h1><h1>info1:{{ info1 }}</h1>
</template>
 
<script lang="ts" setup> import { toRefs } from 'vue'
import { storeToRefs } from 'pinia'
import { useMainStore } from "../../store";
const mainStore = useMainStore();
// **** 注意:直接解构处出来的数据,非响应式的
// const { count: count1, info: info1 } = mainStore;

// 转为响应式方法
// 1:使用 toRefs 可以将一个响应式 reactive 对象的所有原始属性转换为响应式的 ref 属性
const { count: count1, info: info1 } = toRefs(mainStore);
// 2. 通过pinia中提供的storeToRefs方法来解决非响应式问题
const { count, info } = storeToRefs(mainStore);

const refteshData = () => {// 调用 actions 修改数据mainStore.changeState()mainStore.changeStates(10)
} </script>
 
<style scoped>

</style> 

3:getters 的使用

/store/index.ts

import { defineStore } from "pinia";

export const useMainStore = defineStore("main", {state: () => {return {info: "Hello, My Pinia",id: 11,count: 0,depId: 6,userName: "admin",};},// 类似于组件的computed,用来封装计算属性,具有缓存的功能getters: {// 函数接收一个可选参数:state状态对象count10(state) {return (state.count += 10);},// 若使用this.count,则必须指明返回数据的类型count11(): number {return (this.count += 11);},count12(state) {return (this.count += 12);},},// Actions 相当于组件中的 methods,用来修改 state 数据actions: {changeState() {this.count += 11;this.info = "actions修改数据";},changeStates(num: number) {this.count += num + 1;this.info = "actions修改数据";},},
}); 

页面使用

<template><h1>{{ mainStore.count }}</h1><p><button @click="getGetters">获取getters</button></p>
</template>
 
<script lang="ts" setup>
import { ref } from 'vue'
import { useMainStore } from "../../store";
const mainStore = useMainStore() as any;
const count_10 = ref('');
const count_11 = ref('');
const count_12 = ref('');

const getGetters = () => {count_10.value = mainStore.count10;count_11.value = mainStore.count11;count_12.value = mainStore.count12;
}
</script>
 
<style scoped>

</style> 

\

最后

整理了75个JS高频面试题,并给出了答案和解析,基本上可以保证你能应付面试官关于JS的提问。



有需要的小伙伴,可以点击下方卡片领取,无偿分享

<think>首先,用户的问题是关于Vue 3的:他们想将没有setup语法糖的代码转换为使用setup语法糖的写法。具体来说,他们询问“Vue3 setup语法糖 用法 转换指南”。 我需要根据系统级指令来构建我的回答: 1. **行内数学表达式**:用$...$格式。但在这个上下文中,用户的问题是关于编程的,没有数学表达式,所以我可能不需要使用它。除非有变量或方程,否则跳过。 2. **独立公式**:用$$...$$格式并单独成段。同样,不相关。 3. **LaTeX语法正确**:确保任何数学内容正确,但这里没有。 4. **使用中文回答**:整个回答必须用中文。 5. **生成相关问题**:在回答结束时,生成相关问题。 6. **引用标识**:在回答中引用的段落末尾自然地添加引用标识,如[^1]。用户提供了几个引用,我需要引用它们。 用户提供的引用是关于Vue 3的: - [^1]: 在Vue 3中,有2种不同的方法:选项API - this.$emit;组合API - context.emit;组合API - defineEmits() - [^2]: Vue模板语法,数据绑定 - [^3]: pinia的storeToRefs vs Vue的toRefs - [^4]: 一个关于Vue3 $emit用法的指南,包括选项API、组合APIsetup语法糖 用户的问题具体是关于将没有setup语法糖的代码转换为使用setup语法糖的写法。所以,我需要解释如何从传统组合API(使用setup()函数)转换为<script setup>语法糖。 关键点: -Vue 3中,<script setup>是一种编译时语法糖,用于更简洁地使用组合API- 它避免了显式的setup()函数,并自动处理一些东西。 转换指南: 1. **移除setup()函数**:在<script setup>中,不需要定义setup函数;整个script块就是setup上下文。 2. **定义props**:使用defineProps宏。 3. **定义emits**:使用defineEmits宏。 4. **定义响应式状态**:直接使用ref或reactive,不需要返回对象。 5. **生命周期钩子**:使用onMounted等函数。 6. **暴露组件属性**:使用defineExpose如果需要暴露给父组件。 从引用中: - [^4] 提到了setup语法糖:它展示了如何从setup()函数转换为<script setup>。 示例代码: 在引用[^4]中,有一个选项API和组合API的例子,但没有直接<script setup>的例子。用户说“引用[4]”是关于emit的指南,包括setup语法糖。 在引用[4]中:它显示了MyTextInput.vue使用setup()函数,但没有<script setup>版本。用户可能期望我基于此解释转换。 用户说:“我想将Vue3中没有setup语法糖的代码转换为使用setup语法糖的写法”,所以我需要提供一个转换指南。 结构我的回答: - 介绍setup语法糖- 逐步转换一个示例代码。 - 使用用户提供的引用作为支持。 回答结构: 1. **清晰介绍**:解释什么是<script setup>语法糖2. **转换步骤**:一步步展示如何转换代码。 3. **示例**:提供一个简单的例子。 4. **引用**:在相关部分添加引用标识。 5. **结束**:生成相关问题。 确保回答真实可靠:基于Vue 3官方文档和常见实践。 最终,生成相关问题。 用中文回答。 大纲: - 开头:解释setup语法糖的好处。 - 转换指南: - 步骤1: 移除setup函数,使用<script setup> - 步骤2: 使用defineProps和defineEmits - 步骤3: 定义响应式变量直接声明 - 步骤4: 生命周期钩子直接导入使用 - 示例:转换一个简单组件。 - 引用相关部分。 相关问题: 1. Vue3 setup语法糖有哪些限制? 2. 如何在setup语法糖中使用ref和reactive? 3. Vue3组合API与选项API的主要区别是什么? 现在,构建回答。</think>### Vue3 setup语法糖转换指南 在Vue 3中,`<script setup>`是一种编译时语法糖,它简化了组合API的使用,避免了显式定义`setup()`函数的需要,使代码更简洁且易于维护。它自动处理响应式状态、props、emits和生命周期钩子的声明[^1]。以下我将逐步解释如何将没有setup语法糖的代码(即使用传统组合API或选项API)转换为使用`<script setup>`的写法。转换过程基于Vue 3官方最佳实践,并参考了相关引用内容。 #### 步骤1: 理解基本转换规则 - **移除`setup()`函数**:在`<script setup>`中,整个script块被视为setup上下文,无需显式定义`setup()`函数。 - **使用宏定义props和emits**:用`defineProps`和`defineEmits`宏代替在`setup()`中声明props和emits。 - **直接声明响应式状态**:使用`ref`、`reactive`等函数直接声明变量,无需返回一个对象。 - **生命周期钩子**:导入如`onMounted`、`onUpdated`等函数直接使用。 - **暴露组件属性**:如果需要向父组件暴露属性,使用`defineExpose`宏。 - **模板绑定**:所有声明的变量和函数自动在模板中可用,无需通过`return`暴露[^2]。 #### 步骤2: 转换示例代码 假设我们有一个使用传统组合API(无语法糖)的Vue组件,它处理props、emits和响应式状态。我将基于引用[^4]提供的示例(一个自定义输入组件)进行转换。原始代码使用`setup()`函数: ```vue <!-- 原始代码:无setup语法糖 --> <script> import { ref } from &#39;vue&#39;; export default { props: { initialValue: String }, emits: [&#39;customChange&#39;], setup(props, { emit }) { const inputValue = ref(props.initialValue || &#39;&#39;); const handleChange = (event) => { inputValue.value = event.target.value; emit(&#39;customChange&#39;, event.target.value); }; return { inputValue, handleChange }; } }; </script> <template> <div> <label>Custom Input</label> <input type="text" :value="inputValue" @input="handleChange" /> </div> </template> ``` 转换为使用`<script setup>`的写法: ```vue <!-- 转换后代码:使用setup语法糖 --> <script setup> import { ref, defineProps, defineEmits } from &#39;vue&#39;; // 定义props和emits const props = defineProps({ initialValue: String }); const emit = defineEmits([&#39;customChange&#39;]); // 直接声明响应式状态和函数 const inputValue = ref(props.initialValue || &#39;&#39;); const handleChange = (event) => { inputValue.value = event.target.value; emit(&#39;customChange&#39;, event.target.value); }; </script> <template> <div> <label>Custom Input</label> <input type="text" :value="inputValue" @input="handleChange" /> </div> </template> ``` #### 关键转换点详解 1. **props和emits声明**: - 原始代码中,props和emits在`setup()`外部定义(选项API风格)。在`<script setup>`中,使用`defineProps`和`defineEmits`宏直接声明,这些宏在编译时自动处理类型和验证[^1][^4]。 - 例如,`defineProps`替换了`props`选项,`defineEmits`替换了`emits`选项。 2. **响应式状态管理**: - 在`<script setup>`中,变量如`inputValue`使用`ref`直接声明,无需包裹在`setup()`函数内或通过`return`暴露。模板自动访问这些变量,简化了代码结构[^2]。 3. **函数和事件处理**: - 函数如`handleChange`直接定义,并可直接调用`emit`(通过`defineEmits`返回)。这避免了在`setup()`中解构`context`或`emit`的需要[^4]。 4. **生命周期钩子**: - 如果需要添加钩子(如`onMounted`),直接导入并使用: ```javascript import { onMounted } from &#39;vue&#39;; onMounted(() => { console.log(&#39;Component mounted&#39;); }); ``` 5. **暴露属性**: - 如果父组件需要通过`ref`访问子组件的属性,使用`defineExpose`: ```javascript defineExpose({ inputValue }); ``` #### 注意事项 - **兼容性**:`<script setup>`需要Vue 3.2+版本,并依赖构建工具(如Vite或Webpack)进行编译。 - **性能优势**:语法糖减少了样板代码,提升开发效率,但底层响应式原理(基于Proxy)不变[^2]。 - **与Pinia集成**:当使用状态Pinia时,注意`storeToRefs`用于解构store,而Vue的`toRefs`用于响应式对象;在`<script setup>`中,直接导入即可[^3]。 - **错误处理**:避免在`<script setup>`中使用`this`,因为上下文已隐式处理。 通过以上步骤,您可以轻松将现有Vue 3代码迁移到`<script setup>`语法糖,享受更简洁的编码体验。实践中,建议从简单组件开始测试,逐步应用到复杂场景[^1][^4]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值