vue基础(第二章 )

目录

1:创建自己的第一个vue

1.1:项目结构

1.2:创建自己的第一个vue3项目

1.2.1:main.ts项目入口

1.2.2:App.vue项目根组件

1.2.3:启动项目

2:添加子组件

2.1:子组件person

2.2:子组件需要注册到根组件app.vue中,分为导入、注册、使用

3:子组件分析setup

3.1:setup函数

3.2:setup函数语法糖

3.2.1:自动注册app.vue

4:ref响应式数据(用于axios的ajax请求)

4.1:默认不是响应式,修改不会改变

4.2:ref函数实现响应式数据(原始类型)

4.3:reactive函数实现响应式数据(只支持对象类型)

5:vue指令

5.1:v-bind绑定属性

5.2:v-model双向数据绑定

5.3:v-for循环解析数据

6:计算属性computed(只读不能修改)有缓存机制

7:watch监视用来数据修改后执行回调函数

8:标签的ref属性

8.1:普通标签的ref属性,用来屏蔽标签的id相同情况下的错误

8.2:组件标签的ref属性,用来子组件向父组件传递数据

[9:props 父组件向子组件传递数据,子组件不能修改](#9:props 父组件向子组件传递数据,子组件不能修改)

10:vue3的生命周期

11:组合式API的Hooks(逻辑复用)

11.1:使用hooks之前

11.2:使用hook之后


1:创建自己的第一个vue

1.1:项目结构

首先我们知道了vue的项目结构

1.2:创建自己的第一个vue3项目

首先删除src下的所有文件,自己创建main.ts和App.vue

1.2.1:main.ts项目入口

TypeScript 复制代码
// 第一步:创建main.ts文件,作为项目的入口文件

//1:引入Vue的createApp函数和根组件App.vue,作用是创建Vue应用实例和挂载根组件
import { createApp } from 'vue'

//2:引入根组件App.vue,作为应用的根组件
import App from './App.vue'

//3:创建Vue应用实例
const app11 = createApp(App)

//4:挂载应用实例到index.html中的#app元素上
app11.mount('#app')

1.2.2:App.vue项目根组件

html 复制代码
<!-- 根组件 每一个vue组件都是从这里开始的,文件扩展名是.vue -->
 <!-- 一个合法的Vue组件有三部分组成 :模板template、脚本script、样式style-->
 <template>
   <div id="app">
     <h1>Hello Vue3!</h1>
   </div>
 </template>


<!-- 基于ts -->
<script lang="ts">
// 默认导出 在main.ts中会导入这个组件
export default {
    // 影响到VUE浏览器插件的显示
  name: 'App',
  setup() {
    // 组件的逻辑代码
  }
}
</script>

<!-- scoped 局部样式 -->
<style scoped>
    /* #.id  .class 设置样式*/
    #app {
        font-family: Avenir, Helvetica, Arial, sans-serif;
        background-color: #f5f5f5;
        -webkit-font-smoothing: antialiased;
        -moz-osx-font-smoothing: grayscale;
        text-align: center;
        color: #2c3e50;
        margin-top: 60px;
    }

</style>

1.2.3:启动项目

2:添加子组件

2.1:子组件person

html 复制代码
<!-- person子组件 -->
<template>
    <div class="person">
        <h1>我是person组件</h1>
        <h2>姓名:{{ name }}</h2>
        <h2 class="phone"></h2>
        <button @click="showPhone()">显示联系电话@click</button>
        <button v-on:click="showPhone()">显示联系电话v-on:click</button>

    </div>
</template>

<script lang="ts">
export default {
    // vue的插件组件显示名字
    name: 'Person',

    //vue3中使用setup函数来定义组件的逻辑代码 ,组件的逻辑代码。初始化执行一次 
    //setup只会执行一次
    setup() {
        //准备数据
        let name: string = '张三';
        let phone: number = 1234567890;

        function showPhone() {
            alert(phone)
        };
        //返回数据给模板使用
        return {
            name: name,//暴露参数
            showPhone: showPhone //暴露方法
        };

    }
}

</script>

<style lang="css" scoped>
.person {
    border: 1px solid #ccc;
    padding: 20px;
    margin: 20px;
}
</style>

2.2:子组件需要注册到根组件app.vue中,分为导入、注册、使用

TypeScript 复制代码
<!-- 根组件 每一个vue组件都是从这里开始的,文件扩展名是.vue -->
<!-- 一个合法的Vue组件有三部分组成 :模板template、脚本script、样式style-->
<template>
    <div id="app">
        <h1>Hello Vue3!</h1>
        <!-- 3:使用子组件 -->
        <person></person>
    </div>

</template>


<!-- 基于ts -->
<script lang="ts">

// 1:导入子组件
import Person from './componnets/person.vue'

// 默认导出 在main.ts中会导入这个组件
export default {
    //2:注册子组件
   components:{Person}
}
</script>

<!-- scoped 局部样式 -->
<style scoped>
/* #.id  .class 设置样式*/
#app {
    font-family: Avenir, Helvetica, Arial, sans-serif;
    background-color: #f5f5f5;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    text-align: center;
    color: #2c3e50;
    margin-top: 60px;
}
</style>

3:子组件分析setup

3.1:setup函数

TypeScript 复制代码
<!-- person子组件 -->
<template>
    <div class="person">
        <h1>我是person组件</h1>
        <h2>姓名:{{ name }}</h2>
        <h2 class="phone"></h2>
        <button @click="showPhone()">显示联系电话@click</button>
        <button v-on:click="showPhone()">显示联系电话v-on:click</button>

    </div>
</template>

<script lang="ts">
export default {
    // vue的插件组件显示名字
    name: 'Person',

    //vue3中使用setup函数来定义组件的逻辑代码。初始化执行一次 
    setup() {
        //准备数据
        let name: string = '张三';
        let phone: number = 1234567890;

        //定义方法
        function showPhone() {
            alert(phone)
        };
        //returu 返回数据给模板使用,这里是对象
        return {
            name: name,//暴露参数
            showPhone: showPhone //暴露方法
        };

        // return function(){
        //      return "渲染函数,会覆盖掉person组件中template中的所有模板内容"
        // };

    }
}

</script>

<style lang="css" scoped>
.person {
    border: 1px solid #ccc;
    padding: 20px;
    margin: 20px;
}
</style>

3.2:setup函数语法糖

3.2.1:自动注册app.vue

TypeScript 复制代码
<!-- 根组件 每一个vue组件都是从这里开始的,文件扩展名是.vue -->
<!-- 一个合法的Vue组件有三部分组成 :模板template、脚本script、样式style-->
<template>
    <div id="app">
        <h1>Hello Vue3!</h1>
        <!-- 3:使用子组件 -->
        <person></person>
        <cat></cat>
    </div>

</template>


<!-- 基于ts  setup语法糖 不需要注册了 只需导入和使用组件-->
<script lang="ts" setup>

// 1:导入子组件
import Person from './componnets/person.vue'
import Cat from './componnets/cat.vue';

// // 默认导出 在main.ts中会导入这个组件
// export default {
//     //2:注册子组件
//    components:{Person,Cat}
// }
</script>

4:ref响应式数据(用于axios的ajax请求)

4.1:默认不是响应式,修改不会改变

TypeScript 复制代码
<template>
    <div>
        <h1>狗狗</h1>
        <h1>名字:{{ name }}</h1>
        <h1>年龄:{{ age }}</h1>
        <button v-on:click="changename">修改名字不会改变,需要响应式</button>
        <button v-on:click="changeage">修改age不会改变,需要响应式</button>


    </div>

</template>

<script lang="ts" setup>

let name = "小黑"
let age = 0;
function changename() {
    name = "小黑1";
}
function changeage() {
    age++;
}

</script>

<style></style>

4.2:ref函数实现响应式数据(原始类型)

TypeScript 复制代码
<template>
    <div>
        <h1>狗狗</h1>
        <h1>名字:{{ name }}</h1>
        <h1>年龄:{{ age }}</h1>
        <button v-on:click="changename">修改名字不会改变,需要响应式</button>
        <button v-on:click="changeage">修改age不会改变,需要响应式</button>


    </div>

</template>

<script lang="ts" setup>
// 1:导入vue框架的ref函数,让数据具有响应式的效果,需要包裹原始类型
import { ref } from 'vue';

//2:使用ref包裹 就有了响应式
//执行ref函数返回的是refimpl对象
//使用name.value 返回
// {
//     "dep": {
//         "version": 0,
//         "sc": 0,
//         "__v_skip": true
//     },
//     "__v_isRef": true,
//     "__v_isShallow": false,
//     "_rawValue": "小黑",
//     "_value": "小黑"
// }
let name = ref("小黑")
let age = ref(0);
console.log(name);
console.log(age);
function changename() {
    //这里修改值,实质上是在ref函数中的refimpl对象set设置了新的值,然后渲染新的值
    name.value = "小黑1";
}
function changeage() {
    age.value++;
}

</script>

<style></style>

4.3:reactive函数实现响应式数据(只支持对象类型)

底层是代理对象

TypeScript 复制代码
<template>
    <div>
        <h1>狗狗</h1>
        <h1>名字:{{ name }}</h1>
        <h1>年龄:{{ age }}</h1>
        <button v-on:click="changename">修改名字不会改变,需要响应式</button>
        <button v-on:click="changeage">修改age不会改变,需要响应式</button>

        <hr>
        <h1>user.name1:{{ user.name1 }}</h1>
        <h1>user.age1:{{ user.age1 }}</h1>
        <h1>user.address.city:{{ user.address.city }}</h1>


        <button v-on:click="changeUser">修改对象的age不会改变,需要响应式</button>
        <button v-on:click="changeUserAddress">修改user的address,需要响应式</button>



    </div>

</template>

<script lang="ts" setup>
// 1:导入vue框架的ref函数,让数据具有响应式的效果,需要包裹原始类型
import { ref } from 'vue';
import { reactive } from 'vue';

//2:使用ref包裹 就有了响应式
//执行ref函数返回的是refimpl对象
//使用name.value 返回
// {
//     "dep": {
//         "version": 0,
//         "sc": 0,
//         "__v_skip": true
//     },
//     "__v_isRef": true,
//     "__v_isShallow": false,
//     "_rawValue": "小黑",
//     "_value": "小黑"
// }
let name = ref("小黑")
let age = ref(0);

// reactive包裹代理对象
let user = reactive({
    name1: "哈哈",
    age1: 20,
    address: {
        city: "洛阳",
        street: "枫叶街"
    }
})
//类型"number"的参数不能赋给类型"object"的参数。ts-plugin(2345) reactive只支持对象
//let a=reactive(0);

console.log(name);
console.log(age);
function changename() {
    //这里修改值,实质上是在ref函数中的refimpl对象set设置了新的值,然后渲染新的值
    name.value = "小黑1";
}
function changeage() {
    age.value++;
}

function changeUser() {
    //底层原理:先找到用户对应的代理对象Proxy
    // //你表面上访问的是用户对象的用户名
    // //实际上底层访问的是代理对象上的用户名属性。
    // //访问代理对象age属性的时候,底层会做两件事:
    // //第一件事:修改目标对象上的age属性的值。
    // //第二件事:将模板页面重新渲染。
    user.age1++;
}

function changeUserAddress() {
    //底层原理:先找到用户对应的代理对象Proxy
    // //你表面上访问的是用户对象的用户名
    // //实际上底层访问的是代理对象上的用户名属性。
    // //访问代理对象age属性的时候,底层会做两件事:
    // //第一件事:修改目标对象上的age属性的值。
    // //第二件事:将模板页面重新渲染。
    let num=1;
    user.address.city = "洛阳" + (num++);
}

</script>

<style></style>

5:vue指令

5.1:v-bind绑定属性

TypeScript 复制代码
template>
    <div>
        <h1>vue指令1:
            1:所有的指令需要写在template中
            2:v-开头

            v-bind指令:
            1:v-bind:将setup函数暴露的数据,绑定到标签的属性
        </h1>

        <h2>v-bing指令</h2>
        <img v-bind:src="imgObj.src" :alt="imgObj.alt">
        <button @click="changeImg">改变图片1</button>
        <button @click="changeImg" v-bind:disabled="haha">改变图片2</button>

    </div>


</template>

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

let haha=false;

let imgObj = reactive({
    src: "https://picsum.photos/id/1036/800/500",
    alt: "没有图片"
})

function changeImg() {
    imgObj.src = "https://picsum.photos/id/1048/800/500"
}

</script>

<style></style>

5.2:v-model双向数据绑定

修改脚本数据,页面数据更新,修改页面数据,脚本数据也会更新

TypeScript 复制代码
 
            名字1:<input type="text"  v-model="inputname">

            <br>{{ inputname }}
            <button v-on:click="changeinputname1">修改名字</button>


let inputname = ref("张三")

function changeinputname1() {
    inputname.value = "lili"
}

5.3:v-for循环解析数据

TypeScript 复制代码
<div>
            <h2>v-for</h2>
            <ul>
                <li v-for="(person,index) in listPerson" :key="person.id">
                   ID:{{person.id}},名字: {{person.name}}, 年龄:{{person.age}} ,index {{index}}
                </li>
            </ul>


             <ul>
                <li v-for="(value,name,index) in persons" :key="name">
                   属性值:{{value}},属性名字: {{name}}, 属性索引:{{index}} 
                </li>
            </ul>

        </div>

let listPerson = [
    { id:1,name: '哈哈1', age: 21 },
    { id:2,name: '哈哈2', age: 22 },
    { id:3,name: '哈哈3', age: 23 },

]

let persons={id:1,name: '哈哈1', age: 21}

6:计算属性computed(只读不能修改)有缓存机制

TypeScript 复制代码
<div>
            <h1>计算属性</h1>
            姓氏:<input type="text" v-model="firstName">{{ firstName }}
            <br>
            名字:<input type="text" v-model="lastName">{{ lastName }}
            <br>
            全名:{{ firstName.slice(0, 1).toLocaleUpperCase() + firstName.slice(1) }}-{{ lastName }}

            全名方法1:{{ fullName1() }}
            全名方法2:{{ fullName1() }}

            计算属性1:{{ fullName2 }}
            计算属性2:{{ fullName2 }}



        </div>

let persons = { id: 1, name: '哈哈1', age: 21 }

let firstName = ref("zhang")
let lastName = ref("san")

const fullName1 = (() => {
    console.log("方法,2次调用,就会调用2次")
    return (
        firstName.value.slice(0, 1).toLocaleUpperCase() +
        firstName.value.slice(1) +
        '-' +
        lastName.value
    );
});

//computed 计算属性,返回值
const fullName2 = computed(() => {
    console.log("计算属性只会调用一次,当之发生变化的时候")
    return (
        firstName.value.slice(0, 1).toLocaleUpperCase() +
        firstName.value.slice(1) +
        '-' +
        lastName.value
    );
});

7:watch监视用来数据修改后执行回调函数

TypeScript 复制代码
<template>
    <div>
        <h1>watch监视</h1>
        <h1>ref计数器:{{ count }}</h1>
        <button @click="addone">修改ref响应数据的基本类型</button>


        <h1>ref对象:{{ user }},{{ user.age }},{{ user.name }}</h1>
        <button @click="changeName">修改ref响应数据的对象name</button>
        <button @click="changeAge">修改ref响应数据的对象age</button>
        <button @click="changeUser">修改ref响应数据的对象user</button>


    </div>

</template>

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

let count = ref(0);

let addone = function changCount() {
    count.value++;
}
//1:监视ref响应数据的基本类型
//watch(被监视数据,回掉函数,配置项),这里监视count
const stopWatch = watch(count, (newValue, oldValue) => { //a是新的值 b是旧的值
    console.log("count被修改了", newValue, oldValue);
    if (newValue >= 5) {
        stopWatch();//调用停止监视
    }

}, { immediate: true })//immediate:true 页面打开就开始监视,就会执行回掉函数



//2:监视ref响应数据的对象
//watch(被监视数据,回掉函数,配置项),这里监视count
let user = ref({
    name: "哈哈",
    age: 10
})
function changeName() {
    user.value.name = "11";
}

function changeAge() {
    user.value.age++;
}
function changeUser() {
    // Object.assign(user,{ //用于reactive监视
    //     name: "张三11",
    //     age: 100
    // })
    user.value = {
        name: "张三11",
        age: 100
    }
}
// 默认 只有changeUser方法修改了user才会被监视,单单修改name和age不会被监视
watch(user, (newValue, oldValue) => {
   
    console.log("user被修改了", newValue, oldValue);


}, {deep:true}) //这里开启深度监视,才能监视到name和age的修改

</script>

<style></style>

8:标签的ref属性

8.1:普通标签的ref属性,用来屏蔽标签的id相同情况下的错误

TypeScript 复制代码
父组件标签
<template>
    <div class="fu">
        <!-- ref的名字一样。也不影响 -->
        <h1 ref="h1">父组件1</h1>
        <button @click="getfu">父元素点击</button>
        <zi></zi>
    </div>

</template>

<script lang="ts" setup>
import { ref } from 'vue';
import zi from './zi.vue';

let h1 = ref();

function getfu() {
    console.log("父", h1.value) //<h1>父组件1</h1>
}


</script>

<style>
.fu {
    background-color: blue;
}
</style>

子组件标签
<template>
    <div class="zi">
        <h1>子组件1</h1>
        <!-- ref的名字一样。也不影响 -->
        <button ref="h1">子组件点击</button>

        <button @click="getzibut">子组件点击获取</button>
    </div>

</template>

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

//一下代码在组件创建过程中执行
let h1=ref();//zibut必须和ref="h1"的名字一样
function getzibut(){
    console.log(h1.value) //<button>子组件点击</button>
} 

</script>

<style>
.zi {
    background-color: aqua;
}
</style>

8.2:组件标签的ref属性,用来子组件向父组件传递数据

TypeScript 复制代码
父组件
<template>
    <div class="fu">
        <!-- ref的名字一样。也不影响 -->
        <h1 ref="h1">父组件1</h1>
        <button @click="getfu">父元素点击</button>

        <!-- 用ref="muzi"标记子组件 创建整个子组件实例 -->
        <zi ref="muzi"></zi>
        <button @click="getfushili">父元素点击获取子组件实例</button>

    </div>

</template>

<script lang="ts" setup>
import { ref } from 'vue';
import zi from './zi.vue';

let h1 = ref();

//这行代码核心 获取到子组件实例,需要子组件暴露
let muzi = ref();

function getfu() {
    console.log("父", h1.value) //<h1>父组件1</h1>
}
function getfushili() {
    //子组件实例 Proxy(Object) {__v_skip: true}[[Handler]]: 
    // Object[[Target]]: Proxy(Object)[[IsRevoked]]: false
    console.log("子组件实例", muzi.value)
    console.log("普通数据1", muzi.value.a)
    console.log("响应数据1", muzi.value.b)
    muzi.value.b.age=100; //修改数据,子组件数据也会改变
    muzi.value.myfunction();


}

</script>

<style>
.fu {
    background-color: blue;
}
</style>

子组件
<template>
    <div class="zi">
        <h1>子组件1</h1>
        <!-- ref的名字一样。也不影响 -->
        <button ref="h1">子组件点击</button>

        <button @click="getzibut">子组件点击获取</button>
    </div>

</template>

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

//一下代码在组件创建过程中执行
let h1 = ref();//zibut必须和ref="h1"的名字一样
function getzibut() {
    console.log(h1.value) //<button>子组件点击</button>
}

//子组件普通数据和响应式数据
let a = "子组件普通数据";
let b = reactive({
    name: "haha",
    age: 20
});
function myfunction() {
    console.log("子组件函数执行了");
}
//暴露子组件的数据和函数,以便父组件使用
defineExpose({
    a:a,
    b:b,
    myfunction:myfunction
})
</script>

<style>
.zi {
    background-color: aqua;
}
</style>

9:props 父组件向子组件传递数据,子组件不能修改

TypeScript 复制代码
父组件
<template>
    <div class="fu">
        <h1>父组件1</h1>

        <!-- 父组件通过props传递数据 -->
        <zi name="jack" :age="age" :list1="lists"></zi>

    </div>

</template>

<script lang="ts" setup>
import { ref } from 'vue';
import zi from './zi.vue';
let age = ref(20)
let lists = ref([
    { name: "aa", age: 1 },
    { name: "bb", age: 2 }
])

</script>

<style>
.fu {
    background-color: blue;
}
</style>



子组件
<template>
    <div class="zi">
        <h1>子组件1</h1>
        <h1>名字:{{ name }}</h1>
        <h1>年龄:{{ age }}</h1>
        <ul>
            <li v-for="item in list1" :key="item.id">
               id: {{ item.id }}

               name: {{ item.name }}

               age: {{ item.age }}
            </li>
        </ul>





    </div>

</template>

<script lang="ts" setup>


// 全局函数,数组接受父组件数据
defineProps(["name", "age", "list1"])
// console.log("name", name);
// console.log("age", age);




</script>

<style>
.zi {
    background-color: aqua;
}
</style>

10:vue3的生命周期

1:创建 2:挂载 3:更新 4:卸载

TypeScript 复制代码
<template v-if="flag">
    <div>
        <h1>组件的生命周期</h1>
        <h2>计数器:{{num}}</h2>
        <button @click="changeNum">点击</button>
    </div>
</template>

<script lang="ts" setup>
import { onBeforeMount, onBeforeUnmount, onBeforeUpdate, onMounted, onUnmounted, onUpdated,ref } from 'vue';

 let num=ref(0);
 let flag=ref(true);
 function changeNum(){
     num.value++;
 }

// 生命周期:创建执行一次
console.log("生命周期:创建")

//生命周期:挂载
onBeforeMount(()=>{
    console.log("挂载前")
})
onMounted(()=>{
    console.log("挂载后")

})



//生命周期:修改
onBeforeUpdate(()=>{
    console.log("修改前")
})
onUpdated(()=>{
    console.log("修改后")

})


//生命周期:修改
onBeforeUnmount(()=>{
    console.log("销毁前")
})
onUnmounted(()=>{
    console.log("销毁后")
})

</script>

11:组合式API的Hooks(逻辑复用)

11.1:使用hooks之前

TypeScript 复制代码
<template>
    <div>
        <h1>不使用hooks</h1>
        <h1>数字{{ num }}</h1>
        <button @click="add">计数器+1</button>


        <div>
            <img v-for="item in images" :key="item" :src="item" alt="加载失败">
            <button @click="getImage">添加图片</button>
        </div>
    </div>



</template>

<script lang="ts" setup>
import axios from 'axios';
import { ref } from 'vue';

let num = ref(0);
function add() {
    num.value++;
}
//'https://api.btstu.cn/sjbz/api.php?format=json'
let images = ref(["https://picsum.photos/800/600"]);

async function getImage() {
    //    let response=await axios.get("https://api.btstu.cn/sjbz/api.php?format=json");
    //    let josn=response.data;
    //    console.log(josn)

    const res = await axios.get('https://httpbin.org/image/png', {
        responseType: 'blob'
    })
    const url = URL.createObjectURL(res.data)
    console.log('图片blob地址:', url)
    images.value.push(url);

}



</script>

<style></style>

11.2:使用hook之后

新建userCount.ts和userImg.ts,做到代码复用

TypeScript 复制代码
import { ref } from "vue";

//默认导出
export default function () {
  //数据
  let num = ref(0);
  //方法
  function add() {
    num.value++;
  }
  //返回值
  return { num, add };
}


import { ref } from "vue";

//默认导出
export default function () {
  //数据
  let num = ref(0);
  //方法
  function add() {
    num.value++;
  }
  //返回值
  return { num, add };
}



<template>
    <div>
        <h1>不使用hooks</h1>
        <h1>数字{{ num }}</h1>
        <button @click="add">计数器+1</button>


        <div>
            <img v-for="item in images" :key="item" :src="item" alt="加载失败">
            <button @click="getImage">添加图片</button>
        </div>
    </div>



</template>

<script lang="ts" setup>
import useCount from '../hooks/useCount';
import userImg from '../hooks/userImg';

//调用钩子函数
const { num, add } = useCount();
const { images, getImage } = userImg()

</script>

<style></style>
相关推荐
界面开发小八哥1 小时前
界面控件DevExtreme v26.1新版亮点——支持Angular 22
前端·javascript·angular.js·devexpress·ui开发·devextreme
Getflare1 小时前
前端 + UI 设计 + AI:这不是三个工种,是一个新三角能力模型(附自检清单)
前端·人工智能·ui
oil欧哟1 小时前
我做了一个 Vibe Coding 术语学习站:VibeHub
前端·ai·agent·独立开发·vibe coding
审小匠OpenCPAi2 小时前
银行流水核查怎么自动化?单边匹配、双向勾稽与图聚类异常检测的工程对比
java·前端·人工智能·python·审计
Revolution612 小时前
一个公共表格组件,是怎么一步步失控的
前端·前端工程化
mONESY2 小时前
React useState 核心原理与最佳实践:从异步更新到性能优化全解
javascript
腻害兔2 小时前
【若依项目-产品经理视角】RuoYi-Vue-Pro 源码拆解:CRM 客户关系模块深度解析——从线索到回款,一套完整的 B2B 销售闭环是怎么搭的?
java·前端·javascript·vue.js·产品经理·ai编程
whyfail2 小时前
前端学 Spring Boot(2):一次点击,如何穿过整个后端?
前端·spring boot·后端
AI多Agent协作实战派3 小时前
AI多Agent协作系统实战(二十三):Agent读HEARTBEAT.md不读AGENTS.md——openclaw的文件加载之谜
前端·数据库·人工智能·uni-app