在将v3版的变化之前我们先来回顾一下v2版本的函数式组件,它有两种创建方式:functional
attribute 和 { functional : true }
选项,代码分别如下
// attribute 方式
// 选项方式
export default = {
functional:true,
props:{
…
},
render:function(createElement,context){
…
/**
context传递了一些参数:
props,slots,parent,listeners,injections
**/
}
}
v2版本中组件有两种组件类型:有状态组件和函数式组件(无状态组件),相对于有状态组件,函数式组件不需要被实例化,无状态,没有生命周期钩子,它们的渲染速度远高于有状态组件。往往通常被适用于功能单一的静态展示组件从而优化性能。除此之外,函数式组件还有返回多个根节点的能力。
在v3版本中,有状态组件和函数式组件之间的性能差异已经大大减少,在大部分场景下几乎可以忽略不计。所以函数式组件唯一的优势就在一返回多节点的能力,但这种通常运用比较少,且组件往往比较简单,具体语法糖如下:
// 函数创建
import { h } from ‘vue’
const DynamicHeading = (props, context) => {
// context是一个包含 attrs,slots,emit的对象
return h(h${props.level}
, context.attrs, context.slots)
}
DynamicHeading.props = [‘level’]
export default DynamicHeading
// 单文件组件(SFC)
<component
v-bind:is=“h${$props.level}
”
v-bind=“$attrs”
/>
- 全局API调整
v3版本中新增了一个新的全局APIcreateApp
,通过ES模块的方式引入。调用createApp
返回一个应用实例,该应用实例暴露出来全局API,这是Vue3的新概念,主要解决了不同"app"之间能够共享资源(配置,全局组件,指令等等)。我们来对比一下v3和v2分别创建应用的改变。
// v2 创建
import Vue from ‘vue’
import App from ‘./App.vue’
Vue.config.productionTip = false
new Vue({
render: h => h(App),
}).$mount(‘#app’)
// v3 创建
import { createApp } from ‘vue’
import App from ‘./App.vue’
var app = createApp(App);
app.mount(‘#app’)
在"app"之间共享配置的一种方式是工厂模式:
import { createApp } from ‘vue’
import App1 from ‘./App1.vue’
import App2 from ‘./App2.vue’
const createMyApp = options => {
const app = createApp(options)
app.directive(‘focus’ /* … */)
return app
}
createMyApp(App1).mount(‘#foo’)
createMyApp(App2).mount(‘#bar’)
v3将可以全局改变Vue行为的API从原来的Vue构造函数上转移到了实例上了。列表如下
除此之外,还有一些全局API和内部组件都做了重构,考虑到tree-shaking,只能通过ES模块的方式导入,意味着当你的应用程序中没用到的组件和接口都不会被打包。受影响的API列表如下:
-
Vue.nextTick
-
Vue.observable (用 Vue.reactive 替换)
-
Vue.version
-
Vue.compile (仅全构建)
-
Vue.set (仅兼容构建)
-
Vue.delete (仅兼容构建)
// 错误使用
import Vue from ‘vue’
Vue.nextTick(() => {
// 一些和DOM有关的东西
})
// 正确使用
import { nextTick } from ‘vue’
nextTick(() => {
// 一些和DOM有关的东西
})
- 组合式API
重头戏!!!
这是v3中的新概念,vue给我们提供了一些新的api,这些新的api在一个地方使用,而这个地方就是vue给我们新提供了一个从组件初始化到销毁的过程中我们能够做一些事情的地方,我将之理解为钩子函数——Setup
,在Setup里,你可以做原本你能在vue组件里面能做的所有事情,比如你在created
,mounted
,computed
,watch
,methods
里面做的所有事情,都能在Setup
里面完成,那要怎么才能做到呢,就是要通过vue提供的那些新的API。那这个东西主要解决什么事情呢?我们都知道组件的作用就是对功能的提取以及代码的复用。这使得我们的程序在灵活性和可维护性上能走的更远,但是这还不够,当一个组件内部的逻辑很复杂的时候,我们将逻辑分别散落在 created
,mounted
,methods
,computed
,watch
里面,然后整个文件代码长达好几百行。这对于没有编写这个组件的人来说,尝试去理解这些逻辑代码无疑是最头疼的事情。而Setup
正是解决了这个事情,将所有的逻辑都集中起来在Setup
中处理。从今以后,当你想制造一辆汽车的时候,你再也不用去全世界进口各种零件,你在Setup
工厂中就能完成。让我们来见识一下Setup
和那些新的API
的使用以及作用(听说这种东西才被称之为干货???):
Setup
如果你听懂了我上面所说的,那我开局这么写你应该也能理解了:
// 当运行起来打印了run
Setup
可以返回一个对象,你可以在组件的其他地方访问这个对象中的属性。
“
注意:在执行
Setup
的时候尚未创建组件实例,所以在Setup
中没有this
。不过它提供了两个接收参数——props
和context
。在Setup
中无法访问组件中其他的任何属性。
”
// 调用Demo组件
// Demo 组件
我们会发现试图并没有更新,我们发现setup
返回的对象不是响应式的,响应式我们应该不陌生,在data()选项中的property都是响应式的,那是应为Vue在组件初始化的过程中就已经对data()中的property创建了依赖关系。所以当property发生变化时,视图即会自动更新,这就是响应式。那怎么让它变成响应式的呢?
ref & reactive
我们可以通过ref
,reactive
创建响应式状态,
我们使用ref
可以创建基础数据类型和复杂数据类型的响应式状态,使用reactive
只能创建复杂数据类型的响应式状态,如果使用创建数据类型不正确,控制台会给出对应的警告value cannot be made reactive: **
。那ref
和reactive
的区别到底在哪里呢?
const refNum = ref(10);
const refObj = ref({
name:‘jac’,
age:20
});
const reactiveNum = reactive(10);
const reactiveObj = reactive({
name: ‘jac’,
age: 20
})
console.log(‘refNum’,refNum);
console.log(‘refObj’,refObj);
console.log(‘reactiveNum’, reactiveNum);
console.log(‘reactiveObj’, reactiveObj);
结果如下:
当ref
创建的是复杂数据类型的时候内部其实也是用reactive创建的。所以ref
也是可以创建复杂数据类型的响应状态的,只是在setup
中写法会有所不同。
setup(){
const refObj = ref({
name:‘jac’,
age:20
});
const reactiveObj = reactive({
name: ‘jac’,
age: 20
})
// ref 方式的更新
const changeRefObj = () => {
refObj.value.name=“mac”
}
// reactive 方式的更新
const changeReactiveObj = () => {
reactiveObj.name = ‘mac’
}
return {
…
}
}
“
注意:通过
ref
对值进行了包裹,在Setup
中你需要使用变量.value的方式进行访问和设置值,从Setup
中暴露出去的对象你可以直接通过this.变量访问。
”
…
小伙伴可以根据自己的编码习惯选择运用。
toRef & toRefs
有时候我们想通过解构的方式从一个复杂的响应式变量中剥离出一些变量时,我们的代码可能是这样的:
<button @click=“changeObj”>my name is {{info.name}}
这样会使我们解构出来的两个property失去响应性,这个时候我们需要使用toRef
和toRefs
从中解构出来,toRef
用于解构出单个property的响应式变量,toRefs
是将源对象中所有property都创建响应式变量,在通过解构的方式创建我们对应的变量。
<button @click=“changeObj”>my name is {{info.name}}
watch & computed & 注册生命周期钩子
在Setup
中我们还能watch
属性,创建独立的computed
,还可以注册各种生命周期钩子,由于Setup
执行的阶段是围绕beforeCreate
和created
和进行的,所以原本在这两个生命周期中做的事情都能够放在Setup
中处理。
…
// 输出结果如下:
我首先执行
created执行了
onMounted也执行了,结果输出如下
0
总计数:1
mounted执行了
看的出来,Setup
中注册的生命周期钩子函数要比外面注册的钩子函数先执行!
provide & inject
最后
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长,自己不成体系的自学效果低效漫长且无助。
因此收集整理了一份《2024年Web前端开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点!不论你是刚入门Android开发的新手,还是希望在技术上不断提升的资深开发者,这些资料都将为你打开新的学习之门!
如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
created() {
console.log(‘created执行了’);
},
mounted() {
console.log(‘mounted执行了’);
},
}
// 输出结果如下:
我首先执行
created执行了
onMounted也执行了,结果输出如下
0
总计数:1
mounted执行了
看的出来,Setup
中注册的生命周期钩子函数要比外面注册的钩子函数先执行!
provide & inject
最后
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长,自己不成体系的自学效果低效漫长且无助。
因此收集整理了一份《2024年Web前端开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
[外链图片转存中…(img-NczDGugX-1715673924196)]
[外链图片转存中…(img-jTd2ubUB-1715673924197)]
[外链图片转存中…(img-jmXO9SrF-1715673924197)]
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点!不论你是刚入门Android开发的新手,还是希望在技术上不断提升的资深开发者,这些资料都将为你打开新的学习之门!
如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!