Vue3知识点进来学习辣!

143 阅读4分钟

Vue3


1.toRef 方法

掌握toRef 方法的使用 方式及应用场景

一个小案例进行入门开始:

当按钮被点击时模版数据发生更新?

<template>
  <p>{{ name }}</p> //数据不改变,
  <p>{{ person.name }}</p>
  <button @click="onClickHandler">button</button>
</template><script>
import { ref } from 'vue';
export default {
  name:"App",
  setup() {
    const person = ref({name:"张三"});
    const onClickHandler = () => {
      person.value.name = "李四"
    }
    return {
      name:person.value.name,
      person,
      onClickHandler,
    }
  }
}
</script>

toRef 方法用于将响应式数据内部的普通数据转换为响应式数据,并且转换后的数据和原始数据存在引用关系,存在引用关系意味着当原始数据发生变化后,toRef转换后的数据也会跟着变化。

<template>
  <p>{{ name }}</p>
  <p>{{ person.name }}</p>
  <button @click="onClickHandler">button</button>
</template><script>
import { ref, toRef } from "vue";
export default {
  name: "App",
  setup() {
    const person = ref({ name: "张三" });
    const onClickHandler = () => {
      person.value.name = "李四";
    };
    return {
      name: toRef(person.value, "name"),
      person,
      onClickHandler,
    };
  },
};
</script>

需求:当响应式数据的结构层级比较深时,在模版中使用起来也比较繁琐,能不能在模版中使用时简化结构层级呢?

export default {
  setup() {
    const person = ref({brand:{name:"宝马"}});
    return {
      person
    }
  }
}
<template>
  {{person.brand.name}}
</template>

如果能够将模版中的person.brand.name简化成brandName的话不就更加简洁?

import { ref } from "vue";
export default {
  name:"App",
  setup() {
    const person = ref({brand:{name:"宝马"}})
    const onClickHandler = () => {
      person.value.brand.name = "奔驰"
    }
    return {
      person,
      brandName: person.value.brand.name,
      onClickHandler
    }
  }
}
<template>
  <p>
    {{person}}
  </p>
  <p>
    {{brandName}}
  </p>
  <button @click="onClickHandler">
    button
  </button>
</template>
import { ref } from "vue";
export default {
  name:"App",
  setup() {
    const person = ref({brand:{name:"宝马"}})
    const onClickHandler = () => {
      person.value.brand.name = "奔驰"
    }
    return {
      person,
      brandName: toRef(person.value.brand,"name"),
      onClickHandler
    }
  }
}

2.toRefs函数

掌握toRefs 方法批量转换响应式数据的方式。

toRef一次只能转换一次数据,通过toRefs方法可以实现批量数据的转换.

toRefs 方法接收引用数据类型的响应式数据,它可以将数据中的第一层属性全部转换为响应式数据,返回值是一个对象, 对象中存储了所有转换之后的响应式数据.

import {reactive,toRefs} from "vue";
export default {
  name:"App",
  setup() {
    const person = reactive({
      name:"张三",
      age:20,
      brand:{title:"宝马",year:1}
    })
    return {
      ...toRefs(person),...toRefs(person.brand) 
    }
  }
}
<template>{{ name }} {{ age }} {{ title }} {{ year }}</template> //结果是依据以上reactive顺序进行输出

3.组件通讯

掌握组合式API中父子组件通信的方式

父组件给子组件传递数据通过子组件用props进行接收,例子如下:

<template>
  <div>I am parent component</div>
  <hr /> 
  <ChildComp :msg="msg"></ChildComp>
</template><script>
import ChildComp from "./components/ChildComp.vue"
import { ref } from "vue"
export default {
  components: { ChildComp },
  setup() {
    const msg = ref("a message from parent")
    return { msg }
  },
}
</script>
<template>
  <div>
    {{ childMsg }}
    <hr />
    {{ msg }}
  </div>
</template>
<script>
import { computed } from "vue";
export default {
  name: "ChildComponent",
  props: ["msg"],
  setup(props) {
    // 当父组件更新 props 时 setup 函数是不会重新执行的
    // 所以在 setup 函数中使用 props 时需要用到 computed 或者 watch 来响应 props 的变化
    // 注意: 直接在模板中使用 props 数据是没有这个问题的
    const childMsg = computed(() => props.msg + "😀😀");
    return { childMsg };
  },
};
</script>

子组件给父组件传递数据

<template>
  <div>
    {{ childMsg }}
    <hr />
    {{ msg }}
    <hr />
    <button @click="onMsgChanged">change msg</button>
  </div>
</template>
<script>
import { computed } from "vue";
​
export default {
  name: "ChildComponent",
  props: ["msg"],
  emits:["onMsgChanged"] //如果在模版中时使用代码片段,自定义时间需要被显示的声明在emits选项中
  setup(props, { emit }) {
    const onMsgChanged = () => {
      emit("onMsgChanged", "changed msg from children");
    };
    return { onMsgChanged };
  },
};
</script>

解析:首先给button绑定一个事件,当点击这个按钮的时候通过props第二个参数emits出发父组件事件进行数据传递以及更改。

<template>
  <ChildComponent :msg="msg" @onMsgChanged="onMsgChanged" />
</template><script>
import { ref } from "vue";
import ChildComponent from "./components/child-component.vue";
export default {
  components: { ChildComponent },
  name: "App",
  setup() {
    const msg = ref("i am a message");
    const onMsgChanged = (data) => {
      msg.value = data;
    };
    return { msg, onMsgChanged };
  },
};
</script>

父组件接收到自定义事件的数据也就是changed msg from children 用一个数据接收并且把msg里面的数据改成传递过来的数据。


4.组件生命周期

掌握组件生命周期函数的使用方式

setup 组件初次挂载前,重新挂载前都会执行

<!-- App组件 父组件  -->
<template>
  <button @click="show = !show">toggle</button>
  <ChildComponent v-if="show"></ChildComponent>
</template><script>
import { ref } from "vue";
import ChildComponent from "./components/child-component.vue";
export default {
  components: { ChildComponent },
  name: "App",
  setup() {
    const show = ref(true);
    return { show };
  },
};
</script>
<!-- ChildComponent 组件 子组件 -->
<template>child component</template>
<script>
export default {
  name: "ChildComponent",
  setup() {
    // setup 函数会在组件每次重新渲染时执行
    console.log("setup"); ->>>>>>>>>> 记住这里 
  },
};
</script>

解析一下,就是setup是挂载前和重新挂载后都会执行一次setup函数

<!-- child-component  -->
<template>{{ count }} <button @click="onClickHandler">button</button></template>
<script>
import { onMounted, onUnmounted, onUpdated, ref } from "vue";
​
export default {
  name: "ChildComponent",
  setup() {
    console.log("setup");
    let timer = null;
    // 组件挂载完成之后开启定时器
    onMounted(() => {
      timer = setInterval(() => {
        console.log("timer...");
      }, 1000);
    });
    // 组件卸载完成之后清除定时器
    onUnmounted(() => {
      clearInterval(timer);
    });
    const count = ref(0);
    const onClickHandler = () => {
      count.value = count.value + 1;
    };
    // 组件更新之后在控制台中输出 onUpdated
    onUpdated(() => {
      console.log("onUpdated");
    });
    return { count, onClickHandler };
  },
};
</script>

结果走向:第一 ,从之前我们知道,只要组件一挂载起来setup第一个执行,onMouted是组件挂载完成后执行输出以上代码的定时器,如果数据已更新后onUpdated就回执行,再者就是onUnmounted是组件卸载后执行。


5.与服务端通信

掌握组合式API实现与服务器通讯的方式

向服务器端发送请求获取略表数据渲染列表数据,没有数据显示暂无数据,如果请求报错则展示错误信息,加载过程显示loading

​
  import {ref} from "vue";
  import axios from "axios";
  
  export default {
    //用于存储列表的数据
    const data = ref(null);
    //用于标示加载状态
    const loading = ref(false);
    //用于存储错误信息
    const error = ref(null);
    //用于发送请求的方法
    async function getPosts() {
      //  更新加载状态
      loading.value = true;
      try {
        //发送请求
        let response = await axios.get("https://jsonplaceholder.typicode.com/posts")
        //存储列表数据
        data.value = response.data;
        
      } catch(err) {
        err.value = err.message;
      }
      //更新加载状态
      loading.value = false
    }
    //调用方放,发送请求
    getPosts()
    return {
      data,loading.error
    }
    
  }
​
<template>
  <div v-if="loading">加载中...</div>
  <div v-else-if="error">{{ error }}</div>
  <div v-else-if="data && data.length > 0">
    <ul>
      <li v-for="item in data">{{ item.title }}</li>
    </ul>
  </div>
  <div v-else>暂无数据</div>
</template>

代码进行抽离修改成为如下代码:


6.获取DOM对象

掌握组合式API获取DOM对象方式

1.获取单个DOM对象

import {ref,onMounted} from "vue";
export default {
  setup() {
    const divRef = ref(null)
    onMounted(()=> {
      console.log(divRef.value)
    })
    return {divRef}
  }
}
<template>
  <div ref="divRef">
    我是被获取的dom对象
  </div>
</template>

2.获取多个dom对象

import {ref,onMounted,onUpdated} from "vue";
export default {
  setup() {
    const list = ref(['a','b','c'])
    const list1 = ref([])
    const onClickHandler = () => {
      list.value.push('d')
      
    }
    onMounted(()=> console.log(list1.value))
   onUpdated(()=> console.log(list1.value))
    return {list,list1,onClickHandler}
  }
}
<template>
  <ul>
    <li v-for="(item, index) in list" :key="index" :ref="(el) => (list1[index] = el)">
      {{ item }}
    </li>
  </ul>
  <button @click="onClickHandler">button</button>
</template>

7.provide,inject函数

掌握夸组件层级传递数据的方式

通过provide和inject配合使用可以实现夸组件传递数据(组件与组件是存在嵌套关系)

<!-- 父组件 App -->
<template>
  <ChildComponent />
</template><script>
import { ref, provide } from "vue";
import ChildComponent from "./components/ChildComponent.vue";
​
export default {
  components: { ChildComponent },
  name: "App",
  setup() {
    const person = ref({ name: "张三" });
    const changePerson = () => {
      person.value.name = "李四";
    };
    provide("person", person);
    provide("changePerson", changePerson);
  },
};
</script>
<!-- 子组件 -->
<template>
  <LastComponent />
</template>
<script>
import LastComponent from "./LastComponent.vue";
export default {
  components: { LastComponent },
  name: "ChildComponent",
};
</script>
<!-- 孙组件 -->
<template>
  {{ person.name }}
  <button @click="changePerson">button</button>
</template>
<script>
import { inject } from "vue";
export default {
  name: "LastComponent",
  setup() {
    const person = inject("person");
    const changePerson = inject("changePerson");
    return { person, changePerson };
  },
};
</script>

\