Vue3 props ref router 数据通讯传输等使用记录

一、 props

1、 typescript环境 props自定义类型propType

复制代码
//子组件的props类型是复杂的类型的时候,可以用propType进行强制类型转换
//eg 复杂函数,对象数组,对象的类型检查
props: {
 callback: {
 type: Function as PropType<() => void>,
 },
 tableHead: {
 type: Array as PropType<getTableHeadRes[]>,
 default:
 () => [],
 },
 person: {
 type: Object as PropType<Person>,
 required:true,
 },
}

二、ref 标签

1、Vue3中使用ref标签对组件进行操作方法

在Vue2中 一般用 this.$ref.xxxx 进行获取组件对象

Vue3中就不使用这个方法了: 例如:

复制代码
// 如:
 <el-upload class="upload-demo" action="" :http-request="handleUpload" 
:on-change="handleChange"
 :before-upload="handleBeforeUpload" :show-file-list="false" :auto-upload="false" :limit="1" ref="uploadRef">
 <el-button type="primary" icon="upload" slot="trigger">导入</el-button>
 </el-upload>

//想要获取el-upload组件对象,先创建
 const uploadRef = ref()
//使用的话需要xxx.value.xxx ,清除上传列表
 uploadRef.value.clearFiles()

Vue3 中 ref 标记组件使用 : 在 Vue3 中我们还可以使用 ref 标记组件来进行获取父子组件获取属性和方法的操作。

复制代码
// 父组件
<template>
    <hello-world ref='son'></hello-world>
    <button @click='getSon()'>获取</button>
</template>

<script setup>
    // 首先还是先引入子组件
    import HelloWorld from './components/HelloWorld.vue'

    // 然后引入 ref ,并声明 son
    import {ref} from 'vue'
    const son = ref()
    const getSon = () => {
        console.log(son.value.title)
        // 子组件的方法
        son.value.sonMethod()
    }

</script>

//子组件
<template>
  <div> {{ title }} </div>
</template>

<script setup>
    import {ref} from 'vue'
    const title = ref('我是子组件的title')
    const sonMethod = () => {
      console.log('我是子组件的方法')
    }

    // 最要的一步,这里我们需要把父组件需要的属性和方法暴露出去,这样父组件才能获取的到
    defineExpose({sonMethod, title})
</script>

2、vue3 获取 ref 元素的几种方式

(1)、静态绑定
复制代码
// 获取单个 dom 元素
<template>
    <button ref="domRef">dom</button>
</template>
<script setup>
    import { ref, onMounted } from 'vue';

    // 声明一个跟 ref 同名的变量即可,来保存元素
    const domRef = ref(null);

    onMounted(() => {
        domRef.value.style.background = "red";
    })
</script>
 // v-for 中使用
 <template>
    <ul>
        <li v-for="item in list" ref="domRef">
            {{ item }}
        </li>
    </ul>
</template>
<script setup>
    import { ref, onMounted } from 'vue';
    const list = ref([
        /* ... */
    ])

    const domRef = ref([]);
    onMounted(() => {
        console.log(domRef.value)
    })
</script>

//但需要注意的是,itemRefs 元素数组并不保证与 list 数组为相同的顺序
//需要注意的是,访问的时候,要确保 ref 引用值已经成功绑定上元素,我们可以使用以下几种方式确保获取
// onMounted
onMounted(() => {
  domRef.value.style.background = "red";
})

// nextTick
nextTick(() => {
    domRef.value.style.background = "red";
})

// watchEffect
watchEffect(() => {
    if (domRef.value) {
        domRef.value.style.background = "red";
    }
})

// watch
watch(domRef, val => {
    domRef.value.style.background = "red";
})
(2)、动态绑定

动态绑定中,分为两种方式,一种是通过将 ref 设置为函数,第二种则是通过 getCurrentInstance 方法访问当前组件实例上的 $refs

ref 设置函数,获取单个 dom 元素

复制代码
<template>
    <button :ref="handleRef">动态 Ref</button>
</template>
<script setup>
    import { ref } from 'vue'

    const btnRef = ref(null);
    // 赋值动态ref到变量
    const handleRef = el => {
        if (el) {
            btnRef.value = el;
        }
    }
</script>

// ref 的函数回调中,我们能够接受到元素返回值,再动态设置到响应式变量即可

ref 设置函数,v-for 中使用循环设置ref并获取

  1. 使用v-for循环出来的dom,ref通过index下标来命名

    // ref通过index下标来命名

    <Pie :id="`riskSpread${index}`" :ref="el => getRiskSpreadRef(el, index)" :title="item.title" :data="item.data" emptyText="暂无风险" />

    // 此时riskSpreadRefList里面放的就是所有ref
    const riskSpreadRefList = ref<HTMLElement[]>([]);
    //
    const getRiskSpreadRef = (el, index) => {
    if (el) {
    riskSpreadRefList.value[index] = el;
    }
    };
    // 使用:循环去取就行了,item就是通过ref拿到的dom元素。可以操作上面定义的变量或方法
    riskSpreadRefList.value?.forEach((item: any) => {
    console.log(item)
    });m)
    });

  2. 还有一种获取ref的方法,与上面略相似,记录一下,但是用push可能会造成ref还没渲染完得到null的情况,所以最好还是上面那样写

    复制代码
    //
    <div class="chart">
     <Pie
    :id="`risk${index}`"
    :ref="getRiskRef"
    :data="item.data"
    @clickPie="queryRiskList"
    />
    </div>
    //
    let riskRefList = ref<HTMLElement[]>([]);
    const getRiskRef = (el) => {
     if (el) {
       riskRefList.value.push(el);
     }
    };
    
    //
    riskRefList.value?.forEach((item: any) => {
       console.log(item)
    });
(3)、通过 getCurrentInstance 方法

这种方式,与 vue2 的 this.$refs 一般无二,只是我们用了 getCurrentInstance 函数在 setup 中获取了当前组件实例以替代 this

复制代码
<template>
    <ul>
        <li v-for="item in list" :key="item.id" :ref="item.id">
            <button>{{ item.id }}</button>
        </li>
    </ul>
</template>
<script setup>
    import { getCurrentInstance, onMounted, ref } from "vue";
    const { proxy } = getCurrentInstance();
    const list = ref([{ id: "111" }, { id: "222" }, { id: "333" }]);
    onMounted(() => {
        console.log(proxy.$refs["111"]);
    })
</script>

(4)、获取 vue 实例

需要注意的是,无论通过以上哪种方式获取元素,如果元素为 vue 组件,则需要在子组件中使用 defineExpose 进行暴露。

在父组件中,我们静态绑定 childRef

复制代码
<template>
    <Test ref="childRef"></Test>
</template>

<script setup lang="ts">
    import Test from "./components/test.vue";
    import { onMounted, ref } from "vue";

    const childRef = ref(null);
    onMounted(() => {
        console.log(childRef.value.btnRef)
    })
</script>

在子组件中,我们需要通过defineExpose函数,手动暴露出来ref引用值,该值指向了button元素

复制代码
<template>
    <button ref="btnRef">子组件</button>
</template>

<script setup>
    import { ref } from "vue";
    const btnRef = ref(null)
    defineExpose({
        btnRef
    })
</script>

三、vue3数据类型ref,Reactive,shallowRef,shallowReactive基本用法

  1. ref 用于创建基础类型的响应式,也可以创建引用类型的响应式.
  2. ref 对于引用类型,底层也是转换为 reactive 来进行响应式处理
  3. ref 创建的响应式数据在脚本中需要通过 .value, 模板中会自动添加上 .value,所以模板中不需要通过 .value 访问
  4. ref 创建出来的响应式就是 RefImpl 实例对象
  5. Ref 与 Reactive 创建的都是递归响应的,将每一层的 json 数据解析成一个 proxy 对象
  6. shallowRef 与 shallowReactive 创建的是非递归的响应对象
  7. shallowReactive 创建的数据第一层数据改变会重新渲染 dom
  8. shallowRef 创建的响应式对象,需要修改整个 value 才能重新渲染 dom
  9. 想更新 shallowRef 的某一层数据,并且想触发渲染,可以使用 triggerRef
  10. reactive 不支持对基本类型数据响应式
  11. ref 是在 reactive 上在进行了封装进行了增强, 全部使用ref可以
  12. ref(1) 就等价于 reactive({value: 1})
  13. 可以all in reactive,把页面的响应式数据都集中在一个reactive中,类似vue2的data

四、Vue 路由使用

1、路由的跳转方式

  • 声明式导航:router-link,要有to属性
  • 编程式导航 :$router.push | replace实现,可以处理一些业务

2、路由传参,参数有几种呢?

  • params参数
  • query参数
params参数
1、动态路由时传参
  • 属于路径当中的一部分,在配置路由的时候,需要占位。地址栏表现为 /search/v1

  • 刷新页面,参数还在

    //占位:
    path:'/search/:keyword'

2、非动态路由时传参
  • 不属于路径当中的一部分,类似 post请求,地址栏地址不变

  • 但是刷新参数数据会消失

  • params参数,跳转路由需要用:name

    this.$router.push({
    name:'search',
    params:{
    keyword:this.keyword
    }
    });

query参数
  • 不属于路径当中的一部分,类似于get请求,地址栏表现为 /search?k1=v1&k2=v2,不需要占位

  • 跳转路由需要用:name或path都可以。网上说要用path,但是自己测试都可以。

    this.$router.push({
    path:'/search',
    query:{
    k1:this.v1,
    k2:this.v2
    }
    });

3、路由传参

3.1.声明式导航传参
复制代码
<router-link :to="'/search/'+keyword">搜索</router-link>
<!-- http://localhost:8080/search/hhh -->
<router-link :to="{path: '/search', name: 'search', params: { keyword: hhh } }">搜索</router-link>
3.2.编程式导航
复制代码
//1、字符串形式  this.$router.push('/search/'+this.keyword+'?k='+this.keyword.toUpperCase());
//2、模板字符串
this.$router.push(`/search/${this.keyword}?k=${this.keyword.toUpperCase()}`);
//3、对象(常用),传的是对象,路由跳转传参params参数,需要路由配置文件给路由命个名 ==>name:'search'
this.$router.push({
    name:'search',
    params:{
        keyword:this.keyword
    },
    query:{
        k:this.keyword.toUpperCase()
    }
});
//  http://localhost:8080/search/hh?k=HH
  • 对象(常用):this.$router.push({name:"路由名字",params:{传参},query:{传参})
  • 以对象方式传参时,如果我们传参中使用了params,只能使用name,不能使用path,如果只是使用query传参,可以使用path
3.3. props:路由组件可以传递props
复制代码
//router/inex.js
{
    name: "search",
    path: "/search/:keyword?",
    component: Search,
    meta: {
        show: true,
    },
    //1、布尔值写法,props只能传params
    props:true
    //2、对象写法,额外给路由自己传递一些props
    props:{
        a:1,
        b:2
    }
    //3、函数写法,可以params参数、query参数,通过prop传递给路由组件(很少用)
    props:($route)=>{
        return{
            keyword:$route.params.keyword,
            k:$route.query.k
        }
    }
    props: ($route) => ({keyword: $route.params.keyword,k: $route.query.k,}),
},

路由组件可以传递props

复制代码
//pages/Search/index.vue
//路由组件可以传递props
props:['keyword','a','b','k'],

4、路由传参相关问题

1、路由传递参数(对象写法)path是否可以结合params参数一起使用
  • 路由跳转传参的时候,对象的写法可以是name、path形式,但是path的写法不可以和params参数一起使用。

  • params 参数: 已不建议使用 params 方式传参 具体查看

  • (路径参数缺失是无法匹配path里面的占位符)

  • 因此,不能,传params-->对象写法,是要name的写法

    this.$router.push({
    path:'/search',
    params:{keyword:this.keyword},
    query:{k:this.keyword.toUpperCase()}
    });
    //这个写法,真实的是: http://localhost:8080/#/search?k=HH
    //正确路径,应该的是: http://localhost:8080/#/search/hh?k=HH

2、如何指定params参数可以不传?

问题场景:配置路由的时候,已经占位了(params参数),但是路由跳转的时候就不传递。

如何指定params可以传递或者不传递

解决:

  • 配置路由时,可以在占位符后面加个?【?代表可传或不传,正则的问号一次或多次】

    //router/inex.js
    {
    name:'search',
    path:'/search/:keyword?',
    component:Search,
    }

    this.$router.push({
    name:'search',
    // params:{keyword:this.keyword},
    query:{k:this.keyword.toUpperCase()}
    });
    //真实路径:http://localhost:8080/#/search?k=HHH

3、params参数可以传递可以不传递,但是如果传递为空字符串,如何解决?
  • 这个写法,真实的是:http://localhost:8080/#/?k=, 路径没有/search

  • 正确路径,应该的是:http://localhost:8080/#/search?k=

    //使用undefined解决:params参数可以传递,或不传递(传空字符串)
    this.$router.push({
    name: "search",
    params: { keyword: ""||undefined },
    query: { k: this.keyword.toUpperCase() },
    });

4、路由组件能不能传递props数据
  • 3.3. props:路由组件可以传递props

五、数据通讯传输:9 种组件通信机制

1、概述

我们将涵盖以下关键概念:

  • Props / Emit: 用于父组件向子组件传递数据以及子组件向父组件发出事件通知。
  • Provide / Inject: 用于父组件向所有后代组件提供数据,实现依赖注入。
  • Pinia: 一个现代化的 Vue 状态管理库,替代了传统的 Vuex。
  • Expose / Ref: 用于父组件直接访问子组件的实例或元素。
  • Attrs: 用于获取父组件传递给子组件的非 prop 属性。
  • v-Model: 用于实现双向数据绑定。
  • mitt.js: 一个事件总线库,用于跨组件通信。
  • Slots: 用于父组件控制子组件部分内容,实现组件模板的灵活性和可重用性。

2、Props / Emit

2.1 父组件向子组件传递数据

父组件通过 props 属性将数据传递给子组件。子组件可以通过 defineProps 方法获取这些数据。

复制代码
<!-- 父组件 Parent.vue -->
<template>
  <Child :msg2="msg2" />
</template>
<script setup lang="ts">
import Child from './Child.vue';
import { ref, reactive } from 'vue';

const msg2 = ref<string>('This is the message 2 sent to the child component');
// 或对于复杂类型
const msg2 = reactive<string>(['This is the message 2 for the descendant component']);
</script>

<!-- 子组件 Child.vue -->
<template>
  <!-- 使用 props -->
  <div>子组件收到消息:{{ props.msg2 }}</div>
</template>
<script setup lang="ts">
// 无需导入,直接使用
// import { defineProps } from "vue"
interface Props {
  msg1: string;
  msg2: string;
}
const props = withDefaults(defineProps<Props>(), {
  msg1: '',
  msg2: '',
});
console.log(props); // { msg2: "This is the message 2 for the descendant component" }
</script>
2.2 子组件向父组件传递数据

子组件通过 emit 方法向父组件发送事件,并传递数据。父组件可以通过 v-on 指令监听事件,并接收数据。

复制代码
<!-- 子组件 Child.vue -->
<template>
  <button @click="emit('myClick')">Button</button>
  <!-- 方法二 -->
  <button @click="handleClick">Button</button>
</template>
<script setup lang="ts">
// 方法一
// import { defineEmits } from "vue"
// 对应方法一
const emit = defineEmits(['myClick', 'myClick2']);
// 对应方法二
const handleClick = () => {
  emit('myClick', 'This is the message sent to the parent component');
};

// 方法二,不适合 Vue3.2 版本,useContext() 已过时
// import { useContext } from "vue"
// const { emit } = useContext()
// const handleClick = () => {
//     emit("myClick", "This is the message sent to the parent component")
// }
</script>

<!-- 父组件 Parent.vue -->
<template>
  <Child @myClick="onMyClick" />
</template>
<script setup lang="ts">
import Child from './Child.vue';

const onMyClick = (msg: string) => {
  console.log(msg); // This is the message received by the parent component
};
</script>

注意:

  • 如果父组件使用 setup() 方法,子组件使用脚本设置语法,子组件将无法从父组件的数据中接收属性,只能接收父组件 setup() 函数中传递的属性。

  • 如果父组件使用脚本设置语法糖,子组件使用 setup() 方法,子组件可以从父组件的数据和 setup() 函数中通过 props 接收属性。但是,如果子组件想要在它的 setup 中接收属性,它只能接收父组件 setup() 函数中的属性,不能接收数据属性。

2.3 组合式API和选项式AP混用时进行通信(父组件使用语法糖方式,子组件使用函数方式时互相通信,且可以使用v-model 更新属性值)

在 Vue3 中,$emit('update:visible', false) 是一种用于子组件向父组件传递事件的方式,通常用于实现 双向绑定 或通知父组件更新某个属性的值。

以下是一个简单的示例,展示如何使用 $emit 更新父组件的 visible 属性:

复制代码
<!-- 子组件 -->
<template>
 <div>
   <button @click="closeDialog">关闭弹窗</button>
 </div>
</template>
<script setup>
import { defineEmits } from 'vue';
// 定义事件
const emit = defineEmits(['update:visible']);
// 触发事件
const closeDialog = () => {
 emit('update:visible', false);
};
</script>

<!-- 父组件 -->
<template>
 <div>
   <Child :visible="isVisible" @update:visible="isVisible = $event" />
   <p>弹窗状态:{{ isVisible }}</p>
 </div>
</template>
<script setup>
import { ref } from 'vue';
import Child from './Child.vue';
const isVisible = ref(true);
</script>

工作原理:子组件通过 emit('update:visible', false) 通知父组件更新 visible 属性。父组件通过监听 update:visible 事件,动态更新其 isVisible 值。 注意事项:双向绑定:Vue3 推荐使用 v-model 的新语法(如 v-model:visible),它是 update:propName 的语法糖。单向数据流:子组件不能直接修改父组件传递的 props,而是通过 emit 通知父组件更新。

替代方案:如果需要更简洁的写法,可以使用 v-model:

复制代码
<Child v-model:visible="isVisible" />
//这会自动绑定 update:visible 事件,无需手动监听

3、Provide / Inject

provide 和 inject 机制用于在父组件和其所有后代组件之间共享数据,即使它们不是直接的父子关系。

  • provide: 用于在父组件中定义要共享的数据。

  • inject: 用于在后代组件中获取共享数据。

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

    provide('name', 'Jhon');
    </script>

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

    const name = inject('name');
    console.log(name); // Jhon
    </script>

4、Pinia

Pinia 是一个现代化的 Vue 状态管理库,旨在取代传统的 Vuex。

复制代码
// main.ts
import { createPinia } from 'pinia';
createApp(App).use(createPinia()).mount('#app');

// /store/user.ts
import { defineStore } from 'pinia';
export const userStore = defineStore('user', {
  state: () => {
    return {
      count: 1,
      arr: [],
    };
  },
  getters: {
    // ...
  },
  actions: {
    // ...
  },
});

// Page.vue
<template>
  <div>{{ store.count }}</div>
</template>
<script lang="ts" setup>
import { userStore } from '../store';
const store = userStore();
// 解构
// const { count } = userStore()
</script>

5、Expose / Ref

expose 和 ref 机制用于父组件直接访问子组件的实例或元素。

复制代码
<!-- 子组件 Child.vue -->
<script setup>
// 方法一,不适合 Vue 3.2 版本,useContext() 在此版本中已过时
// import { useContext } from "vue"
// const ctx = useContext()
// 暴露属性和方法等
// ctx.expose({
//     childName: "This is a property of the child component",
//     someMethod(){
//         console.log("This is a method of the child component")
//     }
// })

// 方法二,适合 Vue 3.2 版本,无需导入
// import { defineExpose } from "vue"
defineExpose({
  childName: 'This is a property of the child component',
  someMethod() {
    console.log('This is a method of the child component');
  },
});
</script>

<!-- 父组件 Parent.vue -->
<template>
  <Child ref="comp" />
  <button @click="handlerClick">Button</button>
</template>
<script setup>
import Child from './Child.vue';
import { ref } from 'vue';

const comp = ref(null);

const handlerClick = () => {
  console.log(comp.value.childName); // 获取子组件暴露的属性
  comp.value.someMethod(); // 调用子组件暴露的方法
};
</script>

6、Attrs

attrs 对象包含从父级作用域传递给子组件的非 prop 属性,不包括 class 和 style

复制代码
<!-- 父组件 Parent.vue -->
<template>
  <Child :msg1="msg1" :msg2="msg2" title="3333" />
</template>
<script setup>
import Child from './Child.vue';
import { ref, reactive } from 'vue';

const msg1 = ref('1111');
const msg2 = ref('2222');
</script>

<!-- 子组件 Child.vue -->
<script setup>
import { defineProps, useContext, useAttrs } from 'vue';
// 无需在 3.2 版本中导入 defineProps,直接使用
const props = defineProps({
  msg1: String,
});
// 方法一,不适合 Vue3.2 版本,因为 useContext() 已过时
// const ctx = useContext()
// 如果 msg1 没有作为 prop 接收,它将是 { msg1: "1111", msg2:"2222", title: "3333" }
// console.log(ctx.attrs) // { msg2:"2222", title: "3333" }

// 方法二,适合 Vue3.2 版本
const attrs = useAttrs();
console.log(attrs); // { msg2:"2222", title: "3333" }
</script>

7、v-Model

v-model 指令用于实现双向数据绑定。

复制代码
<!-- 父组件 Parent.vue -->
<template>
  <Child v-model:key="key" v-model:value="value" />
</template>
<script setup>
import Child from './Child.vue';
import { ref, reactive } from 'vue';

const key = ref('1111');
const value = ref('2222');
</script>

<!-- 子组件 Child.vue -->
<template>
  <button @click="handlerClick">Button</button>
</template>
<script setup>
// 方法一,不适合 Vue 3.2 版本,因为 useContext() 已过时
// import { useContext } from "vue"
// const { emit } = useContext()

// 方法二,适合 Vue 3.2 版本,无需导入
// import { defineEmits } from "vue"
const emit = defineEmits(['key', 'value']);

// 使用
const handlerClick = () => {
  emit('update:key', 'New key');
  emit('update:value', 'New value');
};
</script>

8、mitt.js

在 Vue3 中,事件总线不再可用,但现在可以使用 mitt.js 来替代,它基于与事件总线相同的原理。

复制代码
// mitt.js
import mitt from 'mitt';
const mitt = mitt();
export default mitt;

// 组件 A
<script setup>
import mitt from './mitt';

const handleClick = () => {
  mitt.emit('handleChange');
};
</script>

// 组件 B
<script setup>
import mitt from './mitt';
import { onUnmounted } from 'vue';

const someMethed = () => {
  // ...
};
mitt.on('handleChange', someMethed);
onUnmounted(() => {
  mitt.off('handleChange', someMethed);
});
</script>

9、Slots

Slots 允许父组件控制子组件部分内容,从而实现组件模板的灵活性和可重用性。

9.1 默认插槽
复制代码
<!-- 父组件 Parent.vue -->
<template>
  <FancyButton>Click me!</FancyButton>
</template>

<!-- 子组件 Child.vue -->
<template>
  <button class="fancy-btn">
    <slot></slot>
  </button>
</template>

Click me!

9.2 具名插槽

具名插槽是基于默认插槽的一种分类,可以理解为将内容匹配到对应的占位符。

复制代码
<!-- 父组件 Parent.vue -->
<template>
  <Child>
    <template v-slot:monkey>
      <div>monkey</div>
    </template>
    <button>Click me!</button>
  </Child>
</template>

<!-- 子组件 Child.vue -->
<template>
  <div>
    <!-- 默认插槽 -->
    <slot></slot>
    <!-- 具名插槽 -->
    <slot name="monkey"></slot>
  </div>
</template>

monkey

Click me!

9.3 作用域插槽

插槽的内容无法访问子组件的状态。然而,在某些情况下,插槽的内容可能想要使用父组件和子组件作用域的数据。为了实现这一点,我们需要一种方法让子组件在渲染时向插槽提供一些数据。

复制代码
<!-- 父组件 Parent.vue -->
<template>
  <!-- v-slot="{scope}" 用于接收从子组件传递上来的数据 -->
  <!-- :list="list" 将列表传递给子组件 -->
  <Child v-slot="{scope}" :list="list">
    <div>
      <div>Name: {{ scope.name }}</div>
      <div>Occupation: {{ scope.occupation }}</div>
      <hr>
    </div>
  </Child>
</template>
<script setup>
import { ref } from 'vue';
import Child from './components/Child.vue';

const list = ref([
  { name: 'Jhon', occupation: 'Thundering' },
  // ...
]);
</script>

<!-- 子组件 Child.vue -->
<template>
  <div>
    <!-- 使用 :scope="item" 返回每个项目 -->
    <slot v-for="item in list" :scope="item" />
  </div>
</template>
<script setup>
const props = defineProps({
  list: {
    type: Array,
    default: () => [],
  },
});
</script>
相关推荐
Cobyte2 小时前
从 JavaScript 的角度理解 Python 语法
前端
travel_wsy2 小时前
vue Pinia 状态管理库
前端·pinia
巫山老妖2 小时前
📐 Embedding向量化:AI如何「理解」语义?万物皆可向量!
前端
巫山老妖2 小时前
🤖 AI Agent智能体:从「聊天机器人」到「数字员工」的关键跨越!
前端
软希网分享源码2 小时前
中英双语言量化交易投资源码/跟单搬砖区块链交易所源码/前端uniapp纯源码+后端
前端·uni-app·区块链·中英双语言量化交易投资源码
巫山老妖2 小时前
🔌 MCP协议:AI工具生态的「USB标准」,数千个工具一键接入!
前端
巫山老妖2 小时前
🎯 AI Skills技能体系:让Agent拥有「专业技能」,可复用可进化!
前端
巫山老妖2 小时前
⚠️ AI幻觉:当AI「一本正经地胡说八道」,我们该怎么办?
前端
巫山老妖2 小时前
🧠 LLM大语言模型:AI世界的「概率引擎」,你真的了解它吗?
前端