Vue 所有代码资料仓库
# Vue3.0 的使用
# src_分析工程结构
// 引入的不再是 Vue 构造函数了,引入的是一个名为 createApp 的工厂函数 | |
import { createApp } from 'vue' | |
import App from './App.vue' | |
// 创建应用实例对象 ——app (类似于之前 Vue2 中的 vm,但 app 比 vm 更 “轻”) | |
const app = createApp(App) | |
// 挂载 | |
app.mount('#app') |
<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> |
<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
// 引入的不再是 Vue 构造函数了,引入的是一个名为 createApp 的工厂函数 | |
import { createApp } from 'vue' | |
import App from './App.vue' | |
// 创建应用实例对象 ——app (类似于之前 Vue2 中的 vm,但 app 比 vm 更 “轻”) | |
const app = createApp(App) | |
// 挂载 | |
app.mount('#app') |
<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 函数
// 引入的不再是 Vue 构造函数了,引入的是一个名为 createApp 的工厂函数 | |
import { createApp } from 'vue' | |
import App from './App.vue' | |
// 创建应用实例对象 ——app (类似于之前 Vue2 中的 vm,但 app 比 vm 更 “轻”) | |
const app = createApp(App) | |
// 挂载 | |
app.mount('#app') |
<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 函数
// 引入的不再是 Vue 构造函数了,引入的是一个名为 createApp 的工厂函数 | |
import { createApp } from 'vue' | |
import App from './App.vue' | |
// 创建应用实例对象 ——app (类似于之前 Vue2 中的 vm,但 app 比 vm 更 “轻”) | |
const app = createApp(App) | |
// 挂载 | |
app.mount('#app') |
<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 的响应式原理
<!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 的两个注意点
// 引入的不再是 Vue 构造函数了,引入的是一个名为 createApp 的工厂函数 | |
import { createApp } from 'vue' | |
import App from './App.vue' | |
// 创建应用实例对象 ——app (类似于之前 Vue2 中的 vm,但 app 比 vm 更 “轻”) | |
const app = createApp(App) | |
// 挂载 | |
app.mount('#app') |
<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> |
<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 函数
// 引入的不再是 Vue 构造函数了,引入的是一个名为 createApp 的工厂函数 | |
import { createApp } from 'vue' | |
import App from './App.vue' | |
// 创建应用实例对象 ——app (类似于之前 Vue2 中的 vm,但 app 比 vm 更 “轻”) | |
const app = createApp(App) | |
// 挂载 | |
app.mount('#app') |
<template> | |
<Demo/> | |
</template> | |
<script> | |
import Demo from './components/Demo' | |
export default { | |
name: 'App', | |
components:{Demo}, | |
} | |
</script> |
<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 函数
// 引入的不再是 Vue 构造函数了,引入的是一个名为 createApp 的工厂函数 | |
import { createApp } from 'vue' | |
import App from './App.vue' | |
// 创建应用实例对象 ——app (类似于之前 Vue2 中的 vm,但 app 比 vm 更 “轻”) | |
const app = createApp(App) | |
// 挂载 | |
app.mount('#app') |
<template> | |
<Demo/> | |
</template> | |
<script> | |
import Demo from './components/Demo' | |
export default { | |
name: 'App', | |
components:{Demo}, | |
} | |
</script> |
<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 数据的说明
// 引入的不再是 Vue 构造函数了,引入的是一个名为 createApp 的工厂函数 | |
import { createApp } from 'vue' | |
import App from './App.vue' | |
// 创建应用实例对象 ——app (类似于之前 Vue2 中的 vm,但 app 比 vm 更 “轻”) | |
const app = createApp(App) | |
// 挂载 | |
app.mount('#app') |
<template> | |
<Demo/> | |
</template> | |
<script> | |
import Demo from './components/Demo' | |
export default { | |
name: 'App', | |
components:{Demo}, | |
} | |
</script> |
<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 函数
// 引入的不再是 Vue 构造函数了,引入的是一个名为 createApp 的工厂函数 | |
import { createApp } from 'vue' | |
import App from './App.vue' | |
// 创建应用实例对象 ——app (类似于之前 Vue2 中的 vm,但 app 比 vm 更 “轻”) | |
const app = createApp(App) | |
// 挂载 | |
app.mount('#app') |
<template> | |
<Demo/> | |
</template> | |
<script> | |
import Demo from './components/Demo' | |
export default { | |
name: 'App', | |
components:{Demo}, | |
} | |
</script> |
<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_生命周期
// 引入的不再是 Vue 构造函数了,引入的是一个名为 createApp 的工厂函数 | |
import { createApp } from 'vue' | |
import App from './App.vue' | |
// 创建应用实例对象 ——app (类似于之前 Vue2 中的 vm,但 app 比 vm 更 “轻”) | |
const app = createApp(App) | |
// 挂载 | |
app.mount('#app') |
<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> |
<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
// 引入的不再是 Vue 构造函数了,引入的是一个名为 createApp 的工厂函数 | |
import { createApp } from 'vue' | |
import App from './App.vue' | |
// 创建应用实例对象 ——app (类似于之前 Vue2 中的 vm,但 app 比 vm 更 “轻”) | |
const app = createApp(App) | |
// 挂载 | |
app.mount('#app') |
<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
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 文件夹内
<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> |
<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
// 引入的不再是 Vue 构造函数了,引入的是一个名为 createApp 的工厂函数 | |
import { createApp } from 'vue' | |
import App from './App.vue' | |
// 创建应用实例对象 ——app (类似于之前 Vue2 中的 vm,但 app 比 vm 更 “轻”) | |
const app = createApp(App) | |
// 挂载 | |
app.mount('#app') |
<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> |
<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
// 引入的不再是 Vue 构造函数了,引入的是一个名为 createApp 的工厂函数 | |
import { createApp } from 'vue' | |
import App from './App.vue' | |
// 创建应用实例对象 ——app (类似于之前 Vue2 中的 vm,但 app 比 vm 更 “轻”) | |
const app = createApp(App) | |
// 挂载 | |
app.mount('#app') |
<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> |
<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
// 引入的不再是 Vue 构造函数了,引入的是一个名为 createApp 的工厂函数 | |
import { createApp } from 'vue' | |
import App from './App.vue' | |
// 创建应用实例对象 ——app (类似于之前 Vue2 中的 vm,但 app 比 vm 更 “轻”) | |
const app = createApp(App) | |
// 挂载 | |
app.mount('#app') |
<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> |
<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
// 引入的不再是 Vue 构造函数了,引入的是一个名为 createApp 的工厂函数 | |
import { createApp } from 'vue' | |
import App from './App.vue' | |
// 创建应用实例对象 ——app (类似于之前 Vue2 中的 vm,但 app 比 vm 更 “轻”) | |
const app = createApp(App) | |
// 挂载 | |
app.mount('#app') |
<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> |
<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
// 引入的不再是 Vue 构造函数了,引入的是一个名为 createApp 的工厂函数 | |
import { createApp } from 'vue' | |
import App from './App.vue' | |
// 创建应用实例对象 ——app (类似于之前 Vue2 中的 vm,但 app 比 vm 更 “轻”) | |
const app = createApp(App) | |
// 挂载 | |
app.mount('#app') |
<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
// 引入的不再是 Vue 构造函数了,引入的是一个名为 createApp 的工厂函数 | |
import { createApp } from 'vue' | |
import App from './App.vue' | |
// 创建应用实例对象 ——app (类似于之前 Vue2 中的 vm,但 app 比 vm 更 “轻”) | |
const app = createApp(App) | |
// 挂载 | |
app.mount('#app') |
<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> |
<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> |
<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_响应式数据的判断
// 引入的不再是 Vue 构造函数了,引入的是一个名为 createApp 的工厂函数 | |
import { createApp } from 'vue' | |
import App from './App.vue' | |
// 创建应用实例对象 ——app (类似于之前 Vue2 中的 vm,但 app 比 vm 更 “轻”) | |
const app = createApp(App) | |
// 挂载 | |
app.mount('#app') |
<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
// 引入的不再是 Vue 构造函数了,引入的是一个名为 createApp 的工厂函数 | |
import { createApp } from 'vue' | |
import App from './App.vue' | |
// 创建应用实例对象 ——app (类似于之前 Vue2 中的 vm,但 app 比 vm 更 “轻”) | |
const app = createApp(App) | |
// 挂载 | |
app.mount('#app') |
<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> |
<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> |
<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> |
<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
// 引入的不再是 Vue 构造函数了,引入的是一个名为 createApp 的工厂函数 | |
import { createApp } from 'vue' | |
import App from './App.vue' | |
// 创建应用实例对象 ——app (类似于之前 Vue2 中的 vm,但 app 比 vm 更 “轻”) | |
const app = createApp(App) | |
// 挂载 | |
app.mount('#app') |
<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> |
<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> |