<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          做了一夜動畫,就為讓大家更好的理解Vue3的Composition Api

          共 5293字,需瀏覽 11分鐘

           ·

          2021-01-21 08:24

          轉(zhuǎn)自:掘金 - 蝸牛老濕_大圣

          這個文章其實很簡單, 只要能說明composition的好處,就是極好的,我們用一個非常簡單的萬金油場景,比如我們有一個非常簡單的to do list

          回顧Option

          <template>
          ??<div?id="app">
          ????<input?type="text"?v-model="val"?@keyup.enter="addTodo">
          ????<ul>
          ??????<li?v-for="todo?in?todos"?:key="todo.id">{{todo.title}}li>
          ????ul>
          ??div>
          template>
          <script>
          export?default?{
          ??data(){
          ????return{
          ??????val:'',
          ??????todos:[?
          ????????{id:0,?title:'吃飯',?done:false},
          ????????{id:1,?title:'睡覺',?done:false},
          ????????{id:2,?title:'lsp',?done:false},
          ??????]
          ????}
          ??},
          ??methods:{
          ????addTodo(){
          ??????this.todos.push({
          ????????id:this.todos.length,
          ????????title:this.val,
          ????????done:false
          ??????})
          ??????this.val?=?''
          ????}
          ??}
          }
          script>

          需求復(fù)雜之后,就會多出watch,computed,inject,provide等配置,這個.vue文件也會逐漸增大

          Option的缺陷--反復(fù)橫跳

          相信大部分同學(xué)都維護(hù)過超過200行的.vue組件,新增或者修改一個需求,就需要分別在data,methods,computed里修改 ,滾動條反復(fù)上下移動,我稱之為『反復(fù)橫跳』 比如我們簡單的加個拍腦門的需求 加個累加器 ,這種寫代碼上下反復(fù)橫條的感覺, 相信大家都懂的,?

          動畫演示

          <template>
          ??<div?id="app">
          ????<h1?@click="add">LSP?{{count}}號?double?is{{double}}h1>
          ????<input?type="text"?v-model="val"?@keyup.enter="addTodo">
          ????<ul>
          ??????<li?v-for="todo?in?todos"?:key="todo.id">{{todo.title}}li>
          ????ul>
          ??div>
          template>

          <script>
          import?Counter?from?'./counter'
          export?default?{
          ??mixins:[Counter],
          ??data(){
          ????return{
          ??????count:1,
          ??????val:'',
          ??????todos:[?
          ????????{id:0,?title:'吃飯',?done:false},
          ????????{id:1,?title:'睡覺',?done:false},
          ????????{id:2,?title:'lsp',?done:false},
          ??????]
          ????}
          ??},
          ??computed:?{
          ????double()?{
          ??????return?this.count?*?2
          ????}
          ??},
          ??methods:{
          ????addTodo(){
          ??????this.todos.push({
          ????????id:this.todos.length,
          ????????title:this.val,
          ????????done:false
          ??????})
          ??????this.val?=?''
          ????},
          ????add(){
          ??????this.count++
          ????}
          ??}
          }
          script>

          Option的缺陷:mixin和this

          反復(fù)橫跳的本質(zhì),在于功能的分塊組織,以及代碼量太大了,如果我們能把代碼控制在一屏,自然就解決了,vue2里的解決方案,是使用mixin來混合, 我們抽離一個counter.js

          export?default?{
          ??data()?{
          ????return?{
          ??????count:1
          ????}
          ??},
          ??computed:?{
          ????double()?{
          ??????return?this.count?*?2
          ????}
          ??},
          ??methods:{
          ????add(){
          ??????this.count++
          ????}
          ??}
          }

          在App.vue中

          import?Counter?from?'./counter'
          export?default?{
          ??mixins:[Counter],
          ??data(){
          ?...
          ??},
          ...
          }

          這樣確實拆分了代碼,但是有一個賊嚴(yán)重的問題,就是不打開counter.js,App.vue里的this上,count,add這些屬性,是完全不知道從哪來的,你不知道是mixin,還是全局install,還是Vue.prototype.count設(shè)置的,數(shù)據(jù)來源完全模糊,調(diào)試爽死你,這也是option的一個大問題,this是個黑盒,template里寫的count和double,完全不知道從哪來的

          mixin命名沖突

          如果有兩個mixin,就更有意思了,比如我們又有一個需求,實時顯示鼠標(biāo)的坐標(biāo)位置x,并且有一個乘以2的計算屬性湊巧也叫double,再整一個mixin

          export?default?{
          ??data()?{
          ????return?{
          ??????x:0
          ????}
          ??},
          ??methods:{
          ????update(e){
          ??????this.x?=?e.pageX
          ????}
          ??},
          ??computed:{
          ????double(){
          ??????return?this.x*2
          ????}
          ??},
          ??mounted(){
          ????window.addEventListener('mousemove',?this.update)
          ??},
          ??destroyed(){
          ????window.removeEventListener('mousemove',?this.update)
          ??}
          }

          這是是一個獨立維護(hù)的mixin,可能在N個地方用到,他根本不知道會不會有人和他沖突,然后用一下

          import?Counter?from?'./counter'
          import?Mouse?from?'./mouse'
          export?default?{
          ??mixins:[Counter,Mouse],
          ??......?
          }

          兩個mixin里都有double這個數(shù),尷尬,看效果 ,lsp的count被覆蓋了 很尷尬,而且在App.vue這里,你完全不知道這個double到底是哪個,調(diào)試很痛苦

          Composition

          composition就是為了解決這個問題存在的,通過組合的方式,把零散在各個data,methods的代碼,重新組合,一個功能的代碼都放在一起維護(hù),并且這些代碼可以單獨拆分成函數(shù) ,也就是大帥的這兩個gif

          我們用vue3演示一下功能,具體api就不解釋了 直接vue3文檔搞起就可以

          <template>
          ??<div?id="app">
          ????<input?type="text"?v-model="val"?@keyup.enter="addTodo">
          ????<ul>
          ??????<li?v-for="todo?in?todos"?:key="todo.id">{{todo.title}}li>
          ????ul>
          ??div>
          template>

          <script>
          import?{reactive,?ref,?toRefs}?from?'vue'

          export?default?{
          ??setup(){
          ????let?val?=?ref('')
          ????let?todos?=?reactive([?
          ????????{id:0,?title:'吃飯',?done:false},
          ????????{id:1,?title:'睡覺',?done:false},
          ????????{id:2,?title:'lsp',?done:false},
          ????])
          ????function?addTodo(){
          ??????todos.push({
          ????????id:todos.length,
          ????????title:val.value,
          ????????done:false
          ??????})
          ??????val.value?=?''
          ????}
          ????return?{val,?todos,?addTodo}
          ??}
          }
          script>

          利用函數(shù)我們可以吧功能完整獨立的拆分成模塊或者函數(shù),方便組織代碼,并且解決了mixin混亂的問題

          比如我們的累加器 ,抽離一個counter.js


          import?{ref,?computed}?from?'vue'

          export?default?function?useCounter(){
          ????let?count?=?ref(1)
          ????function?add(){
          ????????count.value++
          ????}
          ????let?double?=?computed(()=>count.value*2)
          ????return?{count,?double,?add}
          }


          直接使用

          import?{reactive,?ref,?toRefs}?from?'vue'
          +?import?useCounter?from?'./counter'
          export?default?{
          ??setup(){
          ????let?val?=?ref('')
          ?...
          +?????let?{count,double,add}?=?useCounter()?
          ????return?{
          ??????val,?todos,?addTodo,
          +?????count,double,add
          ????}
          ??}
          }

          再來一個鼠標(biāo)位置也不在話下,而且可以很好地利用解構(gòu)賦值的別名,解決mixin的命名沖突問題 mouse.js

          import?{ref,?onMounted,?onUnmounted,?computed}?from?'vue'

          export?default?function?useMouse(){
          ??let?x?=?ref(0)
          ??function?update(e){
          ????x.value?=?e.pageX
          ??}
          ??let?double?=?computed(()=>x.value*2)
          ??onMounted(()=>{
          ????window.addEventListener('mousemove',?update)
          ??})
          ??onUnmounted(()=>{
          ????window.removeEventListener('mousemove',?update)
          ??})
          ??return?{x,?double}
          ??
          }

          模板里直接用doubelX

          let?{count,double,add}?=?useCounter()?
          let?{x,?double:doubleX}?=?useMouse()
          return?{
          ??val,?todos,?addTodo,
          ??count,double,add,
          ??x,doubleX
          }

          script setup

          到這里應(yīng)該就把大帥的文章缺的代碼補(bǔ)了一下,不過有的同學(xué)可能,還有一個小小的吐槽,那就是setup函數(shù)最后的return也是集中的,如果行數(shù)太多,一樣會橫條一下下,這個好解決,因為本身我們可以吧todos也抽離成函數(shù),這樣setup就全部是數(shù)據(jù)的來源,非常精簡絲滑

          import?useCounter?from?'./counter'
          import?useMouse?from?'./mouse'
          import?useTodo?from?'./todos'
          export?default?{
          ??setup(){
          ????let?{?val,?todos,?addTodo?}?=?useTodo()
          ????let?{count,double,add}?=?useCounter()?
          ????let?{x,?double:doubleX}?=?useMouse()
          ????return?{
          ??????val,?todos,?addTodo,
          ??????count,double,add,
          ??????x,doubleX
          ????}
          ??}
          }

          是不是賊爽呢,如果有些同學(xué)就是不想啥都抽離,還是覺得統(tǒng)一return很麻煩, 我們可以使用vue3的setup script功能,把setup這個配置也優(yōu)化掉 一個功能export一次

          <script?setup>
          import?useCounter?from?'./counter'
          import?useMouse?from?'./mouse'
          import?useTodo?from?'./todos'

          let?{?val,?todos,?addTodo?}?=?useTodo()
          export?{val,?todos,?addTodo}

          let?{count,double,add}?=?useCounter()
          export?{count,double,add}

          let?{x,?double:doubleX}?=?useMouse()
          export?{x,doubleX}

          script>

          具體看這里:

          https://github.com/vuejs/rfcs/blob/sfc-improvements/active-rfcs/0000-sfc-script-setup.md

          - EOF -


          專注分享當(dāng)下最實用的前端技術(shù)。關(guān)注前端達(dá)人,與達(dá)人一起學(xué)習(xí)進(jìn)步!

          長按關(guān)注"前端達(dá)人"


          瀏覽 124
          點贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  久久成人电影院 | 色色五月丁香婷婷 | 日韩视频第一页 | 欧美久久性爱视频 | 美女免费一级操逼视频 |