.加强网站安全建设,北京建设职工大学网站,《网站开发尾款结算》申请,新媒体运营的相关优势Vue3#xff1a;第一章 一、创建Vue3.0工程1.使用vue-cli创建2.使用vite创建 二、Vue3中的响应式1.拉开序幕的setup2.ref函数3.reactive函数4.vue3中响应式的原理#xff08;1#xff09;vue2中响应式原理#xff08;2#xff09;Vue3中的Proxy 5.reactive和ref的对比6.se… Vue3第一章 一、创建Vue3.0工程1.使用vue-cli创建2.使用vite创建 二、Vue3中的响应式1.拉开序幕的setup2.ref函数3.reactive函数4.vue3中响应式的原理1vue2中响应式原理2Vue3中的Proxy 5.reactive和ref的对比6.setup的两个注意点1执行时机2setup的参数 三、计算属性和监视1.computed函数2.watch函数1第一个参数怎么写2第一个参数到底写不写.value 3.watchEffect函数 一、创建Vue3.0工程
1.使用vue-cli创建
官方文档https://cli.vuejs.org/zh/guide/creating-a-project.html#vue-create
// 查看vue/cli版本确保vue/cli版本在4.5.0以上
vue --version
// 安装或者升级你的vue/cli
npm install -g vue/cli
// 创建
vue create vue_test
// 启动
cd vue_test
npm run serve2.使用vite创建
官方文档https://v3.cn.vuejs.org/guide/installation.html#vite vite官网https://vitejs.cn
// 创建工程
npm init vite-app project-name
// 进入工程目录
cd project-name
// 安装依赖
npm install
// 运行
npm run dev二、Vue3中的响应式
1.拉开序幕的setup
之前我们在vue2中都是多个配置项组合在一起选项式API在vue3中换了一种方式那就是Composition API组合式API而setup则是组合式API表演的舞台组件中所有的数据和方法都写在setup函数中。
这个setup函数其实有两种返回值1、返回一个对象 2、返回一个渲染函数用的最多的就是返回一个对象把用到的所有属性、方法都返回出去方便在模板中使用当然现在有了setup语法糖后面再说
export default {name: App,setup() {const name zzyconst age 18return {name,age,}//返回一个渲染函数//return () h(h1, zzy)}
}注意不要把setup和vue2中的选项式API混用因为setup中访问不到vue2中的属性方法但2可访问3如果混用的话有重名setup优先。
还有setup前不要加async因为返回值会变成promise而不是我们return的那些属性和方法
2.ref函数
作用定义响应式的数据。
import { ref } from vue
const count ref(0)上面代码创建了一个包含响应式数据的引用对象RefImp对象 在js中操作数据count.value 在模板中读取数据div {{count}} /div这里会自动读取value属性
其实ref可以接受的数据不只是基本数据类型复杂数据类型也可以只不过比较麻烦操作时都要.value
const person ref({name: zzy, age: 18})
person.value.name dantin基本数据类型和负责数据类型实现响应式的方式不同前者依然是Object.defineProperty()的get与set后者则在内部求助了reactive函数
3.reactive函数
作用定义一个对象类型的响应式数据基本类型不要用reactive要用ref
import { reactive } from vue
const person reactive({name: zzy, age: 18})
person.name ht接收一个对象或数组返回一个代理对象Proxy对象且这里的监视式深层次监视
4.vue3中响应式的原理
对于ref和reactive是不一样的ref简单类型是通过Object.defineProperty()的get与set,当然啊ref定义的复杂类型是通过reactive的Proxy
而reactive是通过Proxy来实现响应式的上文提到了并通过Reflect来操作源数据
不管怎么样总结来说vue3中新增的就是对于复杂数据类型通过Proxy实现响应式也就是两个点
通过Proxy代理: 拦截对象中任意属性的变化, 包括属性的增删、属性值的读写等。通过Reflect反射: 对源对象的属性进行上述操作。
1vue2中响应式原理
我们知道vue2中是通过Object.defineProperty()对对象类型数据进行劫持并添加getter和setter来监视数据的对于数组是重写了更新数组的方法。复习vue2监视数据的原理
vue2监视数据存在两个问题 1、直接新增属性、删除属性, 界面不会更新。2、直接通过下标修改数组, 界面不会自动更新。
2Vue3中的Proxy
在vue3中**解决了vue2中的两个问题。下面是模拟实现vue3中响应式的原理
const person {name: zzy,age: 18
}const p new Proxy(person, {get(target, propName) {console.log(target)console.log(有人读person中的${propName})return target[propName]},set(target, propName, value) {console.log(有人改person中的${propName}修改后的值为${value})target[propName] value},deleteProperty(target, propName) {console.log(有人删除了person中的${propName})return delete target[propName]}
})再严谨一些用Reflect来进行增删改查这也是框架的做法其实本质上没什么太大的区别只是Reflect可以避免一些报错吧不然还要用try-catch去捕获这里不用太纠结其实就是为了让框架更加的友好少一些报错
const person {name: zzy,age: 18
}const p new Proxy(person, {//查get(target, propName) {console.log(target)console.log(有人读person中的${propName})// return target[propName]return Reflect.get(target, propName)},//增改set(target, propName, value) {console.log(有人改person中的${propName}修改后的值为${value})// target[propName] valueReflect.set(target, propName, value)},//删deleteProperty(target, propName) {console.log(有人删除了person中的${propName})// return delete target[propName]return Reflect.deleteProperty(target, propName)}
})5.reactive和ref的对比
1、定义数据类别不同
ref用于定义基本数据类型也可以定义复杂类型
reactive用于定义对象或数组类型2、原理不同
ref是通过Object.defineProperty()的get与set,当然啊复杂类型是通过reactive的Proxy
reactive是通过Proxy来实现响应式的上文提到了并通过Reflect来操作源数据3、使用方式不同
ref定义的数据操作时需要.value模板读取不需要.value
reactive定义的数据操作和读取都不需要.value6.setup的两个注意点
1执行时机
setup函数的执行时机是beforeCreate之前也就是所有生命周期的最前面此时this是undefined也就是说在setup中是绝对不能通过this访问组件实例的。
2setup的参数
setup接收两个参数propscontext props是一个对象包含组件外部传递过来且组件内部声明接收了的属性。 context是一个对象包含三个属性分别是attrs、slots、emit 第一个attrs相当于this.$attrs值为对象包含组件外部传递过来但没有在props配置中声明的属性 第二个slots相当于this.$slots包含收到的插槽的内容。 第三个emit相当于this.$emit用来触发组件的自定义事件。
props: [name, age]
setup(props, context) {console.log(props) // Proxy{name:zzy,age:18}组件外部传递过来且组件内部声明接收了的属性。console.log(context.attrs)//相当于this.$attrsconsole.log(context.slots)相当于this.$slotsconsole.log(context.emit)//相当于this.$emit
}三、计算属性和监视
1.computed函数
和vue2中功能是一样的只不过变成了一个函数而且要手动引入。默认写法是传一个回调
import {computed} from vuesetup(){...//计算属性——简写只读readonlylet fullName computed((){return person.firstName - person.lastName})
}当我们去改计算属性的值的时候控制台可能会有警告 这是因为计算属性默认是只读的当它所依赖的值改变的时候它自己会变。如果要想改计算属性需要用下面的完整写法传一个对象里面有getter和settersetter中参数是修改后的新值
import {computed} from vuesetup(){...//计算属性——完整包括读和写let fullName computed({get(){return person.firstName - person.lastName},set(value){const nameArr value.split(-)person.firstName nameArr[0]person.lastName nameArr[1]}})
}2.watch函数
其实watch在vue3中和vue2中功能是一样的就是写法不一样。 先准备一些数据吧
import { ref, reactive } from vue
const sum ref(0)
const msg ref(hello)
const person reactive({name: dantinage: 18job: {type: codesalary: 1000k}
})1第一个参数怎么写
情况一监视ref定义的响应式数据
watch(sum,(newValue,oldValue){console.log(sum变化了,newValue,oldValue)
},{immediate:true})情况二监视多个ref定义的响应式数据
watch([sum,msg],(newValue,oldValue){console.log(sum或msg变化了,newValue,oldValue)//new和old也是监听值构成的数组
}) 情况三监视reactive定义的响应式数据 这里有两个坑第一个是reactive定义的数据监视时回调中无法获得oldValueoldValue和new一样 第二个坑是监视reactive定义的数据默认开启的deep:true且deep不能改成false
watch(person,(newValue,oldValue){console.log(person变化了,newValue,oldValue)
},{immediate:true,deep:false}) //此处的deep配置不再奏效情况四监视reactive定义的响应式数据中的某个属性 这里要注意第一个参数必须写成箭头函数如果直接写person.job那么就相当于写了个死的值这样是监视不到的。还有就是如果job是一个对象那么默认deep是false的如果要深度监视需要手动开启deep:truedeep配置有效
watch(()person.job,(newValue,oldValue){console.log(person的job变化了,newValue,oldValue)
},{immediate:true,deep:true}) 情况五监视reactive定义的响应式数据中的某些属性 如果这种情况的话和上面类似不同的是第一个参数写成数组且每个元素是箭头函数返回的new和old值也是相对应的值构成的数组。
watch([()person.job,()person.name],(newValue,oldValue){console.log(person的job变化了,newValue,oldValue)
},{immediate:true,deep:true})2第一个参数到底写不写.value
如果我们把person换成是一个ref定义的呢那么监视的时候写不写.value
import { ref, reactive } from vue
const sum ref(0)
const msg ref(hello)
const person ref({name: dantinage: 18job: {type: codesalary: 1000k}
})答案是要写的因为ref对于复杂数据类型内部是借助reactive的Proxy实现响应式的所以这么写的话就相当于是写了一个reactive定义的响应式数据在监视时也就具有了对应的坑见上文情况三
watch(person.value,(newValue,oldValue){console.log(person变化了,newValue,oldValue)
},{immediate:true,deep:false}) //此处的deep配置不奏效除此之外还有一种办法那就是深度监视person它是一个RefImpl对象这样就能监视到其中的value及更深层的变化。这是因为如果直接监视person不读取.value那么监视的是RefImpl对象只有其中value的地址变的时候才能监视到value里面的东西变化是监视不到的所以要开deep
watch(person,(newValue,oldValue){console.log(person变化了,newValue,oldValue)
},{immediate:true,deep:true}) 那为什么简单数据类型不需要.value呢其实和上面的情况四是一样的如果简单数据类型直接.value那么监视的就是一个写死的值。不.value的话监视的是一个响应式的RefImpl对象当里面value变化的时候是可以监视到的这块儿感觉懵懵的回头看源码吧
watch(sum,(newValue,oldValue){console.log(sum变化了,newValue,oldValue)
})如果非要.value请使用箭头函数动态读取每次sum变化都会执行回调读取最新的值
watch(() sum.value,(newValue,oldValue){console.log(sum变化了,newValue,oldValue)
})3.watchEffect函数 watch的套路是既要指明监视的属性也要指明监视的回调。 watchEffect的套路是不用指明监视哪个属性监视的回调中用到哪个属性那就监视哪个属性。
watchEffect有点像computed但computed注重的计算出来的值回调函数的返回值所以必须要写返回值。而watchEffect更注重的是过程回调函数的函数体所以不用写返回值。
//watchEffect的回调一上来会先执行一次
//watchEffect所指定的回调中用到的数据只要发生变化则直接重新执行回调。
watchEffect((){const x1 sum.valueconst x2 person.ageconsole.log(watchEffect配置的回调执行了)
})其实感觉这玩意儿就是在模仿React中的useEffect