掘金的第一篇文章献给vue3.0,html
vue3.0的正式版发布有必定的时间了,忙于其余,虽然好奇但没有进行比较和学习,终于不负本身“指望”,打败了“懒惰”,学习相关熟悉的技术新版本,其实入手仍是比较简单的(坐等打脸),本文主要是笔者本身在学习过程当中的探索;vue
最大的感觉,组合api是将具备独立功能的函数封装组合在一块儿,提升复用性; 后来实际封装了相关功能,变量较多的状况下,设计高内聚的功能是很是必要的react
分别用vue2.x以及vue3.x进行了学生列表和老师列表的展现,其代码功能分部图以下图所示es6
vue2.x 学生和老师展现代码功能图
api
vue 3.x! 学生和老师展现代码功能图 其中不一样颜色表示页面中两个功能的代码分布;markdown
根据颜色而言,其实vue2.x的功能相对而言是比较分散的,而vue3.0中的功能和数据定义能够定义在一个函数中,功能比较集中;所以在进行组合性api的是时候是须要思考如何设计是比较合理的;vue3.x在功能上可以实现高度的一个复用,想到vue.mixin
的方法,实现代码的复用;数据结构
响应式数据是实现mvvm很是重要的一个部分,在vue3.x中,在支持data
方式定义响应式的数据外,还提供不少可自定义的api;app
在响应式的数据中值得注意的部分 深层次响应仍是浅层次响应;dom
定义响应式数据的一种方式,经过
Proxy
包装传入的变量,借助Proxy提供的set和get方法,实现响应式数据的逻辑异步
setup(props) {
let state =reactive({
msg:{
name:'mafe',
age:24,
},
time: new Date(), //只能进行 赋值更新
list:[
{name:'mfy'},
{name:'mfy1'},
{name:'mfy2'},
]
})
function changeName(){
//定义的是对象可以直接修改赋值
state.msg.name = '333'
//没法更改state中time的赋值对象
// state.time.setDate(state.time.getDate()+1)
let newDate =new Date(state.time.getTime())
newDate.setDate(state.time.getDate()+1)
state.time = newDate ;//不是对象类型 只能修改数据内容
}
return {
state,
changeName
}
}
复制代码
state.time = XXX
赋值的方式进行更改;new Date()
进行赋值,获得的time的原型并不是是Date的,再次修改time的值的时候不能经过setDate
赋值;Proxy
的代理,用于页面的响应式数据构建;也是定义响应式数据的一种,一般用来定义基础类型数据,以及获取dom元素的内容
reactive
一般用于定义对象,在咱们实际的使用过程当中是很是不便捷的,咱们仅仅是想要某个变量实现响应式,ref
是对简单的值进行监听;
ref
的本质仍是reactive
,系统会自动根据咱们传入的值转换成ref(xxx)->reactive({value:xx})
setup(props) {
// 传递一个值
let age = ref(33);
function changeAge(){
age.value +=1;
}
return{
age,
changeAge
}
}
复制代码
ref 定义的内容:
ref定义对象类型时候更新问题 ref定义的对象类型,若是是只想更改某一层的变化 须要调用triggerRef进行触发更新
// 只想更改ref中某一层的变化
msg.value.a = 'myy'
//增长triggerRef 引发视图的更新
// Vue3 只提供了triggerRef 没有提供reactRef相关的
triggerRef(msg)
复制代码
若是参数为 ref
,则返回内部值,不然返回参数自己。这是 val = isRef(val) ? val.value : val
。
let age = ref(33);
console.log(age)
console.log(unref(age))
复制代码
ref
类型的数据,vue会自动帮咱们计算.valuereactive
类型的数据,vue不会自动帮咱们计算.value.value
的Vue在解析数据以前,会自动判断这个数据是不是ref类型的,若是是,则自动添加上.value
,若是不是,则不会自动添加
ref
类型的__v_isRef
来进行判断的,true
,那么就表明是一个ref
类型的数据console.log("判断是不是ref类型数据",isRef(age))
console.log("判断是不是isReactive类型数据",isReactive(age))
复制代码
不管是ref仍是reactive的都是递归监听的过程,也就是不管咱们嵌套了多少层级,其每一层的每一个数据都会发生监听;
let state= reactive({
a:'2',
gf:{
b:'b',
f:'c',
c:{
a:3
}
}
})
// 多个层级 每一个层级内容改变的时候,都会改变;
function changeValue(){
console.log(state)
console.log(state.gf)
}
复制代码
打印后能够发如今reactive中定义的对象,发现对象中的每一层对象都是经过Proxy进行代理
let msg = ref({
a:'2',
gf:{
b:'b',
f:'c',
c:{
a:3
}
}
})
function changeRef(){
//直接更改ref
console.log(msg.value)
console.log(msg.value.gf)
}
复制代码
只监听对象的第一层,
shallowRef
Vue监听的是.value
的变化,并非第一层的变化利用shallowRef 和shallowReactive可以改变当前对象的监听层级
let state = shallowReactive({
a:'2',
gf:{
b:'b',
f:'c',
c:{
a:3
}
}
})
function changeValue(){
console.log(state)
console.log(state.gf)
}
复制代码
第二层的对象不会包装成响应式内容
let msg = shallowRef({
a:'2',
gf:{
b:'b',
f:'c',
c:{
a:3
}
}
})
function changeRef(){
console.log(msg)
console.log(msg.value)
console.log(msg.value.gf)
}
复制代码
注意内容:
msg.value
的时候,其实已经访问它的值了,天然是没有内容的;只读属性的修改,使用
readonly
防止更改响应式对象
存在一组对象,咱们只能读取,可是不能更改,所以可使用readonly进行包裹;
let state = readonly({name:'mfy',age:34,attr:{weight:45,height:1.88}})
function changeReadonly(){
state.age = 2; //修改第一层
state.attr.weight = 2; //修改深层
console.log(state)
console.log(isReadonly(state))
}
复制代码
点击进行修改时候
const obj = reactive({name:'33'})
console.log(obj)
let state = readonly({name:'mfy',age:34,attr:{weight:45,height:1.88}})
console.log(state)
复制代码
reactive
定义的参数在Proxy
函数的set支持传入四个参数readonly
只能收到两个参数,在set中直接进行警告提示和shallowRef
以及shallowReactive
的性质同样,只能控制第一层的数据是不可修改的;
let state = shallowReadonly({name:'mfy',age:34,attr:{weight:45,height:1.88}})
console.log(state)
function changeReadonly(){
state.age = 2; //修改第一层
state.attr.weight = 2; //修改第二层
console.log(state)
console.log(state.attr)
}
复制代码
shllowReadonly
非递归包装,只包装第一层数据,第二层将不会进行包装const也是定义的变量不能在修改,可是对于对象除外;
在实际的使用中,咱们可能不只仅是进行一整个属性进行监听,有多是单个的属性进行监听,所以toRef等给咱们提供了固定属性进行监听;
let obj1 = {age:34,name:'mfy'}
let state2 = toRef(obj1,'name')
function changeRef(){
state2.value = 333
console.log('obj1',obj1)
console.log('state2',state2)
}
复制代码
toRef
修改的值不只仅使定义的值发生了改变,其原始值也发生了改变;
toRef
将某一个对象的属性变成响应式的,此时修改是会影响到原始值将响应式对象转化为普通对象,其中结果对象的每一个
property
都是指向原始对象相应property
的ref
。
let state3 = toRefs(obj1,'name','age')
复制代码
let obj = {age:34,name:'mfy'}
let state =reactive(obj);
console.log(state)
let state2 = toRefs(state)
console.log(state2)
复制代码
打印出来state
和state2
state2
中的引用和原始数据类型以及经过reactive
定义的类型都是属于同一引用关系;即修改obj
、state
、state2
中的任何一个元素属性值,都会发生改变;
let obj = {age:34,name:'mfy'}
let state =reactive(obj);
console.log(state)
let state2 = toRefs(state)
console.log(state2)
function changeRef(){
//修改值
obj.age = 232323;
console.log('state2',state2)
console.log('state',state)
console.log('obj',obj)
}
复制代码
使用reactive定义的对象是不具备响应式的,所以在使用的时候没法进行结构出来使用,而toRefs
能够定义每一个属性都是响应式的,
function useFeatureX() {
const state = reactive({
foo: 1,
bar: 2
})
// 返回时转换为ref
return toRefs(state)
}
export default {
setup() {
// 能够在不失去响应性的状况下破坏结构
const { foo, bar } = useFeatureX()
return {
foo,
bar
}
}
}
复制代码
被定义的响应式数据,如何找到原始数据呢?
从
reactive
或者ref
中获得原始数据,主要是作一些不想被监听的事情(提高性能),每次修改都会被追踪,都会被更新UI界面,可是是很是消耗性能的,因此有一些操做咱们不须要追踪,不须要更新ui界面,此时能够经过toRaw
方法拿到原始数据,对原始数据进行修改,这样不会被追踪,不会更新ui界面
//默认状况下不是一个响应式数据
let obj = {age:34,name:'mfy'}
let state =reactive(obj);
//把建立时候的参数分解出来
let obj2 = toRaw (state); // 和obj是一个样子
function changeRef(){
//引用修改的内容,页面不会自动更新 只有经过修改包装的方法才能更新
obj2.name = 'myy'
//state和obj是引用关系,其中的一个值更改时候,另一个值也会更改
console.log(state)
console.log(obj)
console.log(obj2)
}
复制代码
toRaw
获取到的变量,是一个引用的关系对于ref
定义的值,必需要准确的告诉toRaw
是.value
若是经过toRaw
获取ref
的数据,必须明确告诉ref
是.value
的值 通过Vue
处理以后,.value
中保存的是当初建立时传入的那个原始数据;
let obj = {age:34,name:'mfy'}
let state =ref(obj);
//把建立时候的参数分解出来
let obj2 = toRaw(state.value); // 必须指定定义的ref内部变量的value
function changeRef(){
obj2.name = 'myy'
console.log('state',state)
console.log('obj',obj)
console.log('obj2',obj2)
}
复制代码
markRaw 永远不想被追踪
let obj = {age:34,name:'mfy'}
//告诉这个对象 永远不能被监听
obj = markRaw(obj)
let state =reactive(obj);
function changeRef(){
state.name ='mfy';//监听到这个的变化
console.log(state)
}
复制代码
经过markRaw定义的属性再次被定义成响应式的时候,不管怎样对state
进行赋值,是没法更改其内容的;
setup
是vue3.x
中加入的一个新的生命周期,也是组合api的入口,因为在执行 setup
时还没有建立组件实例,所以在 setup
选项中没有this
。这意味着,除了props
以外,你将没法访问组件中声明的任何属性——本地状态、计算属性或方法。
setup
->beforeCreate
-> created
setup
在执行的时候是在beforeCreate
以前,所以是没法进行获取到this
的setup(props) {
//定义数据
let age = ref(33)
//定义函数
function changeAge(){
age.value = 333
}
// 必须将变量暴露出去才能进行使用
return{
age,
changeAge
}
}
复制代码
在setup的函数中,其内部提供了不少的可进行兼容的方法
用于使用计算属性,能够直接获取到当前拼接出来的值
let firstName = ref("马");
let lastName = ref("fyy")
let fullName = computed(()=> firstName.value + lastName.value)
console.log(fullName)
复制代码
若想要直接修改computed
的变量,可使用set
的方法,将依赖的属性的值进行修改;
let age = ref(12)
let ageCom = computed({
get: () => age.value + 1,
set: val => {
age.value = val - 1
}
})
复制代码
在响应式地跟踪其依赖项时当即运行一个函数,并在更改依赖项时从新运行它。
let firstName = ref("马");
let lastName = ref("fyy")
let fullName = computed(()=> firstName.value + lastName.value)
watchEffect(() => {
console.log('%c 内容发生改变了','color:yellow',fullName.value)
})
function changeName(){
firstName.value = 'Ming'+Math.random()
}
复制代码
每次watchEffect
里面的内容发生改变的时候都会触发;
watch API
与选项式 API this.$watch
(以及相应的 watch 选项) 彻底等效。watch
须要侦听特定的 data
源,并在单独的回调函数中反作用。默认状况下,它也是惰性的——即,回调是仅在侦听源发生更改时调用。 与 watchEffect
比较,watch
容许咱们:
const state = reactive({ count: 0 })
watch(
()=>state.count,
(count,preCount)=>{
console.log('%c count的值发生修改了','color:yellow','count='+count,' preCount='+preCount)
}
)
function changeCount(){
state.count +=1
}
复制代码
let name = ref('myy')
let age = ref(22)
watch([name,age],([name,age],[prevName,prevAge])=>{
console.log("%c --姓名和年龄更改--",'color:yellow')
console.log("%c 姓名更改",'color:green','prevName='+prevName,' name='+name )
console.log("%c 年龄更改",'color:green','prevAge='+prevAge,' age='+age )
})
function changeCount(){
name.value = 'myyyyy'
age.value +=1
}
复制代码
setup
中定义的参数,只能在setup
的做用域下进行修改changeValue(){
console.log(this.isShowAddModal) //false
this.isShowAddModal.value =3
}
复制代码
reactive
)在外部的method中进行修改数据 可以修改为功
changeValue(){
console.log(this.heorData)
this.heorData.list=[]
}
//setup内部的监听函数是否会触发
watch(heorData,()=>{
console.log("watch:: heroData--数据修改了",heorData)
})
复制代码
调用setup
内部暴露的函数,在setup
内部是能够被检测到的
ref
定义的参数,没法在setup
外部进行参数的修改reactive
定义的参数可以进行修改,而且可以被watch
监听到本身经过文档+视频+实际操做对Vue3.x有了一点点了解,有些内容其实不是不够深刻的,比较好奇的点会经过本身想要了解的内容去实际操做一波;