Vue 所有代码资料仓库

# Vue3.0 的使用

# src_分析工程结构

main.js
// 引入的不再是 Vue 构造函数了,引入的是一个名为 createApp 的工厂函数
import { createApp } from 'vue'
import App from './App.vue'
// 创建应用实例对象 ——app (类似于之前 Vue2 中的 vm,但 app 比 vm 更 “轻”)
const app = createApp(App)
// 挂载
app.mount('#app')
App.vue
<template>
	<!-- Vue3 组件中的模板结构可以没有根标签 -->
	<img alt="Vue logo" src="./assets/logo.png">
	<HelloWorld msg="Welcome to Your Vue.js App"/>
</template>
<script>
	import HelloWorld from './components/HelloWorld.vue'
	export default {
		name: 'App',
		components: {
			HelloWorld
		}
	}
</script>
<style>
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
</style>
HelloWorld.vue
<template>
  <div class="hello">
    <h1>{ { msg } }</h1>
    <p>
      For a guide and recipes on how to configure / customize this project,<br>
      check out the
      <a href="https://cli.vuejs.org" target="_blank" rel="noopener">vue-cli documentation</a>.
    </p>
    <h3>Installed CLI Plugins</h3>
    <ul>
      <li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-babel" target="_blank" rel="noopener">babel</a></li>
      <li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-eslint" target="_blank" rel="noopener">eslint</a></li>
    </ul>
    <h3>Essential Links</h3>
    <ul>
      <li><a href="https://vuejs.org" target="_blank" rel="noopener">Core Docs</a></li>
      <li><a href="https://forum.vuejs.org" target="_blank" rel="noopener">Forum</a></li>
      <li><a href="https://chat.vuejs.org" target="_blank" rel="noopener">Community Chat</a></li>
      <li><a href="https://twitter.com/vuejs" target="_blank" rel="noopener">Twitter</a></li>
      <li><a href="https://news.vuejs.org" target="_blank" rel="noopener">News</a></li>
    </ul>
    <h3>Ecosystem</h3>
    <ul>
      <li><a href="https://router.vuejs.org" target="_blank" rel="noopener">vue-router</a></li>
      <li><a href="https://vuex.vuejs.org" target="_blank" rel="noopener">vuex</a></li>
      <li><a href="https://github.com/vuejs/vue-devtools#vue-devtools" target="_blank" rel="noopener">vue-devtools</a></li>
      <li><a href="https://vue-loader.vuejs.org" target="_blank" rel="noopener">vue-loader</a></li>
      <li><a href="https://github.com/vuejs/awesome-vue" target="_blank" rel="noopener">awesome-vue</a></li>
    </ul>
  </div>
</template>
<script>
export default {
  name: 'HelloWorld',
  props: {
    msg: String
  }
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
h3 {
  margin: 40px 0 0;
}
ul {
  list-style-type: none;
  padding: 0;
}
li {
  display: inline-block;
  margin: 0 10px;
}
a {
  color: #42b983;
}
</style>

# src_初识 setup

main.js
// 引入的不再是 Vue 构造函数了,引入的是一个名为 createApp 的工厂函数
import { createApp } from 'vue'
import App from './App.vue'
// 创建应用实例对象 ——app (类似于之前 Vue2 中的 vm,但 app 比 vm 更 “轻”)
const app = createApp(App)
// 挂载
app.mount('#app')
App.vue
<template>
	<h1>一个人的信息</h1>
	<h2>姓名:{ {name} }</h2>
	<h2>年龄:{ {age} }</h2>
	<h2>性别:{ {sex} }</h2>
	<h2>a的值是:{ {a} }</h2>
	<button @click="sayHello">说话(Vue3所配置的——sayHello)</button>
	<br>
	<br>
	<button @click="sayWelcome">说话(Vue2所配置的——sayWelcome)</button>
	<br>
	<br>
	<button @click="test1">测试一下在Vue2的配置中去读取Vue3中的数据、方法</button>
	<br>
	<br>
	<button @click="test2">测试一下在Vue3的setup配置中去读取Vue2中的数据、方法</button>
</template>
<script>
	// import {h} from 'vue'
	export default {
		name: 'App',
		data() {
			return {
				sex:'男',
				a:100
			}
		},
		methods: {
			sayWelcome(){
				alert('欢迎来到尚硅谷学习')
			},
			test1(){
				console.log(this.sex)
				console.log(this.name)
				console.log(this.age)
				console.log(this.sayHello)
			}
		},
		// 此处只是测试一下 setup,暂时不考虑响应式的问题。
		async setup(){
			// 数据
			let name = '张三'
			let age = 18
			let a = 200
			// 方法
			function sayHello(){
				alert(`我叫${name},我${age}岁了,你好啊!`)
			}
			function test2(){
				console.log(name)
				console.log(age)
				console.log(sayHello)
				console.log(this.sex)
				console.log(this.sayWelcome)
			}
			// 返回一个对象(常用)
			return {
				name,
				age,
				sayHello,
				test2,
				a
			}
			// 返回一个函数(渲染函数)
			//return ()=> h ('h1',' 尚硅谷 ')
		}
	}
</script>

# src_ref 函数

main.js
// 引入的不再是 Vue 构造函数了,引入的是一个名为 createApp 的工厂函数
import { createApp } from 'vue'
import App from './App.vue'
// 创建应用实例对象 ——app (类似于之前 Vue2 中的 vm,但 app 比 vm 更 “轻”)
const app = createApp(App)
// 挂载
app.mount('#app')
App.vue
<template>
	<h1>一个人的信息</h1>
	<h2>姓名:{ {name} }</h2>
	<h2>年龄:{ {age} }</h2>
	<h3>工作种类:{ {job.type} }</h3>
	<h3>工作薪水:{ {job.salary} }</h3>
	<button @click="changeInfo">修改人的信息</button>
</template>
<script>
	import {ref} from 'vue'
	export default {
		name: 'App',
		setup(){
			// 数据
			let name = ref('张三')
			let age = ref(18)
			let job = ref({
				type:'前端工程师',
				salary:'30K'
			})
			// 方法
			function changeInfo(){
				//name.value = ' 李四'
				// age.value = 48
				console.log(job.value)
				//job.value.type = 'UI 设计师'
				// job.value.salary = '60K'
				// console.log(name,age)
			}
			// 返回一个对象(常用)
			return {
				name,
				age,
				job,
				changeInfo
			}
		}
	}
</script>

# src_reactive 函数

main.js
// 引入的不再是 Vue 构造函数了,引入的是一个名为 createApp 的工厂函数
import { createApp } from 'vue'
import App from './App.vue'
// 创建应用实例对象 ——app (类似于之前 Vue2 中的 vm,但 app 比 vm 更 “轻”)
const app = createApp(App)
// 挂载
app.mount('#app')
App.vue
<template>
	<h1>一个人的信息</h1>
	<h2>姓名:{ {person.name} }</h2>
	<h2>年龄:{ {person.age} }</h2>
	<h3>工作种类:{ {person.job.type} }</h3>
	<h3>工作薪水:{ {person.job.salary} }</h3>
	<h3>爱好:{ {person.hobby} }</h3>
	<h3>测试的数据c:{ {person.job.a.b.c} }</h3>
	<button @click="changeInfo">修改人的信息</button>
</template>
<script>
	import {reactive} from 'vue'
	export default {
		name: 'App',
		setup(){
			// 数据
			let person = reactive({
				name:'张三',
				age:18,
				job:{
					type:'前端工程师',
					salary:'30K',
					a:{
						b:{
							c:666
						}
					}
				},
				hobby:['抽烟','喝酒','烫头']
			})
			// 方法
			function changeInfo(){
				person.name = '李四'
				person.age = 48
				person.job.type = 'UI设计师'
				person.job.salary = '60K'
				person.job.a.b.c = 999
				person.hobby[0] = '学习'
			}
			// 返回一个对象(常用)
			return {
				person,
				changeInfo
			}
		}
	}
</script>

# Vue3 的响应式原理

Vue3的响应式原理.html
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8" />
    <title>Document</title>
</head>
<body>
<script type="text/javascript" >
			// 源数据
			let person = {
				name:'张三',
				age:18
			}
			// 模拟 Vue2 中实现响应式
			//#region 
			/* let p = {}
			Object.defineProperty (p,'name',{
				configurable:true,
				get (){ // 有人读取 name 时调用
					return person.name
				},
				set (value){ // 有人修改 name 时调用
					console.log (' 有人修改了 name 属性,我发现了,我要去更新界面!')
					person.name = value
				}
			})
			Object.defineProperty (p,'age',{
				get (){ // 有人读取 age 时调用
					return person.age
				},
				set (value){ // 有人修改 age 时调用
					console.log (' 有人修改了 age 属性,我发现了,我要去更新界面!')
					person.age = value
				}
			}) */
			//#endregion
			
			// 模拟 Vue3 中实现响应式
			//#region 
			const p = new Proxy(person,{
				// 有人读取 p 的某个属性时调用
				get(target,propName){
					console.log(`有人读取了p身上的${propName}属性`)
					return Reflect.get(target,propName)
				},
				// 有人修改 p 的某个属性、或给 p 追加某个属性时调用
				set(target,propName,value){
					console.log(`有人修改了p身上的${propName}属性,我要去更新界面了!`)
					Reflect.set(target,propName,value)
				},
				// 有人删除 p 的某个属性时调用
				deleteProperty(target,propName){
					console.log(`有人删除了p身上的${propName}属性,我要去更新界面了!`)
					return Reflect.deleteProperty(target,propName)
				}
			})
			//#endregion
			let obj = {a:1,b:2}
			// 通过 Object.defineProperty 去操作
			//#region 
			/* try {
				Object.defineProperty(obj,'c',{
					get(){
						return 3
					}
				})
				Object.defineProperty(obj,'c',{
					get(){
						return 4
					}
				})
			} catch (error) {
				console.log(error)
			} */
			//#endregion
			// 通过 Reflect.defineProperty 去操作
			//#region 
			/* const x1 = Reflect.defineProperty (obj,'c',{
				get (){
					return 3
				}
			})
			console.log (x1)
			
			const x2 = Reflect.defineProperty (obj,'c',{
				get (){
					return 4
				}
			}) 
			if (x2){
				console.log (' 某某某操作成功了!')
			} else {
				console.log (' 某某某操作失败了!')
			} */
			//#endregion
			// console.log('@@@')
		</script>
</body>
</html>

# src_setup 的两个注意点

main.js
// 引入的不再是 Vue 构造函数了,引入的是一个名为 createApp 的工厂函数
import { createApp } from 'vue'
import App from './App.vue'
// 创建应用实例对象 ——app (类似于之前 Vue2 中的 vm,但 app 比 vm 更 “轻”)
const app = createApp(App)
// 挂载
app.mount('#app')
App.vue
<template>
	<Demo @hello="showHelloMsg" msg="你好啊" school="尚硅谷">
		<template v-slot:qwe>
			<span>尚硅谷</span>
		</template>
		<template v-slot:asd>
			<span>尚硅谷</span>
		</template>
	</Demo>
</template>
<script>
	import Demo from './components/Demo'
	export default {
		name: 'App',
		components:{Demo},
		setup(){
			function showHelloMsg(value){
				alert(`你好啊,你触发了hello事件,我收到的参数是:${value}`)
			}
			return {
				showHelloMsg
			}
		}
	}
</script>
Demo.vue
<template>
	<h1>一个人的信息</h1>
	<h2>姓名:{ {person.name} }</h2>
	<h2>年龄:{ {person.age} }</h2>
	<button @click="test">测试触发一下Demo组件的Hello事件</button>
</template>
<script>
	import {reactive} from 'vue'
	export default {
		name: 'Demo',
		props:['msg','school'],
		emits:['hello'],
		setup(props,context){
			// console.log('---setup---',props)
			// console.log('---setup---',context)
			//console.log ('---setup---',context.attrs) // 相当与 Vue2 中的 $attrs
			//console.log ('---setup---',context.emit) // 触发自定义事件的。
			console.log('---setup---',context.slots) // 插槽
			// 数据
			let person = reactive({
				name:'张三',
				age:18
			})
			// 方法
			function test(){
				context.emit('hello',666)
			}
			// 返回一个对象(常用)
			return {
				person,
				test
			}
		}
	}
</script>

# src_computed 函数

main.js
// 引入的不再是 Vue 构造函数了,引入的是一个名为 createApp 的工厂函数
import { createApp } from 'vue'
import App from './App.vue'
// 创建应用实例对象 ——app (类似于之前 Vue2 中的 vm,但 app 比 vm 更 “轻”)
const app = createApp(App)
// 挂载
app.mount('#app')
App.vue
<template>
	<Demo/>
</template>
<script>
	import Demo from './components/Demo'
	export default {
		name: 'App',
		components:{Demo},
	}
</script>
Demo.vue
<template>
	<h1>一个人的信息</h1>
	姓:<input type="text" v-model="person.firstName">
	<br>
	名:<input type="text" v-model="person.lastName">
	<br>
	<span>全名:{ {person.fullName} }</span>
	<br>
	全名:<input type="text" v-model="person.fullName">
</template>
<script>
	import {reactive,computed} from 'vue'
	export default {
		name: 'Demo',
		setup(){
			// 数据
			let person = reactive({
				firstName:'张',
				lastName:'三'
			})
			// 计算属性 —— 简写(没有考虑计算属性被修改的情况)
			/* person.fullName = computed(()=>{
				return person.firstName + '-' + person.lastName
			}) */
			// 计算属性 —— 完整写法(考虑读和写)
			person.fullName = computed({
				get(){
					return person.firstName + '-' + person.lastName
				},
				set(value){
					const nameArr = value.split('-')
					person.firstName = nameArr[0]
					person.lastName = nameArr[1]
				}
			})
			// 返回一个对象(常用)
			return {
				person
			}
		}
	}
</script>

# src_watch 函数

main.js
// 引入的不再是 Vue 构造函数了,引入的是一个名为 createApp 的工厂函数
import { createApp } from 'vue'
import App from './App.vue'
// 创建应用实例对象 ——app (类似于之前 Vue2 中的 vm,但 app 比 vm 更 “轻”)
const app = createApp(App)
// 挂载
app.mount('#app')
App.vue
<template>
	<Demo/>
</template>
<script>
	import Demo from './components/Demo'
	export default {
		name: 'App',
		components:{Demo},
	}
</script>
Demo.vue
<template>
	<h2>当前求和为:{ {sum} }</h2>
	<button @click="sum++">点我+1</button>
	<hr>
	<h2>当前的信息为:{ {msg} }</h2>
	<button @click="msg+=''">修改信息</button>
	<hr>
	<h2>姓名:{ {person.name} }</h2>
	<h2>年龄:{ {person.age} }</h2>
	<h2>薪资:{ {person.job.j1.salary} }K</h2>
	<button @click="person.name+='~'">修改姓名</button>
	<button @click="person.age++">增长年龄</button>
	<button @click="person.job.j1.salary++">涨薪</button>
</template>
<script>
	import {ref,reactive,watch} from 'vue'
	export default {
		name: 'Demo',
		setup(){
			// 数据
			let sum = ref(0)
			let msg = ref('你好啊')
			let person = reactive({
				name:'张三',
				age:18,
				job:{
					j1:{
						salary:20
					}
				}
			})
			// 情况一:监视 ref 所定义的一个响应式数据
			/* watch (sum,(newValue,oldValue)=>{
				console.log ('sum 变了 ',newValue,oldValue)
			},{immediate:true}) */
			// 情况二:监视 ref 所定义的多个响应式数据
			/* watch ([sum,msg],(newValue,oldValue)=>{
				console.log ('sum 或 msg 变了 ',newValue,oldValue)
			},{immediate:true}) */
			/* 
				情况三:监视 reactive 所定义的一个响应式数据的全部属性
						1. 注意:此处无法正确的获取 oldValue
						2. 注意:强制开启了深度监视(deep 配置无效)
			*/
			/* watch (person,(newValue,oldValue)=>{
				console.log ('person 变化了 ',newValue,oldValue)
			},{deep:false}) // 此处的 deep 配置无效 */
			// 情况四:监视 reactive 所定义的一个响应式数据中的某个属性
			/* watch (()=>person.name,(newValue,oldValue)=>{
				console.log ('person 的 name 变化了 ',newValue,oldValue)
			})  */
			// 情况五:监视 reactive 所定义的一个响应式数据中的某些属性
			/* watch ([()=>person.name,()=>person.age],(newValue,oldValue)=>{
				console.log ('person 的 name 或 age 变化了 ',newValue,oldValue)
			})  */
			// 特殊情况
			/* watch (()=>person.job,(newValue,oldValue)=>{
				console.log ('person 的 job 变化了 ',newValue,oldValue)
			},{deep:true}) // 此处由于监视的是 reactive 素定义的对象中的某个属性,所以 deep 配置有效 */
			// 返回一个对象(常用)
			return {
				sum,
				msg,
				person
			}
		}
	}
</script>

# src_watch 监视 ref 数据的说明

main.js
// 引入的不再是 Vue 构造函数了,引入的是一个名为 createApp 的工厂函数
import { createApp } from 'vue'
import App from './App.vue'
// 创建应用实例对象 ——app (类似于之前 Vue2 中的 vm,但 app 比 vm 更 “轻”)
const app = createApp(App)
// 挂载
app.mount('#app')
App.vue
<template>
	<Demo/>
</template>
<script>
	import Demo from './components/Demo'
	export default {
		name: 'App',
		components:{Demo},
	}
</script>
Demo.vue
<template>
	<h2>当前求和为:{ {sum} }</h2>
	<button @click="sum++">点我+1</button>
	<hr>
	<h2>当前的信息为:{ {msg} }</h2>
	<button @click="msg+=''">修改信息</button>
	<hr>
	<h2>姓名:{ {person.name} }</h2>
	<h2>年龄:{ {person.age} }</h2>
	<h2>薪资:{ {person.job.j1.salary} }K</h2>
	<button @click="person.name+='~'">修改姓名</button>
	<button @click="person.age++">增长年龄</button>
	<button @click="person.job.j1.salary++">涨薪</button>
</template>
<script>
	import {ref,reactive,watch} from 'vue'
	export default {
		name: 'Demo',
		setup(){
			// 数据
			let sum = ref(0)
			let msg = ref('你好啊')
			let person = ref({
				name:'张三',
				age:18,
				job:{
					j1:{
						salary:20
					}
				}
			})
			console.log(person)
			watch(sum,(newValue,oldValue)=>{
				console.log('sum的值变化了',newValue,oldValue)
			})
			watch(person,(newValue,oldValue)=>{
				console.log('person的值变化了',newValue,oldValue)
			},{deep:true})
			// 返回一个对象(常用)
			return {
				sum,
				msg,
				person
			}
		}
	}
</script>

# src_watchEffect 函数

main.js
// 引入的不再是 Vue 构造函数了,引入的是一个名为 createApp 的工厂函数
import { createApp } from 'vue'
import App from './App.vue'
// 创建应用实例对象 ——app (类似于之前 Vue2 中的 vm,但 app 比 vm 更 “轻”)
const app = createApp(App)
// 挂载
app.mount('#app')
App.vue
<template>
	<Demo/>
</template>
<script>
	import Demo from './components/Demo'
	export default {
		name: 'App',
		components:{Demo},
	}
</script>
Demo.vue
<template>
    <h2>当前求和为:{ {sum} }</h2>
    <button @click="sum++">点我+1</button>
    <hr>
    <h2>当前的信息为:{ {msg} }</h2>
    <button @click="msg+=''">修改信息</button>
    <hr>
    <h2>姓名:{ {person.name} }</h2>
    <h2>年龄:{ {person.age} }</h2>
    <h2>薪资:{ {person.job.j1.salary} }K</h2>
    <button @click="person.name+='~'">修改姓名</button>
    <button @click="person.age++">增长年龄</button>
    <button @click="person.job.j1.salary++">涨薪</button>
</template>
<script>
	import {ref,reactive,watch,watchEffect} from 'vue'
	export default {
		name: 'Demo',
		setup(){
			// 数据
			let sum = ref(0)
			let msg = ref('你好啊')
			let person = reactive({
				name:'张三',
				age:18,
				job:{
					j1:{
						salary:20
					}
				}
			})
			// 监视
			/* watch (sum,(newValue,oldValue)=>{
				console.log ('sum 的值变化了 ',newValue,oldValue)
			},{immediate:true}) */
			watchEffect(()=>{
				const x1 = sum.value
				const x2 = person.job.j1.salary
				console.log('watchEffect所指定的回调执行了')
			})
			// 返回一个对象(常用)
			return {
				sum,
				msg,
				person
			}
		}
	}
</script>

# src_生命周期

main.js
// 引入的不再是 Vue 构造函数了,引入的是一个名为 createApp 的工厂函数
import { createApp } from 'vue'
import App from './App.vue'
// 创建应用实例对象 ——app (类似于之前 Vue2 中的 vm,但 app 比 vm 更 “轻”)
const app = createApp(App)
// 挂载
app.mount('#app')
App.vue
<template>
	<button @click="isShowDemo = !isShowDemo">切换隐藏/显示</button>
	<Demo v-if="isShowDemo"/>
</template>
<script>
	import {ref} from 'vue'
	import Demo from './components/Demo'
	export default {
		name: 'App',
		components:{Demo},
		setup() {
			let isShowDemo = ref(true)
			return {isShowDemo}
		}
	}
</script>
Demo.vue
<template>
	<h2>当前求和为:{ {sum} }</h2>
	<button @click="sum++">点我+1</button>
</template>
<script>
	import {ref,onBeforeMount,onMounted,onBeforeUpdate,onUpdated,onBeforeUnmount,onUnmounted} from 'vue'
	export default {
		name: 'Demo',
		
		setup(){
			console.log('---setup---')
			// 数据
			let sum = ref(0)
			// 通过组合式 API 的形式去使用生命周期钩子
			onBeforeMount(()=>{
				console.log('---onBeforeMount---')
			})
			onMounted(()=>{
				console.log('---onMounted---')
			})
			onBeforeUpdate(()=>{
				console.log('---onBeforeUpdate---')
			})
			onUpdated(()=>{
				console.log('---onUpdated---')
			})
			onBeforeUnmount(()=>{
				console.log('---onBeforeUnmount---')
			})
			onUnmounted(()=>{
				console.log('---onUnmounted---')
			})
			// 返回一个对象(常用)
			return {sum}
		},
		// 通过配置项的形式使用生命周期钩子
		//#region 
		beforeCreate() {
			console.log('---beforeCreate---')
		},
		created() {
			console.log('---created---')
		},
		beforeMount() {
			console.log('---beforeMount---')
		},
		mounted() {
			console.log('---mounted---')
		},
		beforeUpdate(){
			console.log('---beforeUpdate---')
		},
		updated() {
			console.log('---updated---')
		},
		beforeUnmount() {
			console.log('---beforeUnmount---')
		},
		unmounted() {
			console.log('---unmounted---')
		},
		//#endregion
	}
</script>

# src_自定义 hook

main.js
// 引入的不再是 Vue 构造函数了,引入的是一个名为 createApp 的工厂函数
import { createApp } from 'vue'
import App from './App.vue'
// 创建应用实例对象 ——app (类似于之前 Vue2 中的 vm,但 app 比 vm 更 “轻”)
const app = createApp(App)
// 挂载
app.mount('#app')
App.vue
<template>
	<button @click="isShowDemo = !isShowDemo">切换隐藏/显示</button>
	<Demo v-if="isShowDemo"/>
	<hr>
	<Test/>
</template>
<script>
	import {ref} from 'vue'
	import Demo from './components/Demo'
	import Test from './components/Test'
	export default {
		name: 'App',
		components:{Demo,Test},
		setup() {
			let isShowDemo = ref(true)
			return {isShowDemo}
		}
	}
</script>

新建 hooks 文件夹并新建 usePoint.js

usePoint.js
import {reactive,onMounted,onBeforeUnmount} 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(event.pageX,event.pageY)
	}
	// 实现鼠标 “打点” 相关的生命周期钩子
	onMounted(()=>{
		window.addEventListener('click',savePoint)
	})
	onBeforeUnmount(()=>{
		window.removeEventListener('click',savePoint)
	})
	return point
}

一下放在 components 文件夹内

Demo.vue
<template>
	<h2>当前求和为:{ {sum} }</h2>
	<button @click="sum++">点我+1</button>
	<hr>
	<h2>当前点击时鼠标的坐标为:x:{ {point.x} },y:{ {point.y} }</h2>
</template>
<script>
	import {ref} from 'vue'
	import usePoint from '../hooks/usePoint'
	export default {
		name: 'Demo',
		setup(){
			// 数据
			let sum = ref(0)
			let point = usePoint()
			
			// 返回一个对象(常用)
			return {sum,point}
		}
	}
</script>
Test.vue
<template>
	<h2>我是Test组件</h2>
	<h2>当前点击时鼠标的坐标为:x:{ {point.x} },y:{ {point.y} }</h2>
</template>
<script>
	import usePoint from '../hooks/usePoint'
	export default {
		name:'Test',
		setup(){
			const point = usePoint()
			return {point}
		}
	}
</script>

# src_toRef 与 toRefs

main.js
// 引入的不再是 Vue 构造函数了,引入的是一个名为 createApp 的工厂函数
import { createApp } from 'vue'
import App from './App.vue'
// 创建应用实例对象 ——app (类似于之前 Vue2 中的 vm,但 app 比 vm 更 “轻”)
const app = createApp(App)
// 挂载
app.mount('#app')
App.vue
<template>
	<button @click="isShowDemo = !isShowDemo">切换隐藏/显示</button>
	<Demo v-if="isShowDemo"/>
</template>
<script>
	import {ref} from 'vue'
	import Demo from './components/Demo'
	export default {
		name: 'App',
		components:{Demo},
		setup() {
			let isShowDemo = ref(true)
			return {isShowDemo}
		}
	}
</script>
Demo.vue
<template>
    <h4>{ {person} }</h4>
    <h2>姓名:{ {name} }</h2>
    <h2>年龄:{ {age} }</h2>
    <h2>薪资:{ {job.j1.salary} }K</h2>
    <button @click="name+='~'">修改姓名</button>
    <button @click="age++">增长年龄</button>
    <button @click="job.j1.salary++">涨薪</button>
</template>
<script>
	import {ref,reactive,toRef,toRefs} from 'vue'
	export default {
		name: 'Demo',
		setup(){
			// 数据
			let person = reactive({
				name:'张三',
				age:18,
				job:{
					j1:{
						salary:20
					}
				}
			})
			// const name1 = person.name
			// console.log('%%%',name1)
			// const name2 = toRef(person,'name')
			// console.log('####',name2)
			const x = toRefs(person)
			console.log('******',x)
			// 返回一个对象(常用)
			return {
				person,
				// name:toRef(person,'name'),
				// age:toRef(person,'age'),
				// salary:toRef(person.job.j1,'salary'),
				...toRefs(person)
			}
		}
	}
</script>

# src_shallowReactive 与 shallowRef

main.js
// 引入的不再是 Vue 构造函数了,引入的是一个名为 createApp 的工厂函数
import { createApp } from 'vue'
import App from './App.vue'
// 创建应用实例对象 ——app (类似于之前 Vue2 中的 vm,但 app 比 vm 更 “轻”)
const app = createApp(App)
// 挂载
app.mount('#app')
App.vue
<template>
	<button @click="isShowDemo = !isShowDemo">切换隐藏/显示</button>
	<Demo v-if="isShowDemo"/>
</template>
<script>
	import {ref} from 'vue'
	import Demo from './components/Demo'
	export default {
		name: 'App',
		components:{Demo},
		setup() {
			let isShowDemo = ref(true)
			return {isShowDemo}
		}
	}
</script>
Demo.vue
<template>
	<h4>当前的x.y值是:{ {x.y} }</h4>
	<button @click="x={y:888}">点我替换x</button>
	<button @click="x.y++">点我x.y++</button>
	<hr>
	<h4>{ {person} }</h4>
	<h2>姓名:{ {name} }</h2>
	<h2>年龄:{ {age} }</h2>
	<h2>薪资:{ {job.j1.salary} }K</h2>
	<button @click="name+='~'">修改姓名</button>
	<button @click="age++">增长年龄</button>
	<button @click="job.j1.salary++">涨薪</button>
</template>
<script>
	import {ref,reactive,toRef,toRefs,shallowReactive,shallowRef} from 'vue'
	export default {
		name: 'Demo',
		setup(){
			// 数据
			//let person = shallowReactive ({ // 只考虑第一层数据的响应式
			let person = reactive({
				name:'张三',
				age:18,
				job:{
					j1:{
						salary:20
					}
				}
			})
			let x = shallowRef({
				y:0
			})
			console.log('******',x)
			// 返回一个对象(常用)
			return {
				x,
				person,
				...toRefs(person)
			}
		}
	}
</script>

# src_readonly 与 shallowReadonly

main.js
// 引入的不再是 Vue 构造函数了,引入的是一个名为 createApp 的工厂函数
import { createApp } from 'vue'
import App from './App.vue'
// 创建应用实例对象 ——app (类似于之前 Vue2 中的 vm,但 app 比 vm 更 “轻”)
const app = createApp(App)
// 挂载
app.mount('#app')
App.vue
<template>
	<button @click="isShowDemo = !isShowDemo">切换隐藏/显示</button>
	<Demo v-if="isShowDemo"/>
</template>
<script>
	import {ref} from 'vue'
	import Demo from './components/Demo'
	export default {
		name: 'App',
		components:{Demo},
		setup() {
			let isShowDemo = ref(true)
			return {isShowDemo}
		}
	}
</script>
Demo.vue
<template>
	<h4>当前求和为:{ {sum} }</h4>
	<button @click="sum++">点我++</button>
	<hr>
	<h2>姓名:{ {name} }</h2>
	<h2>年龄:{ {age} }</h2>
	<h2>薪资:{ {job.j1.salary} }K</h2>
	<button @click="name+='~'">修改姓名</button>
	<button @click="age++">增长年龄</button>
	<button @click="job.j1.salary++">涨薪</button>
</template>
<script>
	import {ref,reactive,toRefs,readonly,shallowReadonly} from 'vue'
	export default {
		name: 'Demo',
		setup(){
			// 数据
			let sum = ref(0)
			let person = reactive({
				name:'张三',
				age:18,
				job:{
					j1:{
						salary:20
					}
				}
			})
			person = readonly(person)
			// person = shallowReadonly(person)
			// sum = readonly(sum)
			// sum = shallowReadonly(sum)
			// 返回一个对象(常用)
			return {
				sum,
				...toRefs(person)
			}
		}
	}
</script>

# src_toRaw 与 markRaw

main.js
// 引入的不再是 Vue 构造函数了,引入的是一个名为 createApp 的工厂函数
import { createApp } from 'vue'
import App from './App.vue'
// 创建应用实例对象 ——app (类似于之前 Vue2 中的 vm,但 app 比 vm 更 “轻”)
const app = createApp(App)
// 挂载
app.mount('#app')
App.vue
<template>
	<button @click="isShowDemo = !isShowDemo">切换隐藏/显示</button>
	<Demo v-if="isShowDemo"/>
</template>
<script>
	import {ref} from 'vue'
	import Demo from './components/Demo'
	export default {
		name: 'App',
		components:{Demo},
		setup() {
			let isShowDemo = ref(true)
			return {isShowDemo}
		}
	}
</script>
Demo.vue
<template>
	<h4>当前求和为:{ {sum} }</h4>
	<button @click="sum++">点我++</button>
	<hr>
	<h2>姓名:{ {name} }</h2>
	<h2>年龄:{ {age} }</h2>
	<h2>薪资:{ {job.j1.salary} }K</h2>
	<h3 v-show="person.car">座驾信息:{ {person.car} }</h3>
	<button @click="name+='~'">修改姓名</button>
	<button @click="age++">增长年龄</button>
	<button @click="job.j1.salary++">涨薪</button>
	<button @click="showRawPerson">输出最原始的person</button>
	<button @click="addCar">给人添加一台车</button>
	<button @click="person.car.name+='!'">换车名</button>
	<button @click="changePrice">换价格</button>
</template>
<script>
	import {ref,reactive,toRefs,toRaw,markRaw} from 'vue'
	export default {
		name: 'Demo',
		setup(){
			// 数据
			let sum = ref(0)
			let person = reactive({
				name:'张三',
				age:18,
				job:{
					j1:{
						salary:20
					}
				}
			})
			function showRawPerson(){
				const p = toRaw(person)
				p.age++
				console.log(p)
			}
			function addCar(){
				let car = {name:'奔驰',price:40}
				person.car = markRaw(car)
			}
			function changePrice(){
				person.car.price++
				console.log(person.car.price)
			}
			// 返回一个对象(常用)
			return {
				sum,
				person,
				...toRefs(person),
				showRawPerson,
				addCar,
				changePrice
			}
		}
	}
</script>

# src_customRef

main.js
// 引入的不再是 Vue 构造函数了,引入的是一个名为 createApp 的工厂函数
import { createApp } from 'vue'
import App from './App.vue'
// 创建应用实例对象 ——app (类似于之前 Vue2 中的 vm,但 app 比 vm 更 “轻”)
const app = createApp(App)
// 挂载
app.mount('#app')
App.vue
<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>

# src_provide 与 inject

main.js
// 引入的不再是 Vue 构造函数了,引入的是一个名为 createApp 的工厂函数
import { createApp } from 'vue'
import App from './App.vue'
// 创建应用实例对象 ——app (类似于之前 Vue2 中的 vm,但 app 比 vm 更 “轻”)
const app = createApp(App)
// 挂载
app.mount('#app')
App.vue
<template>
	<div class="app">
		<h3>我是App组件(祖),{ {name} }--{ {price} }</h3>
		<Child/>
	</div>
</template>
<script>
	import { reactive,toRefs,provide } from 'vue'
	import Child from './components/Child.vue'
	export default {
		name:'App',
		components:{Child},
		setup(){
			let car = reactive({name:'奔驰',price:'40W'})
			provide('car',car) // 给自己的后代组件传递数据
			return {...toRefs(car)}
		}
	}
</script>
<style>
	.app{
		background-color: gray;
		padding: 10px;
	}
</style>
Child.vue
<template>
	<div class="child">
		<h3>我是Child组件(子)</h3>
		<Son/>
	</div>
</template>
<script>
	import {inject} from 'vue'
	import Son from './Son.vue'
	export default {
		name:'Child',
		components:{Son},
		/* setup(){
			let x = inject('car')
			console.log(x,'Child-----')
		} */
	}
</script>
<style>
	.child{
		background-color: skyblue;
		padding: 10px;
	}
</style>
Son.vue
<template>
	<div class="son">
		<h3>我是Son组件(孙),{ {car.name} }--{ {car.price} }</h3>
	</div>
</template>
<script>
	import {inject} from 'vue'
	export default {
		name:'Son',
		setup(){
			let car = inject('car')
			return {car}
		}
	}
</script>
<style>
	.son{
		background-color: orange;
		padding: 10px;
	}
</style>

# src_响应式数据的判断

main.js
// 引入的不再是 Vue 构造函数了,引入的是一个名为 createApp 的工厂函数
import { createApp } from 'vue'
import App from './App.vue'
// 创建应用实例对象 ——app (类似于之前 Vue2 中的 vm,但 app 比 vm 更 “轻”)
const app = createApp(App)
// 挂载
app.mount('#app')
App.vue
<template>
	<h3>我是App组件</h3>
</template>
<script>
	import {ref, reactive,toRefs,readonly,isRef,isReactive,isReadonly,isProxy } from 'vue'
	export default {
		name:'App',
		setup(){
			let car = reactive({name:'奔驰',price:'40W'})
			let sum = ref(0)
			let car2 = readonly(car)
			console.log(isRef(sum))
			console.log(isReactive(car))
			console.log(isReadonly(car2))
			console.log(isProxy(car))
			console.log(isProxy(sum))
			
			return {...toRefs(car)}
		}
	}
</script>
<style>
	.app{
		background-color: gray;
		padding: 10px;
	}
</style>

# src_Teleport

main.js
// 引入的不再是 Vue 构造函数了,引入的是一个名为 createApp 的工厂函数
import { createApp } from 'vue'
import App from './App.vue'
// 创建应用实例对象 ——app (类似于之前 Vue2 中的 vm,但 app 比 vm 更 “轻”)
const app = createApp(App)
// 挂载
app.mount('#app')
App.vue
<template>
	<div class="app">
		<h3>我是App组件</h3>
		<Child/>
	</div>
</template>
<script>
	import Child from './components/Child'
	export default {
		name:'App',
		components:{Child},
	}
</script>
<style>
	.app{
		background-color: gray;
		padding: 10px;
	}
</style>
Child.vue
<template>
	<div class="child">
		<h3>我是Child组件</h3>
		<Son/>
	</div>
</template>
<script>
	import Son from './Son'
	export default {
		name:'Child',
		components:{Son},
	}
</script>
<style>
	.child{
		background-color: skyblue;
		padding: 10px;
	}
</style>
Dialog.vue
<template>
	<div>
		<button @click="isShow = true">点我弹个窗</button>
		<teleport to="body">
			<div v-if="isShow" class="mask">
				<div class="dialog">
					<h3>我是一个弹窗</h3>
					<h4>一些内容</h4>
					<h4>一些内容</h4>
					<h4>一些内容</h4>
					<button @click="isShow = false">关闭弹窗</button>
				</div>
			</div>
		</teleport>
	</div>
</template>
<script>
	import {ref} from 'vue'
	export default {
		name:'Dialog',
		setup(){
			let isShow = ref(false)
			return {isShow}
		}
	}
</script>
<style>
	.mask{
		position: absolute;
		top: 0;bottom: 0;left: 0;right: 0;
		background-color: rgba(0, 0, 0, 0.5);
	}
	.dialog{
		position: absolute;
		top: 50%;
		left: 50%;
		transform: translate(-50%,-50%);
		text-align: center;
		width: 300px;
		height: 300px;
		background-color: green;
	}
</style>
Son.vue
<template>
	<div class="son">
		<h3>我是Son组件</h3>
		<Dialog/>
	</div>
</template>
<script>
	import Dialog from './Dialog.vue'
	export default {
		name:'Son',
		components:{Dialog}
	}
</script>
<style>
	.son{
		background-color: orange;
		padding: 10px;
	}
</style>

# src_Suspense

main.js
// 引入的不再是 Vue 构造函数了,引入的是一个名为 createApp 的工厂函数
import { createApp } from 'vue'
import App from './App.vue'
// 创建应用实例对象 ——app (类似于之前 Vue2 中的 vm,但 app 比 vm 更 “轻”)
const app = createApp(App)
// 挂载
app.mount('#app')
App.vue
<template>
	<div class="app">
		<h3>我是App组件</h3>
		<Suspense>
			<template v-slot:default>
				<Child/>
			</template>
			<template v-slot:fallback>
				<h3>稍等,加载中...</h3>
			</template>
		</Suspense>
	</div>
</template>
<script>
	//import Child from './components/Child'// 静态引入
	import {defineAsyncComponent} from 'vue' 
	const Child = defineAsyncComponent(()=>import('./components/Child')) // 异步引入
	export default {
		name:'App',
		components:{Child},
	}
</script>
<style>
	.app{
		background-color: gray;
		padding: 10px;
	}
</style>
Child.vue
<template>
	<div class="child">
		<h3>我是Child组件</h3>
		{ {sum} }
	</div>
</template>
<script>
	import {ref} from 'vue'
	export default {
		name:'Child',
		async setup(){
			let sum = ref(0)
			let p = new Promise((resolve,reject)=>{
				setTimeout(()=>{
					resolve({sum})
				},3000)
			})
			return await p
		}
	}
</script>
<style>
	.child{
		background-color: skyblue;
		padding: 10px;
	}
</style>