您好,欢迎来到三六零分类信息网!老站,搜索引擎当天收录,欢迎发信息
免费发信息

如何快速上手vue3,学会这几个API吧!

2024/4/27 22:27:39发布5次查看
如何快速上手vue3?本篇文章给大家分享几个api,学会这几个api,vue3可以直接上手,其他的在慢慢去了解,希望对大家有所帮助!
vue2开发过项目的,想直接上手vue3很快,几个api熟悉了就够了,其它的特性在使用vue3的过程慢慢去了解。任何在熟悉了使用之后再去研究一些api的原理,慢慢就能把vue3掌握。
而且vue3的使用结合ts,开发过程中ts的比重没有那么大,之前分享的ts那些基础会了,完全就够用来开发了。【相关推荐:vuejs视频教程】
全局 api 和应用 api
vue3的一个新概念,返回一个提供应用上下文的应用实例,应用实例挂载的整个组件树共享同一个上下文:
const app = createapp(app);app.use(store).use(router).mount("#app");
vue2:
new vue({ router, store, render: (h) => h(app),}).$mount("#app");
然后以前用vue.的那些api都变成用这个应用实例app.:
vue2vue3
vue.component app.component
app.config app.config
app.directive app.directive
app.mixin app.mixin
app.use app.use
其它api像nexttick、h等都是直接从vue结构出来使用:
import { createapp, h, nexttick } from 'vue'
composition api
tipsvue3中不再使用thisvue3组件不需要根标签,但是会有警告extraneous non-props attributes推荐使用单文件组件,后面的实现代码都是单文件组件方式setup这个可太重要了,vue3把这个函数当作了入口点。接收两个参数props和context。函数会在beforecreate、created之前执行,可以说取代了beforecreate、created成为新的生命周期。新增的composition api都写在setup函数中。
props就是vue2的props,context则提供attrs、slots、emit等。通过return一个对象,把响应式数据暴露给template,相当于vue2的data,不同的是函数也是这样暴露给template:
<template> <div class="hello"> <h1>{{ msg }}</h1> <h1 @click="test">{{ isref }}</h1> </div></template><script lang="ts">import { definecomponent, ref } from "vue";export default definecomponent({ name: "helloworld", props: { msg: string, }, setup(props) { console.log(props.msg); let isref = ref("is ref"); const test = () => { console.log(isref.value); }; return { isref, test, }; },});</script>
单文件组件vue3还提供了单文件组件(推荐),将setup加到script上,里面的代码就会被编译成setup函数。比较重要的几个点:
顶层的绑定会被暴露给模板声明的顶层的绑定 (包括变量,函数声明,以及 import 引入的内容) 都能在模板中直接使用响应式数据、组件等也可以直接使用:
<template> <div class="hello"> <h1>{{ msg }}</h1> <h1 @click="test">{{ isref }}</h1> </div><mycomponent /></template><script lang="ts" setup>import mycomponent from './mycomponent.vue'import { ref } from "vue";const msg = "msg";const isref = ref("");function test() { console.log(isref.value);}</script>
使用单文件组件,一些属性的使用也要改变,当然也有其它替代的api:
属性对应
props和emits defineprops和defineemits
ref或者$parent defineexpose
slots和attrs useslots和useattrs()
ref接受一个内部值并返回一个响应式且可变的 ref 对象,在setup函数内部访问ref函数需要加.value,如果要加类型,要用泛型,不加则会类型推论,也可以不给初始值,则是any,且是undefined:
const ref1 = ref(1);const ref2 = ref<number>(2);const ref3 = ref1.value;//不是响应式,相当于变量const ref4 = ref();//refs.value是undefinedref2.value = 5;//赋值 读取都要.value
一般来说,ref只会赋值基础数据类型和数组,也可以泛型联合类型如果将对象分配为ref值,则它将被reactive函数处理为深层的响应式对象:
//不建议,内部也是reactive处理const ref1 = ref({ a: 10,});//不确定类型const ref3 = ref<string | number>();ref3.value = 1;ref3.value = "";//数组对象,ts类型声明,用泛型type obj1 = { c: string };type obj2 = { b: string; c: obj1[];};const ref2 = ref<obj2[]>([ { b: "", c: [{ c: "" }], },]);
reactive用来声明响应式的对象,类型通过泛型添加:
type obj = { a: number; b: string;};let obj = reactive<obj>({ a: 10, b: "",});let state = reactive({ a: 10, b: "",});
reactive将会解包所有深层的 refs,同时维持ref的响应性,将ref分配给reactive的property时,ref也会被自动解包。简单说就是ref的值和reactive的值响应式了
const count = ref(1)const obj = reactive({ count })// ref 会被解包console.log(obj.count === count.value) // true// 它会更新 `obj.count`count.value++console.log(count.value) // 2console.log(obj.count) // 2// 它也会更新 `count` refobj.count++console.log(obj.count) // 3console.log(count.value) // 3//跟上面一样效果const count = ref(1)const obj = reactive({})obj.count = countconsole.log(obj.count) // 1console.log(obj.count === count.value) // true
toref为源响应式对象上的某个property新创建一个ref,也就是reactive创建的才可以,会保持对其源 property 的响应式连接:
const state = reactive({ foo: 1, bar: 2})const fooref = toref(state, 'foo')fooref.value++console.log(state.foo) // 2state.foo++console.log(fooref.value) // 3
torefs将响应式对象转换为普通对象,其中结果对象的每个property都是指向原始对象相应property的ref:
const state = reactive({ foo: 1, bar: 2})const stateasrefs = torefs(state)/*stateasrefs 的类型:{ foo: ref<number>, bar: ref<number>}*/// ref 和原始 property 已经“链接”起来了state.foo++console.log(stateasrefs.foo.value) // 2stateasrefs.foo.value++console.log(state.foo) // 3
toref和torefs在对一些响应式对象结构展开会很有用,可以有用的时候看看。
watchwatch接收两个参数,第一个参数可以是有return的函数,也可以是一个ref,第二个参数则跟vue2相同的函数,并且watch可以很多个:
//一般ref不用这种方式let count = ref(0);watch( () => count.value, (val, old) => { console.log(old, val); });//单个ref推荐watch(count, (val, old) => { console.log(old, val);});//监听reactive对象let state = reactive({ count: 0 });//函数参数必须具体到某个值,如果是() => state无效,或者加上{ deep: true }watch( () => state.count, (val, old) => { console.log(old, val); });//加上{ deep: true }watch( () => state, (val, old) => { console.log(old, val); }, { deep: true });//监听整个对象,新旧的值都相同,或者用lodash.clonedeep进行深拷贝//state改成() => _.clonedeep(state)watch(state, (val, old) => { console.log(old.count, val.count);});
也可以同时监听多个,两个参数分别用数组,个人还是建议单个:
const state = reactive({ count: 1 });const count = ref(0);// 监听一个数组watch( [() => state.count, count], ([newstate, newcount], [oldstate, oldcount]) => { console.log("new:", newstate, newcount); console.log("old:", oldstate, oldcount); });
官网一直提到惰性,其实就是是否加immediate: true,加了初始化就会执行。
watcheffect它"立即执行"传入的一个函数,同时响应式追踪其依赖,并在其依赖变更时重新运行该函数:
const state = reactive({ count: 1 });const count = ref(0);watcheffect(() => { if (state.count > 3) { count.value++; }});watcheffect(() => console.log(count.value));
至于watch和watcheffect共享停止侦听,清除副作用 (相应地 oninvalidate 会作为回调的第三个参数传入)、副作用刷新时机和侦听器调试行为后面要仔细研究一下。
computed从vue2开始,就很多人分不清什么时候用computed什么时候用watch,computed主要是用来声明有两个及以上的依赖的数据,也就是说一个变量是根据多个数据进行判断的,用computed,单个的用watch。至于语法的不同就不多说了,vue3的computed常用语法是一个带有return的函数,也可以同时存在多个:
let count = ref(0);let page = ref(0);let pg = computed(() => { return count.value + page.value;});
要注意,computed声明的变量(pg)是不能直接去修改的(只读),跟vue2一样也有get、set函数(可读可写)。
defineprops、defineemits在单文件组件中必须使用defineprops和defineemits api来声明props和emits,可以算是语法糖。父组件还是跟原来一样传值,子组件接收:
//父组件<template> <div class="home"> <input v-model="msg" /> <helloworld :msg="msg" @change="change" /> </div></template><script lang="ts" setup>import { ref } from "vue";import helloworld from "@/components/helloworld.vue";let msg = ref("is parent");const change = (val: string) => { msg.value = val;};</script>//子组件<template> <div>{{ msg }}</div> <button @click="change">emit</button></template><script lang="ts" setup>import { defineprops, defineemits } from "vue";const props = defineprops({ msg: string,});console.log(props.msg);const emit = defineemits(["change"]);const change = () => { emit("change", "is son");};</script>//设置默认值defineprops({ msg: { type: number, default: 100, },});
template可以直接使用msg,要调用的话就得props.msg。
withdefaultsdefineprops只能限制类型,没有提供默认值(这边应该是限定用ts的接口才没有默认值)。为了解决这个问题,提供了 withdefaults 编译器宏:
type porps = { msg: string;};const props = withdefaults(defineprops<porps>(), { msg: "default",});
withdefaults接收两个参数,第一个参数是defineprops加props字段的泛型,第二个字段是默认值,也可以不设置。
也可以监听props:
watch( () => props.msg, (val) => { console.log(val); });
this.$refsvue2很多情况还是需要用到这个api,vue3中比较特别,为了获得对模板内元素或组件实例的引用,我们可以像往常一样声明ref,在渲染上下文中暴露root,并通过ref="root",将其绑定到 div 作为其 ref。在虚拟dom补丁算法中,如果 vnode 的 ref 键对应于渲染上下文中的 ref,则vnode的相应元素或组件实例将被分配给该ref的值。这是在虚拟 dom 挂载/打补丁过程中执行的,因此模板引用只会在初始渲染之后获得赋值。
<button ref="testref">testref</button>let testref = ref(null);onmounted(() => { // dom 元素将在初始渲染后分配给 ref console.log(testref.value); // <button>testref</button>});
nexttick跟vue2一样的使用:
nexttick(() => { console.log(testref.value);});
也可以跟官网提供的一样用async的函数await:
let testref = ref(null);const nexttickfn = async () => { await nexttick(); console.log(testref.value);};nexttickfn();
defineexposevue2有时候会用this.$refs调用子组件的函数或者变量,单文件组件是默认关闭的,所以单文件组件要用defineexpose编译器宏暴露出去:
//父组件<template> <div class="home"> <helloworld ref="sonref" /> </div></template><script lang="ts" setup>import { nexttick, ref } from "vue";import helloworld from "@/components/helloworld.vue";let sonref = ref();nexttick(() => { sonref.value.sonfn(); console.log(sonref.value.sonref);});</script>//子组件let sonref = ref("is son");const sonfn = () => { console.log("is son fn");};defineexpose({ sonfn, sonref });
vue2的this.$parent在单文件组件中,自己是实现了,但是官方没有直接给出代码:
//父组件const parentref = ref("is parent ref");const parentfn = () => { console.log("is parent fn");};defineexpose({ parentref, parentfn,});//子组件let parent = getcurrentinstance();console.log(parent?.parent?.exposed?.parentref.value);parent?.parent?.exposed?.parentfn();
新增组件
teleport官网介绍了很多,这个组件最大的作用就是可以让组件脱离固定的组件位置,可以挂载在逻辑上最优的位置,其它使用都跟组件一样,只有位置改变:
<teleport to="#teleportdiv"> <helloworld /></teleport><teleport to="body"> <helloworld /></teleport>
挂载的元素会从上向下解析,第一个to的元素,标签、class、id等。一般使用也不会随便,都会用id元素或者body。
suspensesuspense是一个试验性的新特性,官方也说生产环境请勿使用。主要是允许将组件异步处理等待过程提升到组件树中处理。
单文件组件里面顶层await里面提到:async setup() 必须与 suspense 组合使用,suspense 目前还是处于实验阶段的特性。我们打算在将来的某个发布版本中开发完成并提供文档。
所以这边就不给出不是单文件组件的代码实现了。
生命周期
生命周期还是跟原来的一样,只是前面都加上了on,destroy都变成了unmount。setup会在beforecreate、created之前执行,取代了beforecreate、created。
beforecreate --> beforecreatecreated --> setupbeforemount --> onbeforemountmounted --> onmountedbeforeupdate --> onbeforeupdateupdated --> onupdatedbeforedestroy --> onbeforeunmountdestroyed --> onunmount使用:
onmounted(() => { console.log("mounted");});
试了一下,居然可以写多个。
vue3新增或者删除了哪些api,其实没必要一下子全部去记住,当一些api使用的时候如果发现不生效了,再去官网查一下,当然,基础的这些api就得记下来。
还是那句话,先学会基础,上手开发,然后慢慢去了解学习不常用的,甚至是源码。
(学习视频分享:vuejs教程、web前端)
以上就是如何快速上手vue3,学会这几个api吧!的详细内容。
该用户其它信息

VIP推荐

免费发布信息,免费发布B2B信息网站平台 - 三六零分类信息网 沪ICP备09012988号-2
企业名录