目录
一、创建Vue3项目
1、传统创建方式
在vue安装配置成功后,启动命令行窗口,输入vue create 项目名称,即可开始创建:
运行后,选择vue版本,我们在此选择vue3:
创建成功,可根据下图所示路径找到所创建的项目:
以上为传统创建方式,编译相对较慢
2、与vite搭配使用创建vue项目
创建命令:npm create vite@latest 项目名称
在此我们选择vue项目(这里选择vue项目,则默认为vue3):
如果掌握TS,可选择vue-ts:
创建完成:
根据上述提示安装其依赖:
执行npm run dev 开始运行:
执行完成,通过local查看项目效果:
二、vue2与vue3的区别
1、v - if与v - for的优先级对比
vue2版本中 v - for > v - if
vue3版本中 v - for < v - if
2、v - for 中的Ref数组
vue2版本会自动把Ref填充内容
vue3版本需要手动填充
3、$children
vue2版本可访问当前示例的子组件
vue3版本中$children被移除,且不再支持
vue3版本使用示例:
<!-- 设置 -->
<HelloWorld msg="Welcome" ref="imu" />
<!-- 访问 -->
this.$refs.imu
三、setup的使用
1、setup的定义
setup为vue3版本新引入内容,不适用于vue2版本
setup是一种组合式API,体现在其return中返回的任何内容都可以用于组件的其他部分
2、setup的作用
(一)原有的选项式API:处理相同逻辑关注点的代码被强制拆分在了不同的选项中,位于文件的不同部分。在一个几百行的大组件中,要读懂代码中的一个逻辑关注点,需要在文件中反复上下滚动,这并不理想。另外,如果我们想将一个逻辑关注点抽取重构到一个可复用的工具函数中,需要从文件的多个不同部分找到所需的正确片段。
(二)组合式API:与同一个逻辑关注点相关的代码被归为了一组:①无需再为了一个逻辑关注点在不同的选项块间来回滚动切换;②现在可以很轻松地将这一组代码移动到一个外部文件中,不再需要为了抽象而重新组织代码,大大降低了重构成本,这在长期维护的大型项目中非常关键。
3、响应区别
vue2.x:Object.defineProperty()
vue3.x:Proxy
例:
let Y = {
a:1,
b:2,
arr:[4,5,6]
}
// vue2写法
let L = {};
Object.keys(Y).forEach( key=>{
Object.defineProperty( L , key ,{
get(){
return Y[key];
}
set(){
console.log("修改");
}
})
})
L.a = 7;
// L.arr[0] = 7;
console.log(L);
// vue3写法
let L = new Proxy(Y,{
get(target,key){
return target[key];
}
set(){
console.log("修改");
}
})
L.a = 7;
// L.arr[0] = 7;
console.log(L);
性能总结:Object.defineProperty()不能监听数组变化,必须监听每一个属性。而Proxy不需要遍历
4、使用渲染函数
ref:用于定义简单类型数据(如接口返回一个简单数组,可用ref)
reactive:用于定义复杂类型数据(如接口返回一个对象,可用reactive)
5、toRefs
toRefs函数,用于完成数据的结构
let obj = reactive({
name = 'YYB',
age = 24
})
let { name , age } = toRefs(obj);
const toUse = ()=>{
console.log(name)
}
// 触发toUse时,执行console.log(name),显示值为YYB
6、computed
computed三种使用方法如下:
// 方法一
let obj = reactive({
name:'YYB',
age:24,
str:computed(()=>{
return obj.name.slice(1,2) //最终返回结果为Y
})
})
// 方法二
let objChange = computed(()=>{
return obj.name.slice(1,2) //最终返回结果为Y
})
// 方法三
let objChange = computed({
get(){
return obj.name.slice(1,2) //最终返回结果为Y
}
set(){
*******
}
})
7、watch
(一)Vue2选项式API案例:
<div>
<input type="text" name="msg" v-model='msg'>
<input type="text" name="obj" v-model='obj.a'>
</div>
export default{
data (){
return{
msg:'数据'
obj:{
a:1
}
}
},
watch:{
// 1
msg( newData , oldData ){ // 当值被修改时,才输出被监听的新的值与旧的值
console.log(newData,oldData)
}
// 2
msg:{
handler( newData , oldData ){ // 立刻输出被监听的新的值与旧的值,但值被更改时无法监听对象里的值
console.log(newData,oldData)
},
immediate:true // 用于立即输出监听对象
}
// 3
obj:{
handler( newData , oldData ){ // 立刻输出被深度监听的新的对象里的值与旧的对象里的值
console.log(newData,oldData)
},
immediate:true, // 用于立即输出监听对象
deep:true // 用于深度监听
}
}
}
(二)Vue3组合式API案例:
<div>
<input type="text" name="msg" v-model='msg'>
<input type="text" name="msg" v-model='str'>
<input type="text" name="msg" v-model='obj.arr'>
</div>
监听数据
import { ref , reactive , computed , watch }
export default{
setup(){
let msg = ref('数据');
watch( msg , (newData,oldData)=>{
console.log(newData,oldData)
},{
immediate:true
})
return {
msg
}
}
}
多个数据一起监听
import { ref , reactive , computed , watch }
export default{
setup(){
let msg = ref('数据1');
let str = ref('数据2');
watch( [msg,str] , (newData,oldData)=>{
console.log(newData,oldData)
},{
immediate:true
})
return {
msg,
str
}
}
}
监听对象中某个对象
import { ref , reactive , computed , watch }
export default{
setup(){
let obj = reactive({
a:1,
arr:['a','b','c']
});
watch( ()=>obj.arr , (newData,oldData)=>{
console.log(newData,oldData)
},{
immediate:true
})
return {
obj
}
}
}
watchEffect的使用
import { ref , reactive , computed , watch , watchEffect }
export default{
setup(){
let msg = ref('数据1');
let str = ref('数据2');
let obj = reactive({
a:1,
arr:['a','b','c']
});
watchEffect(()=>{ // 立即执行监听函数,当不确定监听某个函数时,可使用,当有函数变动时,可监听函数变动
console.log( msg.value )
console.log( str.value )
// ...
})
return {
msg,
str,
obj
}
}
}
参考链接:https://v3.cn.vuejs.org/api/computed-watch-api.html#watcheffect
四、生命周期
选项式API | Hood inside(setup) |
beforeCreate | Not needed* |
created | Not needed* |
beforeMount | onBeforeMount |
mounted | onMounted |
beforeUpdate | onBeforeUpdate |
updated | onUpdated |
beforeUnmount | onBeforeUnmount |
unmounted | onUnmounted |
errorCaptured | onErrorCaptured |
renderTracked | onRenderTracked |
renderTriggered | onRenderTriggered |
activated | onActivated |
deactivated | onDeactivated |
参考链接:https://v3.cn.vuejs.org/guide/composition-api-lifecycle-hooks.html
若同时存在选项式API与组合式API的某个生命周期,先执行组合式API(setup)
五、路由(router)
router使用方法
import { createRouter, createWebHistory, createWebHashHistory } from "vue-router";
import HomeView from "../views/HomeView.vue";
const routes = [
{
path:"/",
name:"HomeView",
component:HomeView,
},
{
path:"/about",
name:"AboutView",
component:() =>
import("../views/AboutView.vue")
}
];
const router = createRouter({
history: createWebHistory('/admin'), // 设定初始主界面
// history: createWebHashHistory('/admin'), // 设定初始主界面(哈希模式)
routes,
});
router-link页面直接跳转方法:
<div>
<router-link to='/about'>关于我们</router-link> // “/about”为目标子路径
</div>
router-link运用TS跳转方法(选项式API):
<template>
<div>
<button @click="go">Go</button>
</div>
</template>
<script lang="ts">
export default {
methods:{
go(){
this.$router.push('/about')
}
}
}
</script>
router-link运用TS跳转方法(使用setup):
注:setup是没有this的
<template>
<div>
<button @click="go">Go</button>
</div>
</template>
<script lang="ts">
import { useRoute, useRouter} from "vue-router";
export default {
setup(){
let use = new useRouter;
let go = ()=>{
use.push('/about')
}
return { go }
}
}
六、关系传值
1、父传子
设定子组件代码:
<template>
<div>
子组件 ===> {{ msg }}}
</div>
</template>
<script setup>
defineProps({
msg:{
type:String,
default:'1111'
}
})
</script>
设定父组件:
<template>
<div>
<List :msg='msg'></List>
</div>
</template>
<script setup>
import List from '../url.vue'
import {ref} from "vue";
let msg = ref ('父级数据');
</script>
2、子传父
设定子组件代码:
<template>
<div>
这是子组件 ===> {{ num }}
<button @click='changeNum' >按钮</button>
</div>
</template>
<script setup lang="ts">
import {ref} from "vue";
let num = ref(200);
const emit =defineEmits<{ // defineEmits用于声明事件或传参
(e: 'fn',id: number): void
}>()
const changeNum = ()=>{
emit('fn',num.value)
}
</script>
设定父组件:
<template>
<div>
<List @fn='changeHome'></List>
</div>
</template>
<script setup>
import List from '../url.vue'
const changeHome = ( n ) => {
console.log(n.value);
}
</script>
3、父子组件双向数据传输(利用v-model传值)
设定子组件代码:
<template>
<div>
这是子组件 ===> {{ num }}
<button @click='btn' >按钮</button>
</div>
</template>
<script setup>
import List from '../url.vue'
const props = defineProps({
num:{
type:Number,
default:100
}
})
const emit = defineEmits(['update:num'])
const btn = ()=>{
emit('update:num',200);
}
</script>
设定父组件:
<template>
<div>
<List v-model:num = 'num'></List>
</div>
</template>
<script setup>
import List from '../url.vue';
import {ref} from "vue";
let num = ref(1);
</script>
4、兄弟组件之间的传值(利用mitt插件)
(一)mitt安装:
npm install mitt -S
(二)新建js文件便于使用
// plugins/Bus.js
import mitt from 'mitt';
export default mitt();
(三)传输组件与接收组件
// A组件(传输)
mitt.emit('fn',str); // str为传输的数据
// B组件(接收)
mitt.on('fn',e=>{
s.value = e.value; // s为要展示的数据
})
vue3学习笔记将分两部分进行记录,今日将更新第二部分!!!
如果能解决您的问题,记得收藏+关注呀!!!
创作时间:2022.8.25
文章编号YU.NO.5