Vue.js教程(八)

目录

Vue3

优点

Vue脚手架 Vue CLI 创建一个Vue3的项目

1:安装脚手架

2:创建一个项目

3:Vue初始项目文件

main.js

App.vue

Vue3的Composition API

setup 函数

setup 的参数

        参数:props

        参数:context

ref 函数

reactive 函数

ref 和 reactive 的区别

setup 的 computed 函数

setup 的 watch函数

setup 的 watchEffect 函数

setup 的 toRef 函数

setup 的 toRefs 函数

Vue3中的生命周期函数

多层嵌套组件之间的通讯


Vue3

优点

  • 更小的打包体积和内存
  • 更好的支持 TypeScript
  • 页面第一次的渲染速度和更新速度更快
  • 新增了 Composition API 和内置组件

Vue脚手架 Vue CLI 创建一个Vue3的项目

1:安装脚手架

npm install -g @vue/cli

Node 版本要求
Vue CLI 4.x 需要 Node.js v8.9 或更高版本 (推荐 v10 以上)。你可以使用 n,nvm 或 nvm-windows 在同一台电脑中管理多个 Node 版本。

2:创建一个项目

vue create hello-vue3

报错:vue : 无法加载文件xxx 因为在此系统上禁止运行脚本

解决:以管理员身份运行VS Code,在终端输入 set-ExecutionPolicy RemoteSigned 即可。

使用 vue -V 查看 Vue CLI版本

vue -V

选择  Vue 3 

然后

cd hello-vue3

npm run serve

打开网页 http://localhost:8080。这样一个 Vue3 脚手架项目就创建完成了

3:Vue初始项目文件

  • main.js

整个项目的入口文件

  • App.vue

所有⼦组件的⽗组件


Vue3的Composition API

  • setup 函数

  • setup 函数是Vue3新的配置项
  • 是使用组合API的前提,数据、方法都要放到 setup 函数里声明
  • 在生命周期函数 beforeCreate 之前执行一次,而且 setup 函数没有 this
<template>
	<div>姓名:{{name}}</div>
	<div>年龄:{{age}}</div>
	<button @click="hello">打招呼</button>
</template>
<script>
export default {
	setup() {				// setup函数,里面使用 js 原生语法
		let name = '张三';
		let age = 18;
		function hello () {
			alert(`你好,我是${name},今年${age}岁了`);
		}
		return {	// vue 中要使用 setup 里定义的变量、函数的话,需要把变量、函数 return 出去
			name,
			age,
			hello
		}
	}
}
</script>
  • setup 的参数

        参数:props

用于接收父组件的值

<script>
export default {
	props: ["msg"],	// 接收父组件的值
	setup(props) {
		console.log(props.msg);	// setup 中获取父组件的值
	}
}
</script>

        参数:context

上下文对象,触发自定义事件

        父组件代码

<template>
	<!-- 定义自定义事件 -->
	<HelloWorld @dj="handleDianji"/>
</template>

<script>
import HelloWorld from './components/HelloWorld.vue'

export default {
	components: {
		HelloWorld
	},
	setup() {
		// 自定义事件回调
		function handleDianji(value) {
			console.log("打印子组件传过来的值=", value);
		}
		return {
			handleDianji
		}
	}
}
</script>

        子组件代码

<template>
	<button @click="dianji">点击</button>
</template>
<script>
export default {
	emits: ["dj"],			// 声明自定义事件
	setup(props, context) {
		function dianji() {
			context.emit("dj", "我是子组件的值");	// 触发自定义事件
		}
		return {
			dianji
		}
	}
}
</script>

  • ref 函数

实现数据的响应式        // setup定义的变量数据,如果想通过setup中定义的函数改变数据是没有作用的。这里就要用到 ref 函数改变数据

  • 可以处理基本类型数据、数组或者对象类型的数据
  • 基本类型数据的响应式是通过 Object.defineProperty() 实现
  • 对象类型数据的响应式是通过 ES6 中的 Proxy 实现
<template>
	<div>姓名:{{name}}</div>
	<div>年龄:{{age}}</div>
	<div>性别:{{obj.sex}}</div>
	<button @click="hello">打招呼</button>
	<button @click="changePreson">切换人员</button>
</template>
<script>
import { ref } from "vue";			// 引入 ref 函数

export default {
	setup() {
		let name = ref("张三");		// ref 操作基本数据类型
		let age = ref(18);

		let obj = ref({				// ref 操作对象
			sex: "man"
		});

		function hello() {
			alert(`你好,我是${name.value},今年${age.value}岁了, 性别${obj.value.sex}`);
		}

		function changePreson() {
			name.value = "李四";
			age.value = "20";
			obj.value.sex = "female"
		}

		return {
			name,
			age,
			obj,
			hello,
			changePreson
		}
	}
}
</script>

  • reactive 函数

定义一个对象类型的响应式数据(不能处理基本类型数据)

<template>
	<div>姓名:{{name}}</div>
	<div>年龄:{{age}}</div>
	<div>性别:{{obj.sex}}</div>
	<button @click="hello">打招呼</button>
	<button @click="changePreson">切换人员</button>
</template>
<script>
import { ref, reactive } from "vue";			// 引入 ref 函数

export default {
	setup() {
		let name = ref("张三");		// ref 操作基本数据类型
		let age = ref(18);

		let obj = reactive({		// reactive 操作对象
			sex: "man"
		});

		function hello() {
			alert(`你好,我是${name.value},今年${age.value}岁了, 性别${obj.sex}`);
		}

		function changePreson() {
			name.value = "李四";
			age.value = "20";
			obj.sex = "female"
		}

		return {
			name,
			age,
			obj,
			hello,
			changePreson
		}
	}
}
</script>

  • ref 和 reactive 的区别

  • 处理数据类型不同:ref 可以处理基本类型和对象(数组)类型数据, reactive 只能处理对象(数组)类型数据
  • 实现原理不同:ref 处理基本类型数据通过 Object.defineProperty() 实现, reactive 通过Proxy 实现
  • 操作不同: ref 操作数据需要加 .value

  • setup 的 computed 函数

<template>
	<div>{{fullName}}</div>
</template>
<script>
import { ref, computed } from "vue";
export default {
	setup() {
		let firstName = ref("张");
		let lastName = ref("三");
		let fullName = computed({
			get() {
				return firstName.value + "-" + lastName.value;
			},
			set(value) {
				const arr = value.split("-");
				firstName.value = arr[0];
				lastName.value = arr[1];
			}
		})
		return {
			firstName,
			lastName,
			fullName
		}
	}
}
</script>

  • setup 的 watch函数

<template>
	<h1>
		当前的计数a:<span>{{ numa }}</span> <br />
		当前的计数b:<span>{{ numb }}</span> <br />
	</h1>
	<button @click="numa++">增加a</button>
	<button @click="numb++">增加b</button>
	<hr />
</template>
<script>
import { ref, watch } from "vue";
export default {
	setup() {
		let numa = ref(1);
		let numb = ref(1);

		watch([numa, numb], (newValue, oldValue) => {
			console.log("numa或者numb变化了", newValue, oldValue);
		}, { immediate: true, deep: true });

		return {
			numa,
			numb
		};
	},
};
</script>

监听对象

watch(numObj, (newValue, oldValue) => {
	console.log("numObj变化了", newValue, oldValue);
})

监听对象中的一个基本类型属性

watch(
	() => numObj.a,
	(newValue, oldValue) => {
		console.log("numObj变化了", newValue, oldValue);
	}
);

监听对象中的一些基本类型属性

watch([() => numObj.a, () => numObj.b], (newValue, oldValue) => {
	console.log("numObj变化了", newValue, oldValue);
});

监听对象中的对象属性类型

watch(
	numObj.c,
	(newValue, oldValue) => {
		console.log("numObj.c变化了", newValue, oldValue);
	}
);
  • ref 定义的数据
    • 基本类型数据作为监听值
    • 对象作为监听值,需要加 .value (⽤的少)
  • reactive 定义的数据
    • 对象作为监听值
    • 属性作为监听值,需要放在回调函数中
  • 如果监听 reactive 定义的对象,则无法正确输出 oldValue ,且深度监听是强制开启的,无法关闭 (vue3配置)

  • setup 的 watchEffect 函数

在监听的回调函数中使⽤了属性,则监听该属性,不⽤在参数上指明监听哪个属性

<script>
import { ref, watchEffect } from "vue";
export default {
	setup() {
		let numa = ref(1);
		watchEffect(() => {
			console.log(numa.value);	// 在监听中使用了 numa 属性,就默认监听此属性
			console.log("watchEffect函数执行了");
		});
		return {
			numa
		};
	}
};
</script>
  • setup 的 toRef 函数

创建一个 ref 对象,其 value 值指向另一个对象中指定的属性        // 相当于起了个别名

<template>
	<h1>
		<!-- {{data.name}} // 未使用toRef的方式 -->
		{{aliasName}}	<!-- 使用 toRef 的方式-->
	</h1>
</template>
<script>
import { reactive, toRef} from "vue";
export default {
	setup() {
		let data = reactive({
			name: "张三"
		});

		let aliasName = toRef(data, "name");	// 相当于 把data的name属性定义了一个别名

		return {
			data,
			aliasName,
		}
	}
};
</script>
  • setup 的 toRefs 函数

批量创建 ref 对象,其 value 值指向另一个对象        // 相当于批量起别名

<template>
	<h1>
		{{name}}	
		{{age}}	
	</h1>
</template>
<script>
import { reactive, toRefs} from "vue";
export default {
	setup() {
		let data = reactive({
			name: "张三",
			age: 18
		});

		return {
			...toRefs(data)
		}
	}
};
</script>
  

Vue3中的生命周期函数

<script>
import { onBeforeMount, onMounted, onBeforeUpdate,  onUpdated, onBeforeUnmount, onUnmounted} from "vue";
export default {
	setup() {
		console.log("===setup===");

		onBeforeMount(()=>{
			console.log("===挂载前===");
		})
		onMounted(()=>{
			console.log("===挂载后===");
		})
		onBeforeUpdate(()=>{
			console.log("===更新前===");
		})
		onUpdated(()=>{
			console.log("===更新后===");
		})
		onBeforeUnmount(()=>{
			console.log("===卸载前===");
		})
		onUnmounted(()=>{
			console.log("===卸载后===");
		})
	}
};
</script>

多层嵌套组件之间的通讯

  • provide:祖组件使用此函数传递数据
  • inject:后代组件使用此函数接收数据
// 上级组件代码
<script>
import { ref, reactive, provide } from 'vue';
export default {
	components: {
		HelloWorld
	},
	setup() {
		let name = ref("张三");
		provide("name", name)		// 父组件使用 provide 向下级(多级都可以)组件传值

		let obj = reactive({
			name: "李四",
			age: 18
		});
		provide("obj", obj);
	}
}
</script>
// 下级(多层下级都可以)组件代码
<script>
import { inject } from "vue";
export default {
	setup() {
		let name = inject("name");
		console.log("下级组件接收到值=",name.value);

		let obj = inject("obj");
		console.log("下级组件接收到值=",obj);
	}
};
</script>

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

又逢乱世

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值