vue3 基础
安装脚手架
绑定原理
vue2 绑定原理:访问器属性 + 虚拟DOM树
但是访问器属性只能在首次创建new vue()对象时初始就有的属性,添加监视(访问器属性)。1.今后动态添加进来的成员,就无法自动添加访问器属性,也就无法自动得到监视;2.无法给索引数组的数字下标添加访问器属性;结果在vue 程序中后添加成员,或通过下标修改索引数组中的元素值,页面都不自动更新。
vue3 中的绑定原理(解决2中的以上两点缺点):
ES6 的Proxy 代理对象,proxy在目标对象的外城搭建了一层拦截,外界对目标对象的所有操作,都必须通过这层拦截。
proxy优点 == 对象内部所有现有属性自动被监视,而且后添加的属性,一进入对象就被监视。缺点 == 兼容性问题
数组:
对象:
vue2 对比vue3 变化:ES6的proxy 代替了访问器属性
脚手架的变化
main.ts 中的变化:
// 1.替代了new Vue() ,因为 vue3 更倾向于函数式编程,而不是面向对象式编程 import {createApp} from 'vue' // 用于创建vue Vue对象 import App from './App.vue' // 相当于旧的脚手架中的容器 import router from './router' import store from './store'
import axios from 'axios'; // vue3中可以不用非要放到vue原型中,靠模块化开发的引入也可使用
axios.defaults.baseURL = '/'
createApp(App).use(store).use(router).mount('#app')
页面组件内的变化
<template>和<style>没有任何变化,和vue2中一样使用
<script>中vue3 也支持vue2 写法,但会逐渐不支持。<script>中新写法:
1. 引入 vue 模块中提供的函数,用于创建组件对象和加工组件对象的内容
import { defineComponent,ref } from 'vue'
defineComponent 是vue3 提供的专门创建组件对象的函数
ref 是vue3 提供的一个函数,专门将任何东西包装成为一个能被监视的proxy 对象
2. 用defineComponent()函数创建一个数组对象,依然可以用components 成员引入其他子组件(与vue2 相同)
export default defineComponent({ name:'Home', components:{ 子组件对象,.... } })
3. defineComponent({}) 函数内,必须先调用setup() 函数作为整个数组代码的运行起点
setup() 其实是代替了vue2 中的create 声明周期,即在vue3中的声明起点是setup
4. ‘界面’中所需的所有变量和函数,只要直接声明在setup() 函数内即可
5. 所有要在“界面”上使用的变量或事件处理函数都要放在return 中返回才能使用
因为有的成员需要抛出到界面,而有的长远不需要抛出到界面仅程序内部使用,return 就是分水岭
// 示例 <template> <div> <ul> <li v-for='(t,i) of arr' :key='i'> <button @click='change(i)'>{{ t }}</button> </li> </ul> </div> </template> <scripte> import { defineComponent,ref } from 'vue'; export default defineComponent({ let arr = ref(['tom','jerry','haha']); const change=i=>arr.value[i] = 'nana'; return{ arr,change } }) </script>
新变化
如果一个组件对象中有多个变量值都要返回给界面使用,在return中罗列会让代码过于繁琐。所以将多个变量放在一个对象中,集中保存,并用ref 和toRefs 配合,为每个变量添加监视
1. 将这个功能所有变量都集中保存在一个自定义对象data 中,并在创建对象时,用ref() 包裹{} 及其内容(原理就是ref() 会深度遍历对象中每个成员,甚至遍历成员的子成员,并且自动为各级成员及其子成员添加监视)
2. 再将data 对象中的成员分别解构出来,单独使用(注意:ref 包裹的对象成员虽然在对象内部是被监视的,但是一旦解构出来,就成了普通的变量,不再受监视。修改变量,无法自动更新界面 )
所以,解构时 =右边的data 对象必须用toRefs() 包裹(其原理就是toRefs() 会自动为从data中解构出的每个成员再次调用ref() ,使每个成员即使解构出来,也是受监视的)
但是,使用toRefs() 函数前,也必须先在开头import 中从vue 中解构出来才能使用
代码示例:
<template> <div> <button @click='minus'>-</button> <span>{{ n }}</span> <button @click='add'>+</button> </div> <div> <ul> <li v-for="(t,i) of arr" :key="i"> <button @click='change(i)'>{{ t }}</button> </li> </ul> </div> </template> <script> import {defineComponent,ref,toRefs} from 'vue' export default defineComponent({ name:'home', setup(){ //let n=ref(0); //let arr=ref(['4','5','6']) // toRefs 解构写法 const mydata=ref({ n:0, arr=['4','5','6'] })
let { n,arr }=toRefs(mydata.value);
const myMethods{
change(i:any){
arr.value[i]='tom'
},
add(){
n.value++;
},
minus(){
n.value>0 && n.value--;
}
}
//const change=(i:any)=>arr.value[i]='tom'; //const add=()=>n.value++; //const minus=()=>n.value>0&&n.value--; //return{ // n,arr,change,add,minus //} // toRefs 解构写法 return{ ...toRefs(mydata.value),...myMethods } } }) </script>
总结:ref 负责把一个对象里的所有的属性添加成响应式的,toRefs负责把所有的响应式对象当中的每个成员解构出来单独使用,而每个成员也是响应式的(vue2中的...解构会让解构出的成员不再是响应式)
watch 的变化
vue3 的watch 是通过函数实现的。且一个组件中可以有多个watch()
指令的变化(directive)
vaue3 中2中自定义指令:
1.全局自定义指令:main.ts中
注意:vue3 自定义指令中用mounted() 函数代替了vue2中的inserted() 函数。但是其他用法保持一致
// main.ts 中创建一个名为 my-focus 的全局指令 var app = createApp(App) app.directive('my-focus',{ mounted(el){ el.focus(); } }) app.use(store).use(router).mount('#app'); // 在页面中使用指令 <input v-my-focus />
2.局部自定义指令:vue文件中
注意:除了mounted() 代替了inserted() 之外,其余与vue2 相同
// 局部自定义指令 功能页面中 export default defineComPonent({ directives:{ "my-focus":{ mounted(el){ el.focus(); } } } })
计算属性的变化
vue3 中计算属性也是通过专门的函数实现
过滤器(vue3 中已不再支持过滤器,可用计算属性代替)
注册全局组件:main.ts 中(以前vue.component,现在是app.component)