目录
-
data的双向绑定
-
vue3.0
通过Proxy来劫持数据,当数据发生变化时发出通知<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="yingaxiang" content="width=device-width, initial-scale=1.0"> <title>vue3.0数据双向绑定</title> </head> <body> <div> <input type="text" id="input"> <span id="text"></span> </div> </body> </html> <script> var obj = {}; var obj1 = new Proxy(obj, { // target就是第一个参数obj, receive就是返回的obj(返回的proxy对象) get: function (target, key, receive) { // 返回该属性值 return target[key]; }, set: function (target, key, newVal, receive) { // 执行赋值操作 target[key] = newVal; document.getElementById('text').innerHTML = target[key]; } }) document.addEventListener('keyup', function (e) { obj1[0] = e.target.value; }); </script>
-
vue2.0
通过Object.defineProperty来劫持对象属性的getter和setter操作,当数据发生变化时发出通知// 数据 let data = { title: '', // 备份数据 _data: {} } // 定义特性 Object.defineProperty(data, 'title', { // 定义特性属性或者特性方法 // 取值方法 get() { // console.log('get') // 注意:不能通过自身属性取值 // return this.title // 返回备份的数据 return this._data.title; }, // 赋值方法 set(value) { // this指向对象 // 注意:不能为自身属性赋值 // this.title = value // 我们可以向备份数据中存储 this._data.title = value; // console.log('set') // 更新视图 updateView(this._data) } }) // 视图模板 let tpl = document.getElementById('app').innerHTML // 实现更新视图的方法 function updateView(data) { // 处理模板 let html = tpl.replace(/{{(w+)}}/g, (match, $1) => { // 从data中获取数据 return data[$1] || '' }) // 更新视图 document.getElementById('app').innerHTML = html; }
2.0劫持对象的属性,3.0代理对象数据,所以删除和新建都能检测到
Vue2.x版本中的双向绑定不能检测到下标的变化
proxy可以劫持整个对象,并返回一个新对象 -
2.x 版本中,使用 Vue.set 来给对象新增一个属性时,这个对象的所有 watcher 都会重新运行
3.x 版本中,只有依赖那个属性的 watcher 才会重新运行
-
-
创建项目
- 2.0用的vue-cli是vue-cli2
- 3.0使用的是vue-cli4
-
语法
-
v-model语法糖废弃,改用modelValue
<input v-model="value" /> <input modelValue="value" />
-
弃用全局APInew Vue,使用createApp
const app =?Vue.createApp({})
-
弃用Vue.prototype,在Vue3中,我们可以使用如下定义方式
const app = Vue.createApp({}) app.config.globalProperties.$http = () => {}
-
全局方法现在全部在app实例上,例如:
`app.directive`,`app.use`等
-
现在你需要手动挂载根节点
main.js import { createApp } from 'vue' import App from './App.vue' createApp(App).mount('#app')
-
不能再使用Vue.nextTick/this.$nextTick,Vue3中你可以用:
import { nextTick } from 'vue' nextTick(() => { // something })
-
Vue3允许template设置key,可以有多个根
-
正式弃用scopedSlots正式弃用,旧的不去新的不来
-
监听数组变化需要使用deep属性,否则只能监听到整个数组被替换
-
弃用$children,访问子组件可以使用$ref
-
filter被移除,我X,不能再使用|了
-
移除事件API,$on,$once,$off不再使用。EventBus方法也不再使用。
-
v-for的ref不使用数组,可以是对象
在v-for
语句中使用ref
属性 将不再会自动在$refs
中创建数组。而是,将ref
绑定到一个function
中,在function
中可以灵活处理ref
<div v-for=(item, index) in arrList> <div :ref="el => myRefs[index]=el"></div> </div> setup(){ const myRefs = ref([]) as Ref<string[]> return { myRefs, } }
-
懒加载显示配置
vue2.0 // 不带选项的异步组件 const asyncModal = () => import('./Modal.vue') //对于带有选项的更高阶的组件语法: const asyncModal = { component: () => import('./Modal.vue'), delay: 200, timeout: 3000, error: ErrorComponent, loading: LoadingComponent } vue3.0 import { defineAsyncComponent } from 'vue' import ErrorComponent from './components/ErrorComponent.vue' import LoadingComponent from './components/LoadingComponent.vue' // 不带选项的异步组件 const asyncModal = defineAsyncComponent(() => import('./Modal.vue')) // 带选项的异步组件 const asyncModalWithOptions = defineAsyncComponent({ loader: () => import('./Modal.vue'), delay: 200, timeout: 3000, errorComponent: ErrorComponent, loadingComponent: LoadingComponent })
-
$emit()父组件传入的方法,类似于$props父组件传入的数据.也可以创建默认数据格式.移除了v-on.native,两者同时使用,方法会执行两遍
Props被移除,直接使用CreateApp(*, {prop1:prop1})第二个参数就可以传prop -
template支持多根代码片段
-
v-model修改
<ChildComponent v-model="pageTitle" /> <!-- 是以下的简写: --> <ChildComponent :value="pageTitle" @input="pageTitle = $event" />
-
-
目录结构
- vue-cli2.0与3.0在目录结构方面,有明显的不同
- vue-cli3.0移除了配置文件目录,config 和 build 文件夹
- 同时移除了 static 静态文件夹,新增了 public 文件夹,打开层级目录还会发现, index.html 移动到 public 中
- 3.0 config文件已经被移除,但是多了.env.production和env.development文件,除了文件位置,实际配置起来和2.0没什么不同
- 没了config文件,跨域需要配置域名时,从config/index.js 挪到了vue.config.js中,配置方法不变
- 移除了 static 文件夹,新增 public 文件夹,并且 index.html 移动到 public 中
在 src 文件夹中新增了 views 文件夹,用于分类 视图组件 和 公共组件
-
生命钩子函数
- 对比
options api setup api 说明 beforeCreate not needed 组件创建之前 created not needed 组件创建完成 beforeMount onBeforeMount 组件挂载之前 mounted onMounted 组件挂载完成 beforeUpdate onBeforeUpdate 数据更新,虚拟 DOM 打补丁之前 updated onUpdated 数据更新,虚拟 DOM 渲染完成 beforeDestroy onBeforeUnmount 组件销毁之前 destroyed onUnmounted 组件销毁后
errorCaptured onErrorCaptured 报错 renderTracked onRenderTracked 跟踪虚拟 DOM 重新渲染时调用 renderTriggered onRenderTriggered 当虚拟 DOM 重新渲染被触发时用 activated onActivated 被 keep-alive 缓存的组件激活时用 deactivated onDeactivated 被 keep-alive 缓存的组件失活时用 -
setup
中的函数,接收一个回调函数,当钩子被组件调用时将会被被执行。<template> <router-link to="/">点这里去首页</router-link> <div class="home"> 这里是一个计数器 >>> <span class="red">{{count}}</span> <br> <button @click="countAdd">点击加数字</button> </div> </template> <script> // 你需要使用到什么生命周期,就引出来什么生命周期 // 首先,在 vue 3.0 中,生命周期是从 vue 中导出的,我们需要用到哪些,就导出哪些。 import {onBeforeMount,onMounted,onBeforeUpdate,onUpdated,onBeforeUnmount,onUnmounted,ref} from 'vue' export default { // setup 函数,就相当于 vue 2.0 中的 created setup () { const count = ref(0) // 其他的生命周期都写在这里 onBeforeMount (() => { count.value++ console.log('onBeforeMount', count.value) }) onMounted (() => { count.value++ console.log('onMounted', count.value) }) // 注意,onBeforeUpdate 和 onUpdated 里面不要修改值,会死循环的哦! onBeforeUpdate (() => { console.log('onBeforeUpdate', count.value) }) onUpdated (() => { console.log('onUpdated', count.value) }) onBeforeUnmount (() => { count.value++ console.log('onBeforeUnmount', count.value) }) onUnmounted (() => { count.value++ console.log('onUnmounted', count.value) }) // 定义一个函数,修改 count 的值。 const countAdd = () => { count.value++ } return { count,countAdd} }} </script>
- 对比
-
setup更新
-
beforeCreate:表示组件刚刚被创建出来,组件的data和methods还没有初始化好
Created: 表示组件刚刚被创建出来,并且组件的data和methods已经初始化好 -
setup函数是 Composition API(组合API)的入口
-
在setup函数中定义的变量和方法最后都是需要 return 出去的 不然无法再模板中使用
-