#vue3对vue-cli的版本要求必须在4.5.0以上
执行命令:vue -V查看vue-cli版本
如果版本低于4.5.0 可以重新执行命令 npm install -g @vue/cli安装最新版
## 创建项目
vue create 项目名
## 启动项目
cd 项目目录
npm run serve
官网地址:https://vitejs.cn/
Vite(法语意为 “快速的”,发音 /vit/
,发音同 “veet”)是一种新型前端构建工具,能够显著提升前端开发体验。它主要由两部分组成:
Vite 意在提供开箱即用的配置,同时它的 插件 API 和 JavaScript API 带来了高度的可扩展性,并有完整的类型支持。
grant gulp webpack
基于打包器启动时,重建整个包的效率很低。原因显而易见:因为这样更新速度会随着应用体积增长而直线下降。
一些打包器的开发服务器将构建内容存入内存,这样它们只需要在文件更改时使模块图的一部分失活[1],但它也仍需要整个重新构建并重载页面。这样代价很高,并且重新加载页面会消除应用的当前状态,所以打包器支持了动态模块热重载(HMR):允许一个模块 “热替换” 它自己,而不会影响页面其余部分。这大大改进了开发体验 —— 然而,在实践中我们发现,即使采用了 HMR 模式,其热更新速度也会随着应用规模的增长而显著下降。
在 Vite 中,HMR 是在原生 ESM 上执行的。当编辑一个文件时,Vite 只需要精确地使已编辑的模块与其最近的 HMR 边界之间的链失活[1](大多数时候只是模块本身),使得无论应用大小如何,HMR 始终能保持快速更新。
## 创建项目
npm init vite-app 项目名
## 进入项目
cd 项目名
## 安装依赖包 vite项目需要自己手动安装依赖包
npm install
## 运行项目
npm run dev
//此处的引入import 不在是 Vue的构造函数了 引入的是一个名为 createApp的工厂函数。
createApp(App).mount("#app")这句代码可以拆分成两部分代码
//创建实例对象
//注意:此处创建的app跟之前的vm实例对象不一样了,可以看成是一个轻量级的vm实例对象。
let app = createApp(App)
//挂载模板
app.mount('#app')
Vue
构造方法了。必须使用vue3的写法,引入createApp()
工厂方法打开chrome应用商店 下载beta版 就是vue3的开发者工具版本,之前安装的应该也可以使用。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kB9O8dNs-1655452084596)(assets/image-20220308112040949.png)]
通过创建 Vue 组件,我们可以将界面中重复的部分连同其功能一起提取为可重用的代码段。仅此一项就可以使我们的应用在可维护性和灵活性方面走得相当远。然而,我们的经验已经证明,光靠这一点可能并不够,尤其是当你的应用变得非常大的时候——想想几百个组件。处理这样的大型应用时,共享和重用代码变得尤为重要。
使用 (data
、computed
、methods
、watch
) 组件选项来组织逻辑通常都很有效。然而,当我们的组件开始变得更大时,逻辑关注点的列表也会增长。尤其对于那些一开始没有编写这些组件的人来说,这会导致组件难以阅读和理解。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3EoQG5rU-1655452084598)(assets/options-api.png)]
这是一个大型组件的示例,其中逻辑关注点按颜色进行分组。
这种碎片化使得理解和维护复杂组件变得困难。选项的分离掩盖了潜在的逻辑问题。此外,在处理单个逻辑关注点时,我们必须不断地“跳转”相关代码的选项块。
如果能够将同一个逻辑关注点相关代码收集在一起会更好。而这正是组合式 API 使我们能够做到的。
既然我们知道了为什么,我们就可以知道怎么做。为了开始使用组合式 API,我们首先需要一个可以实际使用它的地方。在 Vue 组件中,我们将此位置称为 setup
。
为什么要使用setup()函数: https://zhuanlan.zhihu.com/p/68477600
setup
组件选项**注意:**在 setup
中你应该避免使用 this
,因为它不会找到组件实例。setup
的调用发生在 data
property、computed
property 或 methods
被解析之前,所以它们无法在 setup
中被获取。
setup
选项是一个接收 props
和 context
的函数,我们将在之后进行讨论。此外,我们将 setup
返回的所有内容都暴露给组件的其余部分 (计算属性、方法、生命周期钩子等等) 以及组件的模板。
**使用方式一:**在vue3中 之前定义的data,methods,computed,watch,directives还都仍然可以使用 用法跟vue2是完全一样的,但是过滤器不能使用了
<template>
<h1>{{ msg }}</h1>
<button @click="count++">count is: {{ count }}</button>
<p>{{msg1}}</p>
<p v-color='"blue"'>计算属性{{aaa}}</p>
<p>过滤器{{count | bbb}}</p>
<button type="button" @click="changeMsg">改变msg</button>
</template>
<script>
import {ref} from 'vue'
export default {
name: 'HelloWorld',
props: {
msg: String
},
data(){
return {
count:0,
msg1:'',
}
},
methods:{
changeMsg(){
this.msg1 = this.msg
}
},
computed:{
aaa(){
return this.count+1
}
},
watch:{
count(newVal,oldVal){
console.log(newVal,oldVal)
}
},
filters:{
bbb(val){
return val+5
}
},
directives:{
color(el,binding){
el.style.color = binding.value
}
}
}
</script>
使用方式二:setup基本用法
在实例中不在配置data,methods,computed…等独立配置项 而是在其中添加一个setup(){}
项, 所有的配置内容都写在其中,最终把页面中需要用到的数据通过return{} 暴漏出去。
<template>
<h1>这里是组件{{age}}</h1>
<button type="button" @click="age+=1">点我</button>
</template>
<script>
import {ref} from 'vue'
export default {
components:{},
//定义setup函数
setup(){
let name = '张三'
let age = ref(58)
return{
name,age
}
}
}
</script>
注意:
**发现问题:**在以上案例中,如果我们想点击按钮修改age的值,会发现 页面中是无法更新渲染age数据的 为什么?
带
ref
的响应式变量
在 Vue 3.0 中,我们可以通过一个新的 ref
函数使任何响应式变量在任何地方起作用,如下所示:
//一定要先导入
import { ref } from 'vue'
const counter = ref(0)
ref
接收参数并将其包裹在一个带有 value
property 的对象中返回,然后可以使用该 property 访问或更改响应式变量的值:
import { ref } from 'vue'
const counter = ref(0)
console.log(counter) // { value: 0 }
console.log(counter.value) // 0
counter.value++
console.log(counter.value) // 1
将值封装在一个对象中,看似没有必要,但为了保持 JavaScript 中不同数据类型的行为统一,这是必须的。这是因为在 JavaScript 中,Number
或 String
等基本类型是通过值而非引用传递的:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fyLxXbYc-1655452084599)(assets/pass-by-reference-vs-pass-by-value-animation.gif)]
在任何值周围都有一个封装对象,这样我们就可以在整个应用中安全地传递它,而不必担心在某个地方失去它的响应性。
换句话说,ref
为我们的值创建了一个响应式引用。在整个组合式 API 中会经常使用引用的概念。
使用: let age = ref(58)
此句代码 58 被ref包括后 并不是说age=58 此时的age是一个对象RefImpl{}
其中包含一个属性value, 我们使用age.value
才可以真正的取到数值58 ;
此处的控制台输出为:
小结:
属性名.value
才可以完成 ;在setup中添加如下代码 son对象: 点击按钮 改变 son中的数据
<template>
<h2>儿子的名字:{{son.name}}</h2>
<h2>儿子的年龄:{{son.age}}</h2>
<button type="button" @click="changeSonAge">点我改变儿子的年龄+1</button>
</template>
<script>
//需要先导入ref函数
import {ref} from 'vue'
export default {
components:{},
setup(){
let son = ref({
name:'张三',
age:18
})
function changeSonAge(){
//报错
son.value.age.value += 1
//有效代码
son.value.age += 1
console.log(son)
}
//返回页面中需要使用的数据
return{
son,changeSonAge
}
}
}
</script>
此时虽然同样是用 ref包括的数据 但是操作时 只需要取出 son.value
操作属性就可以了, 不需要使用son.value.age.value
这样会报错 ;
原因: 此处我们打印 son
对象 发现 被ref()包括的son对象是如下形式:
此时虽然整体的son还是 RefImpl
形式 , 但是其中的value
属性却变成了 proxy
形式 是 ES6的新特性 : 代理
小结:
RefImpl
形式proxy
形式注意:
Object.defineProperty()
getter和setter
proxy
简介:
使用:
<template>
<h2>儿子的名字:{{son.name}}</h2>
<h2>儿子的年龄:{{son.age}}</h2>
<button type="button" @click="changeSonAge">点我改变儿子的年龄+1</button>
</template>
<script>
import {ref,reactive} from 'vue'
export default {
components:{},
setup(){
let son = reactive({
name:'张三',
age:18
})
function changeSonAge(){
son.age += 1
console.log(son)
}
return{
name,age,son,changeSonAge
}
}
}
</script>
此处把son对象使用reactive
函数包括起来 此时再想操作son中的age属性就不需要添加value了 可以直接使用son.age
操作, 因为此时返回的直接就是 proxy
代理对象 把son对象换成数组 一样可以操作 , 并且可以直接通过下标来对数组进行修改(vue2中不行) ;
注意: ref函数包括对象类型实现响应式就是因为 ref在底层调用了reactive
函数 ;
小结:
setup完整语法格式: setup(props,context){}
<button @click="bbb">子组件中触发自定义事件</button>
export default{
//此处添加emits属性 把自定义的事件类型填入
emits:['hello'],
setup(props,context){
function bbb(){
console.log('hello自定义事件触发了')
//通过context调用emit方法来完成自定义事件
context.emit('hello','你好哈哈哈')
}
return{
bbb
}
}
}
父组件中:
<Son @hello='aaa'></Son>
setup(){
//自定义事件触发aaa函数 val就是子组件传递来的数据
function aaa(val){
console.log('接收到子组件传递来的数据:',val)
}
return{
aaa
}
}
**简介:**通常,当我们需要从父组件向子组件传递数据时,我们使用 props。想象一下这样的结构:有一些深度嵌套的组件,而深层的子组件只需要父组件的部分内容。在这种情况下,如果仍然将 prop 沿着组件链逐级传递下去,可能会很麻烦。
对于这种情况,我们可以使用一对 provide
和 inject
。无论组件层次结构有多深,父组件都可以作为其所有子组件的依赖提供者。这个特性有两个部分:父组件有一个 provide
选项来提供数据,子组件有一个 inject
选项来开始使用这些数据。
**主要作用:**父组件向后代组件传递数据。
在祖组件
使用privade
定义要传递的数据,在后代组件
中通过inject
来接收参数。
//祖组件中 定义privade传递数据
provide('fage',fage.value)
//后代组件 接收privade数据的方式二
let fage = inject('fage')
通过 Object.defineProperty()
方法来实现。通过getter
和setter
方法来完成。
Object.defineProperty(obj,'属性',{
get(){},set(){}
})
ref() ===> reactive()
通过
Es6
中的 proxy
代理来完成的。
<body>
<script type="text/javascript">
let obj = {
name:'张三',
age:18,
address:'郑州'
}
let p = new Proxy(obj,{
//target表示 被代理对象 propKey表示读取的属性值
get(target,propKey){
console.log(`获取了${propKey}属性`)
return target[propKey]
},
set(target,propKey,value){
console.log(`修改了${propKey}属性`)
target[propKey] = value
},
deleteProperty(target,propKey){
console.log(`删除了${propKey}属性`)
return delete target[propKey]
}
})
</script>
</body>
</html>
获取属性调用get()方法
修改或者新增属性调用set()方法
删除属性调用deleteProperty()方法
Reflect
反射反射:获取对象中的属性值
概念: 见教程:https://es6.ruanyifeng.com/#docs/reflect
**使用:**Reflect是与Proxy 完全对应的方法,我们可以通过Proxy代理对 对象的操作添加一些拦截 做一些事情,同时可以使用Reflect反射 来从对象中获取数据。主要用途:封装底层框架,保证代码顺利执行
<body>
<script type="text/javascript">
let obj = {
name:'张三',
age:18,
address:'郑州'
}
let p = new Proxy(obj,{
//target表示 被代理对象 propKey表示读取的属性值
get(target,propKey){
console.log(`获取了${propKey}属性`)
return Reflect.get(target,propKey)
},
set(target,propKey,value){
console.log(`修改了${propKey}属性`)
Reflect.set(target,propKey,value)
},
deleteProperty(target,propKey){
console.log(`删除了${propKey}属性`)
return Reflect.deleteProperty(target,propKey)
}
})
</script>
</body>
</html>
仍然可以按照vue2中的语法来实现计算属性。
但是这里我们推荐使用vue3
import {computed} from 'vue'
<template>
<input v-model="msg"/>
<p>转为大写:{{newVal}}</p>
</template>
<script>
import {ref,computed} from 'vue'
export default{
setup(){
let msg = ref('')
//定义计算属性
let newVal = computed(()=>{
return msg.value.toUpperCase()
})
return {msg,newVal}
}
}
</script>
首先:vue2中侦听器的使用方式在vue3中仍然可以使用
vue3的方式定义侦听器:
语法格式:
import {watch} from 'vue'
export default{
watch(被监视的数据,监视的回调函数),
watch(name,(newVal,oldVal)=>{})
}
案例:
<template>
<!-- vue3中的侦听器 -->
<h1>数量:{{count}}</h1>
<button type="button" @click='count++'>点我+1</button>
<h1>数量:{{num}}</h1>
<button type="button" @click='num+=2'>点我+2</button>
<h1>===========================reactive数据监听====================================</h1>
<h1>姓名:{{obj.name}}</h1>
<button type="button" @click='obj.name+="#"'>点我改变名字</button>
<h1>年龄:{{obj.age}}</h1>
<button type="button" @click='obj.age+=1'>点我改变年龄</button>
<h1>班级:{{obj.class.c1}}</h1>
<button type="button" @click='obj.class.c1+="--"'>点我改变班级</button>
</template>
<script>
import {ref,reactive,watch} from 'vue'
export default{
setup(){
let count = ref(0)
let num = ref(10)
let obj = reactive({
name:'张三',
age:18,
address:'郑州',
class:{
c1:'qy147',
c2:'qy148'
}
})
//监视一个数据
/* watch(count,(newVal,oldVal)=>{
console.log(newVal,oldVal)
}) */
//监听多个数据 此时的newVal,oldVal 都是以数组形式展示数据
/* watch([count,num],(newVal,oldVal)=>{
console.log(newVal,oldVal)
}) */
//监听reactive对象数据
//注意:此处可以监听到数据的改变,但是无法获取到oldVal
//reactive响应式数据的监听,vue3会自动开启深度监听 并且是强制开启的 deep配置没有效果
/* watch(obj,(newVal,oldVal)=>{
console.log(newVal,oldVal)
},{immediate:true}) */
//监听对象中单独的属性
//注意:需要把要监听的属性以函数的形式返回 才可以监视到
//此时的oldVal也可以使用
/* watch(()=>obj.class.c1,(newVal,oldVal)=>{
console.log(newVal,oldVal)
},{immediate:true}) */
//此时直接监听class对象 此时需要开启 deep:true属性
watch(()=>obj.class,(newVal,oldVal)=>{
console.log(newVal,oldVal)
},{immediate:true,deep:true})
return {count,num,obj}
}
}
</script>
watchEffect
侦听**简介:**立即执行传入的一个函数,同时响应式追踪其依赖,并在其依赖变更时重新运行该函数。也就是说监视的回调函数中用到了哪个属性,那么当这个属性发生改变时,watchEffect回调就会执行。
watchEffect(()=>{
num.value+=1
console.log('watchEffect执行了')
})
只要num的值 发生了改变 watchEffect中的回调函数就会执行。
概念:Fragment就是一个虚拟的元素,vue3中元素不必使用根元素包括,其实就是放在一个Fragment虚拟元素中了。
**简介:**Vue 鼓励我们通过将 UI 和相关行为封装到组件中来构建 UI。我们可以将它们嵌套在另一个内部,以构建一个组成应用程序 UI 的树。
然而,有时组件模板的一部分逻辑上属于该组件,而从技术角度来看,最好将模板的这一部分移动到 DOM 中 Vue app 之外的其他位置。
一个常见的场景是创建一个包含全屏模式的组件。在大多数情况下,你希望模态框的逻辑存在于组件中,但是模态框的快速定位就很难通过 CSS 来解决,或者需要更改组件组合。
语法格式:
<teleport to="#Father"></teleport>
通过to属性指定要传送的位置。to属性的值: 可以是html标签名 也可以是标签的id值
官方案例: 点击按钮 打开弹出框,teleport内置组件可以让弹出框显示在指定的位置
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7ZjdmYW1-1655452084601)(assets/image-20220309110532944.png)]
Father.vue组件:
<template>
<div id="Father">
<h1>这里是父组件</h1>
<Son></Son>
</div>
</template>
<script>
import Son from './Son.vue'
export default{
components:{Son}
}
</script>
<style scoped>
#Father{
border:1px solid red;
background-color: red;
line-height: 100px;
}
</style>
Son.vue组件
<template>
<div id="son">
<h1>这里是儿子组件</h1>
<Child></Child>
<button type="button" @click='isShow=true'>打开弹窗</button>
<Dialog v-if="isShow" @closeDialog='bbb'></Dialog>
</div>
</template>
<script>
import Child from './Child.vue'
import Dialog from './Dialog.vue'
import {ref} from 'vue'
export default{
components:{Child,Dialog},
//emits:['closeDialog'],
setup(props,context){
let isShow = ref(false)
function bbb(val){
isShow.value = val
}
return {isShow,bbb}
}
}
</script>
<style scoped>
#son{
border:1px solid red;
background-color: gray;
line-height: 100px;
}
</style>
Child.vue组件
<template>
<div id="child">
<h1>这里是孙子组件</h1>
<button type="button" @click='isShow=true'>打开弹窗</button>
<Dialog v-if="isShow" @closeDialog='bbb'></Dialog>
</div>
</template>
<script>
import Dialog from './Dialog.vue'
import {ref} from 'vue'
export default{
components:{Dialog},
//emits:['closeDialog'],
setup(){
let isShow = ref(false)
function bbb(val){
isShow.value = val
}
return {isShow,bbb}
}
}
</script>
<style scoped>
#child{
border:1px solid red;
background-color: blue;
line-height: 100px;
color: white;
}
</style>
Dialog.vue组件:
<template>
<teleport to="#Father">
<div id="dialog">
<div class="dialog">
<h2>这里是弹出层组件</h2>
<h3>你好啊哈哈哈</h3>
<button type="button" @click="close">点我关闭</button>
</div>
</div>
</teleport>
</template>
<script>
import {ref} from 'vue'
export default{
emits:['closeDialog'],
setup(props,context){
let isShow = ref(true)
function close(){
context.emit('closeDialog',false)
}
return{isShow,close}
}
}
</script>
<style scoped>
#dialog{
background-color: rgba(0,0,0,0.5);
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
}
.dialog{
width: 300px;
height: 300px;
background-color: yellow;
margin: auto;
margin-top: 200px;
}
</style>
完成效果:让dialog弹出层 能够显示在teleport的to属性指定的位置。
**注意:**vue2的生命周期写法在vue3中同样可以使用。
vue3生命周期图解:
你可以通过在生命周期钩子前面加上 “on” 来访问组件的生命周期钩子。
下表包含如何在 setup () 内部调用生命周期钩子:
选项式 API | Hook inside setup |
---|---|
beforeCreate | setup() |
created | setup() |
beforeMount | onBeforeMount |
mounted | onMounted |
beforeUpdate | onBeforeUpdate |
updated | onUpdated |
beforeUnmount | onBeforeUnmount |
unmounted | onUnmounted |
errorCaptured | onErrorCaptured |
renderTracked | onRenderTracked |
renderTriggered | onRenderTriggered |
activated | onActivated |
deactivated | onDeactivated |
**注意:**因为 setup
是围绕 beforeCreate
和 created
生命周期钩子运行的,所以不需要显式地定义它们。换句话说,在这些钩子中编写的任何代码都应该直接在 setup
函数中编写。
vue3中生命周期钩子的使用方法(组合API形式):
这些函数接受一个回调函数,当钩子被组件调用时将会被执行:
<template>
<h1>App.vue组件</h1>
<h3>{{age}}</h3><button @click="age+=1">点我</button>
</template>
<script>
//首先导入需要使用生命周期钩子函数
import {ref,onBeforeMount,onMounted,onBeforeUpdate,onUpdated,onBeforeUnmount,onUnmounted} from 'vue'
export default {
name: 'App',
components: {},
setup(){
let age = ref(18)
console.log('================beforeCreate======================')
console.log('================created======================')
onBeforeMount(()=>{
console.log('================onBeforeMount======================')
})
onMounted(()=>{
console.log('================onMounted======================')
})
onBeforeUpdate(()=>{
console.log('================onBeforeUpdate======================')
})
onUpdated(()=>{
console.log('================onUpdated======================')
})
//当组件进行切换时 可以调用卸载钩子函数
onBeforeUnmount(()=>{
console.log('================onBeforeUnmount======================')
})
onUnmounted(()=>{
console.log('================onUnmounted======================')
})
return {age}
}
}
</script>
const obj = reactive({ count: 0 })
响应式转换是“深层”的——它影响所有嵌套 property。在基于 ES2015 Proxy 的实现中,返回的 proxy 是不等于原始对象的。建议只使用响应式 proxy,避免依赖原始对象。
const state = shallowReactive({
foo: 1,
nested: {
bar: 2
}
})
// 改变 state 本身的性质是响应式的
state.foo++
// ...但是不转换嵌套对象
isReactive(state.nested) // false
state.nested.bar++ // 非响应式
const original = reactive({ count: 0 })
const copy = readonly(original)
watchEffect(() => {
// 用于响应性追踪
console.log(copy.count)
})
// 变更 original 会触发依赖于副本的侦听器
original.count++
// 变更副本将失败并导致警告
copy.count++ // 警告!
const state = shallowReadonly({
foo: 1,
nested: {
bar: 2
}
})
// 改变 state 本身的 property 将失败
state.foo++
// ...但适用于嵌套对象
isReadonly(state.nested) // false
state.nested.bar++ // 适用
让一个数据变为只读的,浅层只读,内部嵌套的数据不是只读的
<script>
import {reactive,ref,toRef,toRefs,shallowReadonly,readonly} from 'vue'
export default{
name:"Father",
components:{Son},
setup(){
let fname = ref('父亲')
let person = reactive({
name:'张三',
age:18,
job:{
salary:20
}
})
//把person对象重新使用shallowReadonly包括 重新赋值给person
person = shallowReadonly(person)
return {
...toRefs(person)
}
}
}
</script>
import { reactive, isReactive } from 'vue'
export default {
setup() {
const state = reactive({
name: 'John'
})
console.log(isReactive(state)) // -> true
}
}
const foo = {}
const reactiveFoo = reactive(foo)
console.log(toRaw(reactiveFoo) === foo) // true
const foo = markRaw({})
console.log(isReactive(reactive(foo))) // false
// 嵌套在其他响应式对象中时也可以使用
const bar = reactive({ foo })
console.log(isReactive(bar.foo)) // false
.value
property,指向该内部值。
示例:const count = ref(0)
console.log(count.value) // 0
count.value++
console.log(count.value) // 1
如果将对象分配为 ref 值,则它将被 reactive 函数处理为深层的响应式对象。
val = isRef(val) ? val.value : val
的语法糖函数。const state = reactive({
foo: 1,
bar: 2
})
const fooRef = toRef(state, 'foo')
fooRef.value++
console.log(state.foo) // 2
state.foo++
console.log(fooRef.value) // 3
我们可以把对象中的常用数据通过toRef引用出来,这样就不需要再把整个对象向外返回了,写法上会简单些。
export default{
name:"Father",
setup(){
let fname = ref('父亲')
let person = reactive({
name:'张三',
age:18
})
return {
name:toRef(person,'name')
}
}
}
我们可以通过toRef把一个响应式对象中的单个数据向外暴漏 并且这个单个数据 不会丢失对person对象的响应性。
toRef引用响应式对象中的单个数据
toRefs
非常有用,这样消费组件就可以在不丢失响应性的情况下对返回的对象进行解构/展开:
toRefs
引用响应式对象中的多个数据,可以以解构赋值的形式解析响应式对象export default{
name:"Father",
setup(){
let fname = ref('父亲')
let person = reactive({
name:'张三',
age:18
})
return {
...toRefs(person)
}
}
}
可以直接把整个person对象中所有的数据都变成 toRef形式 使用的时候 直接使用person对象的属性名就可以了。
app.mixin app.use app.directive
全局挂载
app.config.globalProperties.foo = 'bar'
keycodes.数字
我们可以把对象中的常用数据通过toRef引用出来,这样就不需要再把整个对象向外返回了,写法上会简单些。
```js
export default{
name:"Father",
setup(){
let fname = ref('父亲')
let person = reactive({
name:'张三',
age:18
})
return {
name:toRef(person,'name')
}
}
}
我们可以通过toRef把一个响应式对象中的单个数据向外暴漏 并且这个单个数据 不会丢失对person对象的响应性。
toRef引用响应式对象中的单个数据
toRefs
非常有用,这样消费组件就可以在不丢失响应性的情况下对返回的对象进行解构/展开:
toRefs
引用响应式对象中的多个数据,可以以解构赋值的形式解析响应式对象export default{
name:"Father",
setup(){
let fname = ref('父亲')
let person = reactive({
name:'张三',
age:18
})
return {
...toRefs(person)
}
}
}
可以直接把整个person对象中所有的数据都变成 toRef形式 使用的时候 直接使用person对象的属性名就可以了。
app.mixin app.use app.directive
全局挂载
app.config.globalProperties.foo = 'bar'
keycodes.数字