Vue3相比于Vue2
- 解决了:Vue2中新增属性,删除属性,界面不会更新的问题。
- 解决了:Vue2中直接通过下标修改数组,界面不会刷新的问题。
vue-cli版本必须是4.5以上,查看版本命令:vue -V
创建工程命令:vue create 项目名
关闭语法检查
- module.exports = {
- transpileDependencies: true,
- lintOnSave: false, /*关闭语法检查*/
- }
示例
- <template>
- <h2>姓名:{{name}}h2>
- <h2>姓名:{{age}}h2>
- <button @click="fun">按钮button>
- template>
-
- <script>
-
- export default {
- name: 'App',
- setup(){
- let name='李义新';
- let age=10;
- function fun(){
- alert(`姓名:${name} 年纪:${age}`);
- }
-
- //返回一个对象(常用)
- return {
- name,age,fun
- }
-
- //返回一个渲染函数(不常用)
- //return ()=> h('h1','尚硅谷')
-
- }
- }
- script>
- <template>
- <h2>姓名:{{name}}h2>
- <h2>工作:{{job.type}}h2>
- <button @click="fun">按钮button>
- template>
-
- <script>
- //引入ref
- import {ref} from "vue"
-
- export default {
- name: 'App',
- setup(){
- let name=ref('李义新');
- let job = ref({
- type:"前端工程师"
- })
-
- function fun(){
- name.value="李二新";
- job.value.type="后端工程师"
- }
-
- return {
- name,job,fun
- }
- }
- }
- script>
- <template>
- <h2>工作:{{job.type}}h2>
- <h2>工作:{{job.xin.name}}h2>
- <button @click="fun">按钮button>
- template>
-
- <script>
- //引入ref
- import {reactive} from "vue"
-
- export default {
- name: 'App',
- setup(){
- let job = reactive({
- type:"前端工程师",
- xin:{
- name:"xxx"
- }
- })
-
- function fun(){
- job.type="后端工程师";
- job.xin.name="哈哈哈";
- }
-
- return {
- job,fun
- }
- }
- }
- script>
从定义数据角度对比
ref用来定义:基本类型数据。
reactive用来定义:对象(或数组)类型数据。
备注:ref也可以用来定义对象(或数组)类型数据,它内部会自动通过reactive转为代理对象。
从原理角度对比:
ref通过Object.defineProperty()的get与set实现响应式(数据劫持)。
reactive通过使用Proxy来实现响应式(数据劫持),并通过Reflect操作源对象内部的数据。
从使用角度对比:
ref定义的数据:操作数据需要.value,读取数据时模板中直接读取不需要.value。
reactive定义的数据:操作数据与读取数据:均不需要.value。
与Vue2中的computed一样。
- import {computed} from 'vue'
-
- setup(){
- //计算属性简写
- let fullName = computed(()=>{
- return 1+1;
- })
-
- //计算属性完整
- let fullName = computed({
- get(){
- return 1+1;
- },
- set(value){
- a = value;
- }
- })
-
- }
参数:watch(监视的属性或者对象,(newVal,oldVal)={},{配置项})
watch函数使用的六种情况
- <template>
- <h2>总和:{{sum}}h2>
- <h2>一共:{{count}}h2>
- <h2>工作:{{job.type}}h2>
- <h2>工作:{{job.xin.name}}h2>
- <button @click="sum++">sum++button>
- <button @click="count++">count++button>
- template>
-
- <script>
- //引入ref
- import {ref,watch,reactive} from "vue"
-
- export default {
- name: 'App',
- setup(){
- let sum = ref(0);
- let count = ref(0);
- let job = reactive({
- type:"前端工程师",
- name:"李义新",
- xin:{
- name:"xxx"
- }
- })
-
- //情况一:监视ref所定义的一个响应式数据,第三个参数是配置项
- watch(sum,(newValue,oldValue)=>{
- console.log("sum改变了")
- },{immediate:true})
-
- // //情况二:监视ref所定义的多个响应式数据
- watch([sum,count],(newVal,oldVal)=>{
- console.log("sum或者count改变了",newVal,oldVal)
- },{immediate:true})
-
-
- //情况三:监视reactive所定义的一个响应式数据
- //1.注意:次数无法正确的获取oldValue
- //2.注意:强制开启了深度监视(depp配置无效)
- watch(job,()=>{
- console.log("job改变了")
- },{immediate:true})
-
- //情况四:Jin啊哈斯reactive所定义的一个响应式数据中的某个属性
- watch(()=>job.type,()=>{
- console.log("job.type改变了")
- },{immediate:true})
-
- //情况五:监视reactive所定义的一个响应式数据中的某些属性
- watch([()=>job.type,()=>job.name],()=>{
- console.log("job.type或者job.name改变了")
- },{immediate:true})
-
- //特殊情况,如果监视的属性是对象,需要开启深度监视
- watch(()=>job.xin,()=>{
- console.log("job.type或者job.name改变了")
- },{immediate:true,deep:true})
-
- function fun(){
- job.type="后端工程师";
- job.xin.name="哈哈哈";
- console.log(this);
- }
-
- return {
- sum,count,job,fun
- }
- }
- }
- script>
- //watchEffact所指定的回调中用到的数据只要发生变化,则直接重新执行回调
- watchEffect(()=>{
- const x1=sum.value
- const x2=parson.age
- console.log('watchEffer配置的回调执行了')
- })
Vue3中可以继续使用Vue2中的生命钩子,但是有两个函数改名了:
| Vue2 | Vue3 |
|---|---|
| beforeDestroy() | beforeUnmout() |
| destroyed() | unmounted() |
Vue3也提供了Composition API形式的生命钩子,如果在setup与配置项中都写了钩子,写在setup中的钩子执行优先级比写在配置项中高,使用之前需要先import引入,与Vue2中钩子对应关系如下:
| Vue2 | Vue3 |
|---|---|
| beforeCreate() | setup() |
| create() | setup() |
| beforeMount() | onBeforeMount() |
| mounted() | onMounted() |
| beforeUpdate() | onBeforeUpdate() |
| updated() | onUpdated() |
| beforeUnmount() | onBeforeUnmount() |
| unmounted() | onUnmounte() |
示例
hooks/hook.js
- import {onMounted,onBeforeUnmount,reactive} from "vue"
-
- export default function(){
- let point = reactive({
- x:0,
- y:0
- })
-
- function savePoint(event){
- point.x=event.pageX
- point.y=event.pageY
- console.log("X:",event.pageX," Y:",event.pageY)
- }
-
- onMounted(()=>{
- window.addEventListener("click",savePoint)
- })
-
- onBeforeUnmount(()=>{
- window.removeEventListener("click",savePoint)
- })
-
- return point;
- }
App.vue
- <template>
- <h2>X:{{point.x}} Y:{{point.y}}h2>
- template>
-
- <script>
- import hookFun from "./hooks/hook"
-
- export default {
- name: 'App',
- setup(){
- let point=hookFun();
- return {
- point
- }
- }
- }
- script>
- <template>
- <h2>{{name}}h2>
- <h2>{{xin}}h2>
- <h2>{{mes}}h2>
- <button @click="fun">按钮button>
- template>
-
- <script>
- import { reactive, toRef, toRefs } from '@vue/reactivity'
-
- export default {
- name: 'App',
- setup(){
-
- const obj=reactive({
- name:"李义新",
- mes:"haha",
- xin:{
- age:11,
- sex:"男"
- }
- })
-
- const name=toRef(obj,"name");
- const xin=toRef(obj,"xin");
-
- function fun(){
- obj.name='李二新',
- obj.xin.age=222
- }
-
- return {
- name,xin,fun,
- ...toRefs(obj) //把所有属性都封装成Ref类型
- }
- }
- }
- script>
- <template>
- <input type="text" v-model="keyWord">
- <h3>{{keyWord}}h3>
- template>
-
- <script>
- import {ref,customRef} from 'vue'
- export default {
- name: 'App',
- setup() {
- //自定义一个ref——名为:myRef
- function myRef(value,delay){
- let timer
- return customRef((track,trigger)=>{
- return {
- get(){
- console.log(`有人从myRef这个容器中读取数据了,我把${value}给他了`)
- track() //通知Vue追踪value的变化(提前和get商量一下,让他认为这个value是有用的)
- return value
- },
- set(newValue){
- console.log(`有人把myRef这个容器中数据改为了:${newValue}`)
- clearTimeout(timer)
- timer = setTimeout(()=>{
- value = newValue
- trigger() //通知Vue去重新解析模板
- },delay)
- },
- }
- })
- }
-
- // let keyWord = ref('hello') //使用Vue提供的ref
- let keyWord = myRef('hello',500) //使用程序员自定义的ref
-
- return {keyWord}
- }
- }
- script>
-
- setup(){
- let car = reactive({name:"xin",price:"100k"})
- provide('car',car);
- }
孙组件中:
- setup(){
- const car = inject('car');
- return{car};
- }
Teleport是一种能够将我们的组件html结构移动到指定位置的技术。
参数to中可以写标签,也可以写css选择器。
- <teleport to="body">
- <div>
- <div>
- <h1>我是一个标签h1>
- div>
- div>
- teleport>
- <template>
- <div>
- <h1>我是App组件h1>
- <Suspense>
-
- <template v-slot:default>
- <Child/>
- template>
-
-
- <template v-slot:default>
- <h2>稍等,加载中。。。h2>
- template>
- Suspense>
- div>
- template>
-
- <script>
- import {defineAsyocComponent} from 'vue'
- const Child = defineAsyncComponent(()=>import('./components/Child.vue'))
- export default {
- name:"App",
- components:{Child}
- }
- script>