setup 取代了 beforeCreate created 。
setup作用:之前,我们需要在data、methods、mounted的不同位置编写代码,分散的区域很大。现在我们可以在setup中实现它。
<template>
<div>{{name}}</div>
</template>
<script>
import {ref} from "vue"
export default {
name: "App",
setup() {
let name = ref(0);
return {name};
},
};
</script>
这里的ref代替了data的双向绑定,最后我们需要返回一个对象。
vue2.x:
vue3.x:
清单:
vue2使用data初始化数据并进行双向绑定,现在使用ref来实现。
<template>
<div>age is:{{age}}</div>
</template>
<script>
import {ref} from "vue"
export default {
name: "App",
setup() {
let age = ref(20);
return {age};
},
};
</script>
修改双向绑定的值,需要使用 value 属性,如:age.value。
<template>
<div>age is:{{age}}</div>
</template>
<script>
import {ref} from "vue"
export default {
name: "App",
setup() {
let age = ref(20);
setTimeout(() => {
age.value = 22;
}, 2000);
return {age};
},
};
</script>
toRefs() 期望一个响应对象,并根据响应对象属性值的自动变化来渲染页面。
<template>
<div>name is:{{obj.name}}</div>
</template>
<script>
import { toRefs,reactive } from 'vue';
export default {
name: "App",
setup() {
let obj = reactive({
name:'anny',
age:22
})
let objs = toRefs(obj);
setTimeout(() => {
objs.name.value = 'tony'
}, 2000);
return {obj};
},
};
</script>
toRef() 期望一个响应对象及参数,并根据响应对象属性值的自动变化来渲染页面。
<template>
<div>name is:{{obj.name}}</div>
</template>
<script>
import { toRef,reactive } from 'vue';
export default {
name: "App",
setup() {
let obj = reactive({
name:'anny',
age:22
})
let names = toRef(obj,'name');
setTimeout(()=>{
names.value = 'tony';
},2000)
return {obj};
},
};
</script>
非对象类型 的参数。对象类型 ,将 单个reactive对象属性转换ref,保持与父对象的连接对象类型 ,将 所有 reactive对象属性转换ref,保持与父对象的连接相较于 watch ,watchEffect 传入回调函数,不需要指定监听的数据源,自动收集响应式数据。
<template>
<div>age is:{{age}}</div>
</template>
<script>
import { ref, watchEffect } from 'vue';
export default {
name: "App",
setup() {
let age = ref(0);
setTimeout(() => {
age.value+=1;
}, 2000);
watchEffect(()=>{
console.log(age.value)
})
return {age};
},
};
</script>
通过在 template 标签上使用 v-slot 并指定插槽名称来实现命名插槽。
App.vue:
<template>
<HelloWorld>
<template v-slot:test>
<h1>hello test</h1>
</template>
</HelloWorld>
</template>
<script>
import HelloWorld from "./components/HelloWorld.vue";
export default {
name: "App",
components: { HelloWorld },
setup() {},
};
</script>
HelloWorld.vue:
<template>
<div class="hello">
<slot name="test"></slot>
</div>
</template>
要使父级提供的插槽可以访问子组建的数据,我们需要在子组建添加一个 slot 元素并将其作为一个 attribute 绑定:
如:这里我们在子组建使用了 myName
HelloWorld.vue:
<template>
<div class="hello">
<slot :myName="user.name" name="test"></slot>
</div>
</template>
<script>
export default {
name: "HelloWorld",
setup() {
let user = {
name: "anny",
age: 22,
};
return {
user,
};
},
};
</script>
在父级使用:
App.vue:
<template>
<HelloWorld>
<template v-slot:test='item'>
<h1>hello {{item.myName}}</h1>
</template>
</HelloWorld>
</template>
vue3.x 中无需再使用 .async 修饰。
.async实现对某一个 prop 进行“双向绑定”。
teleport 可以将模板的这一部分移动到 DOM 中 Vue app 之外的其他位置。
请注意,目标元素必须在组件安装之前存在 - 即目标不能由组件本身渲染,理想情况下应该在整个 Vue 组件树之外。
<!DOCTYPE html>
<html lang="">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
<title><%= htmlWebpackPlugin.options.title %></title>
</head>
<body>
<!-- vue dom -->
<div id="app"></div>
<!-- vue之外其他dom -->
<div id="some-id"></div>
</body>
</html>
组建 HelloWorld.vue 使用:
<template>
<div class="hello">
<teleport to='#some-id'>123</teleport>
</div>
</template>
可用于全局弹窗,全局提醒等功能。
defineAsyncComponent 主要用于异步加载组建。
defineAsyncComponent 接收一个 Promise 的工厂函数。
<template>
<div id="some-id">
<AsyncCom />
</div>
</template>
<script>
import {defineAsyncComponent} from 'vue'
const AsyncCom = defineAsyncComponent(function(){
return import('./components/HelloWorld.vue')
})
export default {
name: "App",
components: { AsyncCom },
};
</script>
对于高价用法 AsyncCom 参数如下:
const AsyncCom = defineAsyncComponent({
// 工厂函数
loader: () => import('./components/HelloWorld.vue'),
// 加载异步组件时要使用的组件
loadingComponent: LoadingComponent,
// 加载失败时要使用的组件
errorComponent: ErrorComponent,
// 在显示 loadingComponent 之前的延迟 | 默认值:200(单位 ms)
delay: 200,
// 如果提供了 timeout ,并且加载组件的时间超过了设定值,将显示错误组件
// 默认值:Infinity(即永不超时,单位 ms)
timeout: 3000,
// 定义组件是否可挂起 | 默认值:true
suspensible: false,
/**
*
* @param {*} error 错误信息对象
* @param {*} retry 一个函数,用于指示当 promise 加载器 reject 时,加载器是否应该重试
* @param {*} fail 一个函数,指示加载程序结束退出
* @param {*} attempts 允许的最大重试次数
*/
onError(error, retry, fail, attempts) {
if (error.message.match(/fetch/) && attempts <= 3) {
// 请求发生错误时重试,最多可尝试 3 次
retry()
} else {
// 注意,retry/fail 就像 promise 的 resolve/reject 一样:
// 必须调用其中一个才能继续错误处理。
fail()
}
}
})
相较于 vue2.x,vue3.x允许包含多个根结点:
vue2.x:
<template>
<div class="hello">
<div>hello</div>
<div>world</div>
</div>
</template>
vue3.x:
<template>
<div>hello</div>
<div>world</div>
</template>
vue3.x中的数据变化劫持,由 definePoperty 改为了 Proxy。
vue2.x:当数据发生变化时,会生成一个新的 DOM 树,与之前的 DOM 树进行比较,找到不同的节点并更新
vue3.x: 在创建虚拟 DOM 树时,会根据 DOM 中的内容是否发生变化,添加一个静态标签。那么与上一个虚拟节点比较时,只会比较这些带有静态标签的节点。
作用: