<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>

          那個(gè)忙了一夜的Vue3動(dòng)畫很好,就是太短了

          共 5260字,需瀏覽 11分鐘

           ·

          2021-01-26 18:07


          (給前端大學(xué)加星標(biāo),提升前端技能.

          轉(zhuǎn)自:?蝸牛老濕_大圣

          這個(gè)文章其實(shí)很簡單, 只要能說明composition的好處,就是極好的,我們用一個(gè)非常簡單的萬金油場景,比如我們有一個(gè)非常簡單的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ù)雜之后,就會(huì)多出watch,computed,inject,provide等配置,這個(gè).vue文件也會(huì)逐漸增大

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

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

          動(dòng)畫演示

          <template>
          ??<div?id="app">
          ????<h1?@click="add">LSP?{{count}}號(hào)?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來混合, 我們抽離一個(gè)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(){
          ?...
          ??},
          ...
          }

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

          mixin命名沖突

          如果有兩個(gè)mixin,就更有意思了,比如我們又有一個(gè)需求,實(shí)時(shí)顯示鼠標(biāo)的坐標(biāo)位置x,并且有一個(gè)乘以2的計(jì)算屬性湊巧也叫double,再整一個(gè)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)
          ??}
          }

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

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

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

          Composition

          composition就是為了解決這個(gè)問題存在的,通過組合的方式,把零散在各個(gè)data,methods的代碼,重新組合,一個(gè)功能的代碼都放在一起維護(hù),并且這些代碼可以單獨(dú)拆分成函數(shù) ,也就是大帥的這兩個(gè)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ù)我們可以吧功能完整獨(dú)立的拆分成模塊或者函數(shù),方便組織代碼,并且解決了mixin混亂的問題

          比如我們的累加器 ,抽離一個(gè)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
          ????}
          ??}
          }

          再來一個(gè)鼠標(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é)可能,還有一個(gè)小小的吐槽,那就是setup函數(shù)最后的return也是集中的,如果行數(shù)太多,一樣會(huì)橫條一下下,這個(gè)好解決,因?yàn)楸旧砦覀兛梢园蓆odos也抽離成函數(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這個(gè)配置也優(yōu)化掉 一個(gè)功能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

          瀏覽 39
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <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>
                  jiujiujiu999 | 操女综合网 | 青草免费视频 | 黄色视频网站免费 | 秋霞视频网 |