Vue3快速使用手册

Vue3的创建

npm create vite@latest

1.设置项目名。

2.选择框架。

3.选择支持的语法,默认使用TS。

......

Vue3的使用

setUp(无法直接修改数据,也就是没有响应式)

在vue3中不不再推荐使用选项式编程而是使用组合式编程。

Vue2写法

javascript 复制代码
<template>
  <div>
    <span>姓名:{{name}}</span>
    <br>
    <span>年龄:{{age}}</span>
    <br>
    <button @click="setName()">修改名字</button>
    <button @click="addAge()">年龄+1</button>
  </div>
</template>

<script lang="ts">
export default {
    name: 'Person',
    data() {
        return {
            name: 'tolen',
            age: 18
        }
    },
    methods: {
        setName() {
            this.name = 'ostkaka'
        },
        addAge() {
            this.age++;
        }
    },
}
</script>

Vue3写法

javascript 复制代码
<template>
  <div>
    <span>姓名:{{name}}</span>
    <br>
    <span>年龄:{{age}}</span>
    <br>
    <button @click="setName()">修改名字</button>
    <button @click="addAge()">年龄+1</button>
  </div>
</template>

<script lang="ts">
export default {
    name: 'Person',
    setup() {
        //变量
        let name = 'tolen';
        let age = 18;

        //函数
        function setName() {
            name = 'ostkaka'
        }
        function addAge() {
            age++;
        }
        return {name, age, setName, addAge}
    }
}
</script>

如果data函数和setup中设置的变量名相互冲突的时候会优先读取setup中的数据。

但是每次都需要return对应的数据,写起来非常的麻烦,所以我们可以将setup单独写一个script。

javascript 复制代码
<template>
  <div>
    <span>姓名:{{name}}</span>
    <br>
    <span>年龄:{{age}}</span>
    <br>
    <button @click="setName()">修改名字</button>
    <button @click="addAge()">年龄+1</button>
  </div>
</template>

<!-- 如果没有主键名字的要求,我们甚至可以将此script省略掉 -->
<script lang="ts">
export default {
    name: 'Person',
}

</script>

<script lang="ts" setup>
    //变量
    let name = 'tolen';
        let age = 18;

        //函数
        function setName() {
            name = 'ostkaka'
        }
        function addAge() {
            age++;
        }
</script>

ref(用于定义响应式的基本数据,也可以定义对象,但是无法保证嵌套响应)

在我们需要保证响应式的数据赋值上使用ref函数,并且操作其中的vlaue属性,主要就是对value进行操作。

javascript 复制代码
<script lang="ts" setup>
    import { ref } from 'vue'
    //变量,使用ref函数包裹
    let name = ref('tolen');
        let age = ref(18);
        //函数,主要做到响应式的效果就是使用ref中的value属性
        function setName() {
            name.value = 'ostkaka'
        }
        function addAge() {
            age.value++;
        }
</script>

reactive(用于定义响应式的对象)

在我们需要保证对象嵌套式的相应的时候我们就可以使用reactive。

javascript 复制代码
<template>
  <div>
    <span>车牌:{{car.name}}</span>
    <br>
    <span>价格:{{car.cost}}</span>
    <br>
    <button @click="setName()">修改名字</button>
    <button @click="addAge()">加价</button>
  </div>
</template>

<!-- 如果没有主键名字的要求,我们甚至可以将此script省略掉 -->
<script lang="ts">
export default {
    name: 'car',
}

</script>

<script lang="ts" setup>
    import {reactive } from 'vue'
    //对象
    let car = reactive({
      name:'BYD',
      cost: 2000000
    });
        //函数
        function setName() {
            car.name = 'ostkaka'
        }
        function addAge() {
            car.cost+=10000;
        }
</script>

当要使用响应式对象赋值的时候,我们需要使用toRefs函数来将对象中键值赋值为响应式的数据。

我们每次使用ref中数据的时候都需要添加 .value,写起来非常的麻烦,所以我们可以配置插件进行修改。

computed

编写计算属性,且计算属性是只读的,不同于普通的属性。

javascript 复制代码
<template>
  <div>
    性:<input v-model="firstName"/>
    <br>
    名:<input v-model="secondName"/>
    <br>
    名字:<span>{{name}}</span>
    <button @click="change()">修改名字</button>
  </div>
</template>

<!-- 如果没有主键名字的要求,我们甚至可以将此script省略掉 -->
<script lang="ts">
export default {
    name: 'car',
}

</script>

<script lang="ts" setup>
    import {ref, computed} from 'vue'
    let firstName=ref("to");
    let secondName=ref("len");
    let name = computed({
      set(val) {
        const[str1, str2] =  val.split('-');
        firstName.value = str1;
        secondName.value = str2;
      },
      get() {
          return firstName.value + secondName.value;
      }
    });
    let change = function() {
      name.value = "ost-kaka";
    }

</script>

在Vue3中主要就是引入computed函数,通这个函数来创建属性,并且在该函数中主要就是编写 set(修改属性)和get(获取属性)函数。

watch

watch是一个监听函数,我们且有三个参数:数据源,回调函数,监听配置。

watch的数据源只能是: ref,reactive,对象,gatter函数(返回一个数据)。

例子

javascript 复制代码
<template>
  <div>
    名字:<span>{{name}}</span>
    <br>
    年龄:<span>{{age}}</span>
    <br>
    <button @click="changeName">修改名字</button>
    <button @click="changeAge">修改年龄</button>
  </div>
</template>

<!-- 如果没有主键名字的要求,我们甚至可以将此script省略掉 -->
<script lang="ts">
export default {
    name: 'car',
}

</script>

<script lang="ts" setup>
    import {ref, watch} from 'vue'
    let name = ref("tolen");
    let age = ref(18);
    let changeName = function() {
      name.value +='~';
    }
    let changeAge = function() {
      age.value++;
    }
    watch(name, function() {
      if(name.value != "ostkaka") {
        console.log(name.value);
      }
    })

</script>

暂停监听

javascript 复制代码
//返回值就是暂停函数,通过对应的条件调用暂停函数
let stop = watch(() => person.value.name, function() {
        //编写对应的回调函数
        if(1==1) {
          stop();
        }
    })

特殊情况

1.数据源是ref的话,直接使用ref就可以,不需要添加.value。

2.数据源是ref定义的对象的话,其默认是不支持深度监听的,所以需要在watch配置中添加deep:true。

javascript 复制代码
    watch(name, function() {
      if(name.value != "ostkaka") {
        console.log(name.value);
      }
    },{deep:true})

3.数据源是reactive定义的话,其是默认开启深度监听的。

4.监听ref或reactive定义的对象中某个属性的时,如果属性是基本类型的话使用getter函数,如果是对象类型的话,可以直接监听,但是还是推荐使用getter函数,是可以在做对象属性监听的时候都使用getter函数进行编写。

javascript 复制代码
//person.value.name对应ref中对象的属性
watch(() => person.value.name, function() {
        //编写对应的回调函数
    })

5.如果需要监听多个数据源的话,直接使用数组进行收集。

当我们需要自动去监听某些数据源的时候,我们就可以使用watchEffect,而watch需要我们手动的指出需要监听的数据源。

javascript 复制代码
<template>
  <div>
    名字:<span>{{name}}</span>
    <br>
    年龄:<span>{{age}}</span>
    <br>
    <button @click="changeName">修改名字</button>
    <button @click="changeAge">修改年龄</button>
  </div>
</template>

<!-- 如果没有主键名字的要求,我们甚至可以将此script省略掉 -->
<script lang="ts">
export default {
    name: 'car',
}

</script>

<script lang="ts" setup>
    import {ref, watchEffect} from 'vue'
    let name = ref("tolen");
    let age = ref(18);
    let changeName = function() {
      name.value +='~';
    }
    let changeAge = function() {
      age.value++;
    }
    watchEffect(function() {
        console.log(name.value)
    })

</script>

标签中的ref属性

如果使用标签中的id作为唯一标识的话,在不同的组件之间就会有冲突的风险。使用使用ref作为容器用于间隔。

javascript 复制代码
<template>
  <div>
    名字:<span ref="person">{{name}}</span>
  </div>
</template>

<script lang="ts">
export default {
    name: 'car',
}

</script>

<script lang="ts" setup>
//且person中的值就是该标签的数据。
    let person  = ref();

</script>

如果ref加在html标签上,则其数据就是标签数据,如果ref加在主键标签上,则其数据就是主键数据。

ts类型规范

自定义接口

javascript 复制代码
//对应的自定义类型
export interface Person {
    name: string,
    age: number,
}

//标识对应类型的数组形式
export type Persons = Array<Person>

在vue中进行使用

javascript 复制代码
<script lang="ts" setup>
    import {Persons, type Person} from '../types/index'
    let ren:Person = {name:'tolen', age: 18};
    let rens:Persons = [
    {name:'tolen', age: 18},
    {name:'tolen', age: 18},
    {name:'tolen', age: 18}
    ];
</script>

props

使用defineProps函数进行参数的传递。

//父组件传入对应的list集合

<template>
  <div>
   <ul>
    <li v-for="item in list" :key="item.age">
      {{item.name}} -- {{item.age}}
    </li>
   </ul>
  </div>
</template>

<!-- 如果没有主键名字的要求,我们甚至可以将此script省略掉 -->
<script lang="ts">
export default {
    name: 'car',
}

</script>

<script lang="ts" setup>
    import {defineProps} from 'vue';
    defineProps(['list']);
    
</script>

将接口写入泛型就可以指定对应类型的数据。

javascript 复制代码
<script lang="ts" setup>
    import {Persons } from '../types';
    import {defineProps} from 'vue';
    defineProps<{list?:Persons}>();
    
</script>

使用withDefaults,设置默认的数据。且需要是个函数返回对应的数据。

javascript 复制代码
<script lang="ts" setup>
    import {Persons } from '../types';
    import {defineProps, withDefaults} from 'vue';
    // defineProps<{list?:Persons}>();
    withDefaults(defineProps<{list?:Persons}>(), {
      list: () => [{name: 'ostkaka', age: 45}]
    });
    
</script>

Vue的生命周期

1.创建:setUp中的代码就是创建时需要执行的代码。

2.挂载前/挂载:使用onBeforeMount和onMounted。

javascript 复制代码
    //挂载前
    onBeforeMount(() => console.log("挂载前"));
    //完成挂载
    onMounted(() => console.log("完成挂载"));

3.更新前/更新:使用onBeforeUpdated和onUpdated。

javascript 复制代码
    //更新前
    onBeforeUpdate(() => console.log("更新前"));
    //更新完成
    onUpdated(() => console.log("更新"));

4.卸载前/卸载:使用onBeforeUnmount和onUnmounted

javascript 复制代码
    //卸载前
    onBeforeUnmount(() => console.log("卸载前"));
    //卸载完成
    onUnmounted(() => console.log("卸载完成"));

hooks

将相同模块的代码放在同个ts文件中,进行统一的维护。

集中的ts文件

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

export default function() {
    let num = ref(50);

    let add = function() {
        return num.value += 10;
    }
    //返回数据可以存在多个
    return {num, add};
}

在主键中使用

javascript 复制代码
<script lang="ts" setup>
    import useradd from '../hooks/useAdd'
    const {num,add} = useradd();
</script>

路由

安装路由

TypeScript 复制代码
npm i vue-router

创建router文件/index.ts,创建路由规则。(使用history的工作模式,也可以使用哈希模式(就是路径中带#))

TypeScript 复制代码
import {createRouter, createWebHistory} from "vue-router";

import blog from '../page/blog.vue'
import user from '../page/user.vue'

const router = createRouter({
//使用history的工作模式,也可以使用哈希模式(就是路径中带#)
    history: createWebHistory(),
    routes:[
        {   name: 'blog'
            path:'/blog',
            component: blog
        },
        {   
            name: 'user',
            path:'/user',
            component: user
        }
    ]
})

export default router

在main.ts中使用router。

TypeScript 复制代码
import { createApp } from 'vue'
import './style.css'
import App from './App.vue'
import router from './router'

let app = createApp(App);
app.use(router);
app.mount('#app');

使用router-link标签进行跳转(可以使用字符串,也可以使用 对象形式,对象中可以使用name和path来指定路由),使用router-view指定渲染vue主键的位置。

App.vue例子

TypeScript 复制代码
<script setup lang="ts">

</script>

<template>
  <router-link to="/blog">博客区</router-link> <span>||</span>
  <router-link to="/user">用户区</router-link>
  <hr>
  <router-view></router-view>
</template>

测试结果

如果在子页面中还要展示其他的小页面的话,就可以使用子路由,使用参数 children。

路由传递参数

在router-Link中的to属性可以传入query/params参数。

javascript 复制代码
 <router-link :to="
  {
    name: 'blog',
    query/params: {
      name: 'ostkaka',
      age: 13
    }
  }
  ">博客区</router-link>

在对应的组件上使用useRoute函数进行接收。

javascript 复制代码
import {useRoute} from 'vue-router'
  let route = useRoute();
 // route.query / route.param

可以使用restful风格,在路由配置中编写路径格式,必须使用name进行配置。(如果某个参数非一定存在的话就在其后加`?`)

在对应的组件上使用useRoute.params进行接收。

编程式路由导航

使用route-Link是在template中进行编写的,如果需要在script中编写的话,我们需要使用useRouter进行编写。useRouter.push函数跳转到对应的路径。(运用场景:定时跳转,划过跳转,等等,在script编程)

重定向

将一个路径直接重定向到另一个路径上。

pinia

作用:集中管理数据。

安装

npm i pania

在main.t中引入并使用pinia。

TypeScript 复制代码
import { createApp } from 'vue'
import App from './App.vue'
import {createPinia} from 'pinia'

let app = createApp(App);
//创建pinia
const pinia = createPinia();
//使用pinia
app.use(pinia);
app.mount('#app');

存储数据:创建文件夹 /store,并创建对应模块的文件,在state中编写对应的数据。

TypeScript 复制代码
import {defineStore} from 'pinia'

export const useAddStore = defineStore('add', {
    state() {
        return {
            sum: 1,
            size: 1
        }
    }
})

修改数据

1.直接修改。

TypeScript 复制代码
<script setup lang="ts">
    import {useAddStore} from '../store/add'
    
    let addStore = useAddStore();
    console.log(addStore);
    let add = function () {
       addStore.sum += addStore.size;
    }
    let minus = function () {
        addStore.sum -= addStore.size;
    }
</script>

2.使用$patch函数。

TypeScript 复制代码
<script setup lang="ts">
    import {useAddStore} from '../store/add'
    
    let addStore = useAddStore();
    //修改对应对应的属性
    addStore.$patch({
        sum: 100,
        size: 2
    })
    
</script>

3.通过action属性进行修改。

TypeScript 复制代码
import {defineStore} from 'pinia'

export const useAddStore = defineStore('add', {
    actions: {
        add(sum, size) {
            this.sum = sum;
            this.size = size;
        }
    },
    state() {
        return {
            sum: 1,
            size: 1
        }
    }
})

在对应的组件中直接调用此函数即可修改。

storeToRefs的使用

如果需要使用store中的数据时为了不破坏响应式,我们就可以使用storeToRefs来保证数据的响应式。(storeToRefs('store'))

组件通信

1.使用自定义事件(子传父常使用)

在传递者进行 定义事件和触发事件

TypeScript 复制代码
<script setup lang="ts">
    import{onMounted} from 'vue'
    //声明事件
    const emit = defineEmits(['send-toy']);
    onMounted(() => {
        emit('send-toy', 'ostkaka');
    })
</script>

获得数据者进行 事件的绑定

javascript 复制代码
<script setup lang="ts">
  import Add from './components/Add.vue' 
  import Love from './components/Love.vue'
  
  let saveToy = function(value:any) {
    console.log('@', value);
  }
</script>

<template>
  <Add @send-toy="saveToy"/>
  <hr>
  <Love/>
</template>

2.使用mitt组件(任意主件间通信)

下载mitt

javascript 复制代码
npm i mitt

创建mitt工具包

TypeScript 复制代码
//引入mitt
import mitt from 'mitt'

const emitter = mitt()

export default emitter

在需要进行通信的组件中进行引入

在获取数据的组件中使用emitter.on进行事件的绑定

TypeScript 复制代码
<script setup lang="ts">
  import emitter from './utils/emitter'
  
  //绑定事件
  emitter.on('send-toy', (value:any) => {
    console.log("@", value)
  })

</script>

在传递数据的组件中使用emitter.emit进行事件的触发

TypeScript 复制代码
<script setup lang="ts">
    import emitter from '../utils/emitter'
    // 触发事件
    emitter.emit('send-toy', 'ostkaka')
    
</script>

3.使用provide和inject实现爷孙数据传递

在上级处使用provide函数来传递数据给子级。

javascript 复制代码
<script setup lang="ts">
  import { provide, ref } from 'vue'

  let money = ref(100);
  //向自己的子孙通过数据
  provide('money', money);

</script>

在子级处使用inject函数来接收上级的数据。

javascript 复制代码
<script setup lang="ts">
    import { inject } from 'vue';

    //使用上级的数据,第二个参数为默认数据
    let money = inject('money', 1);
    
</script>

最终实现上级向子级数据的传递。

插槽

1.默认插槽

在对应的组件中编写插槽位置。

javascript 复制代码
<template>
    <slot></slot>
</template>

<script lang="ts">
    export default {
        name: 'Add'
    }
</script>

<script setup lang="ts">
    
</script>

在调用处使用。

javascript 复制代码
<template>
  <Add>
    <span>你好</span>
  </Add>
</template>

2.具名插槽

指定标签存放在对应的插槽上。

javascript 复制代码
<template>
    <slot name="s1"></slot>
    <slot name="s2"></slot>
</template>

<script lang="ts">
    export default {
        name: 'Add'
    }
</script>

<script setup lang="ts">
    
</script>

使用标签填充插槽。

javascript 复制代码
<template>
  <Add>
    <template v-slot:s1>
      <span>你好</span>
    </template>
    <template #s2>
      <span>ostkaka</span>
    </template>
  </Add>
</template>

可以使用 # 代替 v-slot: 指定插槽。

3.作用域插槽

当插槽的组件的数据需要传递到调用者时就可以使用此插槽。

javascript 复制代码
<template>
    <slot name="s1" :userName="name"></slot>
</template>

<script lang="ts">
    export default {
        name: 'Add'
    }
</script>

<script setup lang="ts">
    import { ref } from 'vue';
    let name = ref('ostkaka');
</script>

调用者使用传来的数据。

javascript 复制代码
<script setup lang="ts">
  import Add from './components/Add.vue' 
</script>

<template>
  <Add>
    <template v-slot:s1="value">
      <span>你好</span>
      <span>{{value.userName}}</span>
    </template>
  </Add>
</template>
相关推荐
LCG元3 小时前
Vue.js组件开发-使用vue-pdf显示PDF
vue.js
哥谭居民00014 小时前
将一个组件的propName属性与父组件中的variable变量进行双向绑定的vue3(组件传值)
javascript·vue.js·typescript·npm·node.js·css3
烟波人长安吖~5 小时前
【目标跟踪+人流计数+人流热图(Web界面)】基于YOLOV11+Vue+SpringBoot+Flask+MySQL
vue.js·pytorch·spring boot·深度学习·yolo·目标跟踪
PleaSure乐事5 小时前
使用Vue的props进行组件传递校验时出现 Extraneous non-props attributes的解决方案
vue.js
土豆炒马铃薯。6 小时前
【Vue】前端使用node.js对数据库直接进行CRUD操作
前端·javascript·vue.js·node.js·html5
赵大仁7 小时前
深入解析 Vue 3 的核心原理
前端·javascript·vue.js·react.js·ecmascript
bidepanm7 小时前
Vue.use()和Vue.component()
前端·javascript·vue.js
Ashore_9 小时前
从简单封装到数据响应:Vue如何引领开发新模式❓❗️
前端·vue.js
顽疲9 小时前
从零用java实现 小红书 springboot vue uniapp (6)用户登录鉴权及发布笔记
java·vue.js·spring boot·uni-app
&活在当下&9 小时前
ref 和 reactive 的用法和区别
前端·javascript·vue.js