美文网首页
Vue3 新特性

Vue3 新特性

作者: 我是Msorry | 来源:发表于2021-01-13 15:41 被阅读0次
  • 重构响应式系统,使用Proxy替换Object.defineProperty,使用Proxy优势:
  • 可直接监听数组类型的数据变化
  • 监听的目标为对象本身,不需要像Object.defineProperty一样遍历每个属性,有一定的性能提升
  • 可拦截 applyownKeyshas等13种方法,而Object.defineProperty不行
  • 直接实现对象属性的新增/删除
  • 新增 Composition API,更好的逻辑复用和代码组织
  • 重构 Virtual DOM
  • 模板编译时的优化,将一些静态节点编译成常量
  • slot 优化,将 slot 编译为 lazy 函数,将 slot 的渲染的决定权交给子组件
  • 模板中内联事件的提取并重用(原本每次渲染都重新生成内联函数)
  • 代码结构调整,更便于Tree shaking,使得体积更小
  • 使用 Typescript 替换 Flow

使用 Composition API

  1. setup
 export default {
     props: {
        str: String
     },
     setup(props, context) {
         console.log(props) // str
         console.log(context)  // attrs, slots, parent, root, emit, refs
     },
 }
  1. relative
 import { reactive } from 'vue'
 export default {
     setup() {
         const state = reactive({count: 0}) // 创建响应式数据对象
         return state //将响应式数据对象 return 出去,供 template 使用
     }
 }
  1. ref
    ref() 函数根据给定的值创建一个响应式的数据对象,返回值是一个对象,这个对象上只包含一个 .value 属性
 import { ref } from 'vue'
 export default {
     setup() {
         const count = ref(0) // 创建响应式数据对象 count,初始值为 0
         console.log(count.value) // 在setup内访问count值需要.value 属性才可以,但在template中可以直接访问
         return {
            count
         }
     },
 }
  1. toRefs
    toRefs() 函数可以将 reactive() 创建出来的响应式对象,转换为普通的对象,只不过,这个对象上的每个属性节点,都是 ref() 类型的响应式数据

 import { reactive, toRefs } from 'vue'

 export default {

     setup() {
         const state = reactive({count: 0, name:'weedsFly'}) // 用reactive集中创建多个响应式对象
         const add = () => { // methods写在setup内
             state.count++
         }
         return {
             // ...state,  // 使用展开运算符后 用reactive创建的响应式数据 变成了 固定的值
             ...toRefs(state), // 可以用toRefs函数 将传进来的非响应式对象 转成 ref() 类型的响应式数据

             add
        }
    },
 }
  1. watch
    1. 监视单个数据源变动

监视单个 reactive 创建的数据源


 import { reactive, watch } from 'vue'

 export default {
     setup() {
         const state = reactive({count: 100}) 
         watch(
             () => state.count,
             (newVal, oldVal) => { console.log(newVal, oldVal)},
             {lazy: true} // 在 watch 被创建的时候,不执行回调函数中的代码
         )
         setTimeout(() => {
            state.count++
         }, 1500)
     }
 }

监视单个 ref 创建的数据源


 import { ref, watch } from 'vue'

 export default {
     setup() {
         const count = ref(100) 
         watch(
             count,
             (newVal, oldVal) => { console.log(newVal, oldVal)},
             {lazy: true} // 在 watch 被创建的时候,不执行回调函数中的代码
         )
         setTimeout(() => {
            count++
         }, 1500)
     }
 }
    1. 监视多个数据源

监视多个 reactive 创建的数据源


 import { reactive, watch } from 'vue'

 export default {
     setup() {
     const state = reactive({count: 100, name: 'Laiyj'})
     watch(
         [() => state.count, () => state.name],
         ([newCount, newName], [oldCount, oldName]) => { 
             console.log(newCount, oldCount)
             console.log(newName, oldName)
         },
         {lazy: true} // 在 watch 被创建的时候,不执行回调函数中的代码
     )
     setTimeout(() => {
         state.count++
         state.name = 'Lucy'
     }, 1000)
     }
 }

监视多个 ref 创建的数据源


 import { ref, watch } from 'vue'

 export default {
     setup() {
         const count = ref(100)
         const name = ref('Laiyj')
         watch(
             [count, name],
             ([newCount, newName], [oldCount, oldName]) => {
                 console.log(newCount, oldCount)
                 console.log(newName, oldName)
             },
             {lazy: true} // 在 watch 被创建的时候,不执行回调函数中的代码
         )
         setTimeout(() => {
             count++
             name = 'Lucy'
         }, 1000)
     }
 }
    1. 清除watch监视

 import { ref, watch } from 'vue'

 export default {
     setup() {
         const count = ref(100)
         const stop = watch( // 创建监视,并得到 停止函数
             count,
             (newVal, oldVal) => {
                 console.log('I am watching.')
                 console.log(newVal, oldVal)
             },
             {lazy: true} // 在 watch 被创建的时候,不执行回调函数中的代码
         )
         setTimeout(() => {
            count++
         }, 1000)
         const clearWatch = () => {
            stop()
         }
         return {
             count,
             clearWatch
         }
     }
 }
    1. 在 watch 中清除无效的异步任务(与节流防抖同效)

 import { ref, watch } from 'vue'

 export default {
     setup() {
         const keyword = ref('')
         const asyncPrint = (val) => { // 执行异步任务,并得到关闭异步任务的 timerId
             return setTimeout(() => {
                console.log(val)
             }, 1000)
         }
         watch(
             keyword,
             (newVal, oldVal, onClean) => {
                 const timeId = asyncPrint()
                 onClean(() => {clearTimeout(timeId)}) // 如果 watch 监听被重复执行了,则会先清除上次未完成的异步任务
             }
         )
         return {
             keyword
         }
     }
 }
  1. provide & inject
    provide() 和 inject() 可以实现嵌套组件之间的数据传递。
    这两个函数只能在 setup() 函数中使用。
    父级组件中使用 provide() 函数向下传递数据;子级组件中使用 inject() 获取上层传递过来的数据。

相关文章

网友评论

      本文标题:Vue3 新特性

      本文链接:https://www.haomeiwen.com/subject/paldaktx.html