day 1
1. 创建vue3工程
相关代码如下:
## 创建vue工程 npm create vue@lastest ## 安装node_modules npm install // npm i
创建工程完毕之后,进入文件夹可以发现有如下文件,下图是文件介绍:
入口文件介绍:
这里main.ts
是与index.html
建立联系的;
通过.mount('#app')
这样 main.ts
就与index.html
建立起了联系;
其中main.ts
的代码格式如下:
<template> <div> <h1>你好</h1> </div> </template> <script setup lang="ts"> // js或者ts </script> <style scoped> /* 样式 */ </style>
App.vue
的代码格式如下:
<template> <div class="app"> <h1>你好</h1> </div> </template> <script setup lang="ts"> // js或者ts </script> <style scoped> /* 样式 */ .app { background-color: #ddd; box-shadow: 0 0 10px; border-radius: 10px; padding: 20px; } </style>
网页调试vue可以在chrome应用商店search vue.js devtools
下载安装就好;
你好
### 2. 选项式API和组合式API
感觉vue2和vue3的主要不同就在于vue文件中script部分;其中vue2是选项式OptionsAPI
的,vue3是组合式Composition
的;
选项式API相关代码如下:
注意,这里并没有setup
;
<script lang="ts"> export default { // 定义组件名字 name: 'Person', // 定义数据 data(){ return { name: '张三', age: 18, tel: '138888888' } }, // 定义方法 methods:{ changeName(){ this.name = 'zhang-san' }, changeAge(){ this.age += 1 }, showTel(){ alert(this.tel) } }, } </script>
组合式相关代码如下:
注意,这里的setup比beforecreate执行得还要早,setup的返回值也可以是渲染函数,data,method,setup可以同时存在,setup不可以读取data中的数据,反之则可以,因为setup是执行得最早的;
<script lang="ts"> export default { name: 'Person', setup(){ // 数据 let name = '张三' // 此时name,age,tel 不是响应式的 应该改为ref或者reactive let age = 18 // 此时name,age,tel 不是响应式的 应该改为ref或者reactive let tel = '138888888' // 此时name,age,tel 不是响应式的 应该改为ref或者reactive // 方法 function changeName(){ name = 'zhang-san' } function changeAge(){ age += 1 } function showTel(){ alert(tel) } // 把数据和方法交出去 return {name, age, changeAge, changeName, showTel} } } </script>
setup语法糖简化后代码如下:
<script lang="ts"> export default { name: 'Person', } </script> <script setup lang="ts"> // 数据 let name = '张三' // 此时name,age,tel 不是响应式的 应该改为ref或者reactive let age = 18 // 此时name,age,tel 不是响应式的 应该改为ref或者reactive let tel = '138888888' // 此时name,age,tel 不是响应式的 应该改为ref或者reactive // 方法 function changeName(){ name = 'zhang-san' } function changeAge(){ age += 1 } function showTel(){ alert(tel) } // 此时不需要return 自动提交 </script>
3. 响应式数据
响应式数据创建有两种方法,一种是ref
,一种是reactive
ref
定义基本类型的数据
使用的相关代码如下:
<template> <div class="app"> <h2>姓名:{{ name }}</h2> // 利用大括号包起来的是不需要.value的 <h2>年龄:{{ age }}</h2> // 利用大括号包起来的是不需要.value的 <button @click="changeName">修改名字</button> <button @click="changeAge">修改年龄</button> <button @click="showTel">查看联系方式</button> </div> </template> <script setup lang="ts"> import {ref} from 'vue' let name = ref('张三') let age = ref(18) let tel = ref('138888888') // 在ref包裹住后,需要操作值都需要.value function changeName(){ name.value = 'zhang-san' } function changeAge(){ age.value += 1 } function showTel(){ alert(tel.value) }
这里值用ref
包裹起来之后,变量会变成一个RefImpl
类的数据,这时要修改值直接对变量操作是无意义的,我们需要对.value
进行操作;这里要注意的是,ref
也可以定义对象类的响应式数据,实现原理是先用ref
包裹,再用reactive
包裹,即取值还是需要用value
;
reactive
定义对象类型的数据
使用的相关代码如下:
<template> <div class="app"> <h2>姓名:{{ student.name }}</h2> <h2>年龄:{{ student.age }}</h2> <button @click="changeName">修改名字</button> <button @click="changeAge">修改年龄</button> </div> </template> <script lang="ts"> export default { name: 'Person', } </script> <script setup lang="ts"> import {reactive} from 'vue' let student = reactive({name:'张三', age:18}) function changeName(){ student.name = 'zhang-san' } function changeAge(){ student.age += 1 } </script> <style scoped> /* 样式 */ .app { background-color: #ddd; box-shadow: 0 0 10px; border-radius: 10px; padding: 20px; } button { margin: 10px; } </style>
用reactive
包起来后,对象变成了一个Proxy
的对象,原对象在Proxy
里面的target
中;这里的reactive
是深层次的,只能定义对象类型的响应式数据;
ref
和reactive
的对比
这里要注意的是,重新分配reactive
的对象时,使用Object.assign
,但是如果是利用ref
定义的对象类数据,我们是可以直接进行替换的;
对响应式数据进行解构,toRef
和toRefs
:
let person = reactive({ name: '张三', age: 18 }) let {name, age} = person // let name = person.name // let age = person.age let {name, age} = toRefs(person) //把reactive对象里面的每一组对象转化为ref // let name = toRef(person, 'name') // let age = toRef(person, 'age')
4. 计算属性
v-bind
是 单向绑定,数据流向页面;v-model
是 双向绑定,页面也可以流向数据;
计算属性 computed
是只要响应式变量出现了变化,就随之变化;
使用例子如下:
<template> <div class="app"> 姓名:<input type="text" v-model="name"> <br> 年龄:<input type="text" v-model="age"> <br> information: {{ information }} </div> </template> <script lang="ts"> export default { name: 'Person', } </script> <script setup lang="ts"> import {ref, computed} from 'vue' let name = ref('zhangsan') let age = ref(18) let information = computed(()=>{ return name.value + age.value }) </script> <style scoped> /* 样式 */ .app { background-color: #ddd; box-shadow: 0 0 10px; border-radius: 10px; padding: 20px; } </style>
computed
是用来区别于方法的,使用computed
得到的属性是没有缓存的,而且computed
得到的属性是不可修改的;如果需要修改,则需要使用以下方法:
<template> <div class="app"> 姓名:<input type="text" v-model="name"> <br> 年龄:<input type="text" v-model="age"> <br> information: {{ information }} <br> <button @click="changeInformation">修改information为lisi</button> </div> </template> <script lang="ts"> export default { name: 'Person', } </script> <script setup lang="ts"> import {ref, computed} from 'vue' let name = ref('zhangsan') let age = ref(18) let information = computed({ get(){ return name.value + '-' + age.value }, set(val){ const [s1, s2] = val.split('-') name.value = s1 age.value = parseInt(s2) } }) function changeInformation(){ information.value = 'lisi-18' } </script> <style scoped> /* 样式 */ .app { background-color: #ddd; box-shadow: 0 0 10px; border-radius: 10px; padding: 20px; } </style>
day 2
5. watch 监视
情况1:监视ref
定义的基本类型数据
停止监视只需要调用watch
函数的返回值就可以;
<template> <div> <h5>情况1:监视【ref】定义的值是【基本类型】的数据</h5> sum : {{ sum }} <br> <button @click="changeSum"> sum + 1</button> <br> <hr> </div> </template> <script lang="ts"> export default { name: 'Person' } </script> <script setup lang="ts"> import {ref, watch} from 'vue' let sum = ref(1) function changeSum(){ sum.value += 1 } // 这里的sum是不需要添加.value的,返回值就是停止监视的函数 const stopwatch = watch(sum, (newVal, oldVal)=>{ console.log('sum变化了', newVal, oldVal) // 如果sum的最新值大于等于10则停止监视 if(newVal >= 10 ){ stopwatch() } }) </script> <style scoped> </style>
情况2:监视ref
定义的对象类型数据
这里要注意的是:若修改的是ref定义的对象中的属性,newVal和oldVal都是新值,因为是同一个对象;若修改的是ref定义的整个对象,newVal是新值,oldVal是旧值,因为不是同一个对象;
<template> <div> <h5>情况2:监视【ref】定义的值是【对象类型】的数据</h5> 姓名: {{ person.name }} <br> 年龄: {{ person.age }} <br> <button @click="changeName">修改名字</button> <button @click="changeAge">修改年龄</button> <button @click="changeFull">修改整个人</button> </div> </template> <script lang="ts"> export default { name: 'Person' } </script> <script setup lang="ts"> import {ref, watch} from 'vue' let person = ref({ name: '张三', age: 18 }) function changeName (){ person.value.name = '李四' } function changeAge (){ person.value.age = 19 } function changeFull (){ person.value = {name: '王五', age: 20} } // 监视【ref】定义的【对象类型数据】,监视的是对象的地址值,若想要监视 // 对象的内部属性的变化,需要手动开启深度监视deep // 若修改的是ref定义的对象中的属性,newVal和oldVal都是新值,因为是同一个对象 // 若修改的是ref定义的整个对象,newVal是新值,oldVal是旧值,因为不是同一个对象 // watch的第一个参数是:被监视的数据 // watch的第二个参数是:监视的回调 // watch的第三个参数是:配置对象(deep, immediate ... ) watch(person, (newVal, oldVal)=>{ console.log('person变化了', newVal, oldVal) }, {deep: true}) </script> <style scoped> button { margin: 10px; } </style>
情况3:监视reactive
定义的对象类型数据
很简单,只需要把ref
定义的对象改为reactive
定义的对象,然后在修改整个对象的时候使用Object.assign
替换就可以;
<template> <div> <h5>情况3:监视【reactive】定义的值是【对象类型】的数据</h5> 姓名: {{ person.name }} <br> 年龄: {{ person.age }} <br> <button @click="changeName">修改名字</button> <button @click="changeAge">修改年龄</button> <button @click="changeFull">修改人</button> </div> </template> <script lang="ts"> export default { name: 'Person' } </script> <script setup lang="ts"> import {reactive, watch} from 'vue' let person = reactive({ name: '张三', age: 18 }) function changeName (){ person.name = '李四' } function changeAge (){ person.age = 19 } function changeFull (){ // 并没有修改地址值; Object.assign(person, {name: '王五', age: 20}) } // 监视【reactive】定义的对象类型数据,默认是开启深度监视的,而且深度是关不掉的 watch(person, (newVal, oldVal)=>{ console.log('person变化了', newVal, oldVal) }) </script> <style scoped> button { margin: 10px; } </style>
情况4:监视ref
或者reactive
定义的对象类型中的某个属性
<template> <div> <h5>情况4:监视【ref或reactive】定义的【对象类型】某个属性</h5> 姓名: {{ person.name }} <br> 年龄: {{ person.age }} <br> 车辆:{{ person.car.c1 }}, {{ person.car.c2 }} <br> <button @click="changeName">修改名字</button> <button @click="changeAge">修改年龄</button> <button @click="changeC1">修改c1</button> <button @click="changeC2">修改c2</button> <button @click="changeCar">修改car</button> </div> </template> <script lang="ts"> export default { name: 'Person' } </script> <script setup lang="ts"> import {reactive, watch} from 'vue' let person = reactive({ name: '张三', age: 18, car:{ c1: 'asd', c2: 'das' } }) function changeName (){ person.name = '李四' } function changeAge (){ person.age = 19 } function changeC1(){ person.car.c1 = 'qqq' } function changeC2(){ person.car.c2 = 'www' } function changeCar(){ person.car = {c1:'yyy', c2:'jjj'} } // 监视响应式对象中的某个属性,且该变量是基本类型的,要写成函数式 /* watch(()=>person.name, (newVal, oldVal)=>{ console.log('person.name变化了', newVal, oldVal) }) */ // 监视响应式对象中的某个属性,且该属性是对象类型的,可以直接写,也能写函数,推荐写函数 watch(()=>person.car, (newVal, oldVal)=>{ console.log('person.car变化了', newVal, oldVal) }, {deep:true}) </script> <style scoped> button { margin: 10px; } </style>
情况5:监视多个数据
<template> <div> <h5>情况4:监视【ref】定义的值是【对象类型】的数据</h5> 姓名: {{ person.name }} <br> 年龄: {{ person.age }} <br> 车辆:{{ person.car.c1 }}, {{ person.car.c2 }} <br> <button @click="changeName">修改名字</button> <button @click="changeAge">修改年龄</button> <button @click="changeC1">修改c1</button> <button @click="changeC2">修改c2</button> <button @click="changeCar">修改car</button> </div> </template> <script lang="ts"> export default { name: 'Person' } </script> <script setup lang="ts"> import {reactive, watch} from 'vue' let person = reactive({ name: '张三', age: 18, car:{ c1: 'asd', c2: 'das' } }) function changeName (){ person.name = '李四' } function changeAge (){ person.age = 19 } function changeC1(){ person.car.c1 = 'qqq' } function changeC2(){ person.car.c2 = 'www' } function changeCar(){ person.car = {c1:'yyy', c2:'jjj'} } // 此时newVal和oldVal是数组与前面的对应 watch([()=>person.name, ()=>person.age], (newVal, oldVal)=>{ console.log('变化了', newVal, oldVal) }) </script> <style scoped> button { margin: 10px; } </style>
Vue3 五天速成(中)https://developer.aliyun.com/article/1504166?spm=a2c6h.13148508.setting.28.36834f0eJwPRIa