記一次Vue3.0技術乾貨分享會

echa攻城獅 發佈 2020-05-24T15:54:22+00:00

前面小編也整理了關於Vue 3.0的設計原則、入門語法、虛擬Dom、Vue3.0 Beta版本新特性知識點匯總等等,在這裡小編就不一一講解了。




作者:lulu_up

轉發連結:https://segmentfault.com/a/1190000022719461

前言

前面小編也整理了關於Vue 3.0的設計原則、入門語法、虛擬Dom、Vue3.0 Beta版本新特性知識點匯總等等,在這裡小編就不一一講解了。更多Vue2.x到Vue3.x 入門到實踐知識點相關文章,請見本篇文章底部,好東西都在下面。

一. 版本

當前還處於 beta版本, 想要正式使用在項目里還需要一段的時間, 但是結構與api變化應該不大了.

     這裡列出的並不全, 但是夠用了
1. alpha 內測版本
2. beta  公測版本
3. Gamma 正式發布的候選版本
4. Final 正式版
5. plus  增強版
6. full  完全版 
7. Trial 試用版(一般有時間或者功能限制)

二. 介紹

  1. 學一門新鮮的技術,就像練習王者榮耀新出的英雄一樣, 探索他的好玩之處可以給開發者帶來快樂, 使用新的好的技術會讓工作更愉悅

  2. 這個版本的vue 類似"我的世界", 全部都是一個個方塊組成, 不要小看方塊, 方塊多了甚至可以組成圓形(量變引起質變), 新鮮的玩法才能激發我們的興趣

三. vue3.0的環境搭建

準備一套搭建好的環境防治到時候出現意外, 現場再按照步驟搭建一版, 每一步都不要落下能讓大家更好的理解.

  1. npm install -g @vue/cli  cli升級到4版本

  2. 隨便創建個項目, vue create next-test

  3. 選擇配置最好把router與vuex一起選上, 方便後續升級

  4. vue add vue-next   cli提供的進化到下一版本的命令, 執行後自動將router, vuex 升級到alpha版.

四. vue3.0重要的優化

  1. 模板編譯速度的提升, 對靜態數據的跳過處理.
  2. 對數組的監控
  3. 對ts有了很好的支持
  4. 對2.x版本的完全兼容
  5. 可以有多個根節點 (也有bug, 比如外層開了display:flex 那麼裡面會收到影響, 也就是說布局更靈活但也更要小心, 總之請對自己與他人的代碼負責)
  6. 支持Source map, 雖然沒演示但是這點真的重要

五. vuex, router, vue 初始化寫法的變化

vue:

import { createApp } from 'vue';
import App from './App.vue'
import router from './router'
import store from './store'

// 方法一. 創建實例變成了鏈式, 直接寫下去感覺語義與結構有點模糊, 但是我們要理解vue這樣做的良苦用心, 前端趨近於函數化.
// createApp(App).use(router).use(store).mount('#app')

// 方法二.
const app = createApp(App);
app.use(router);
app.use(store);
app.mount('#app');

vuex:

import { createStore } from 'vuex'
// 專門創建實例的一個方法
export default createStore({
  state: {
  },
  mutations: {
  },
  actions: {
  },
  modules: {
  }
});

router

import { createRouter, createWebHistory } from 'vue-router';
import Home from '../views/Home.vue'

const routes = [
  {
    path: '/',
    name: 'Home',
    component: Home
  }
]

const router = createRouter({
// 專門創建history的函數
  history: createWebHistory(process.env.BASE_URL),
  routes
})

export default router

六. 變量的定義

1: ref

import { ref } from "vue";
export default {
  // 1: 這個版本基本邏輯都在setup裡面完成了, 有人說把他當成2.x的data.
  setup() {
    // 2: 定義一個追蹤的變量,也就是雙向綁定.
    const n = ref(1); // 生成的n是一個對象, 這樣方便vue去監控它
    function addN() {
      n.value++; // 注意這裡要使用.value的形式, 因為n是對象↑, value才是他的值
    }
    return {
      n,   // 返回出去頁面的template才可以使用它, {{n}} 不需要.value
      addN
    }
  }
 }

2: reactive

import { reactive, toRefs } from "vue";
export default {
  setup() {
    // 注意事項: reactive的對象不可以結構返回或導入, 會導致失去響應式
    const obj = reactive({
      name: "金毛",
      age: 4
    });
    function addObj() {
      obj.age++;
    }
    return {
      ...obj, // 這樣寫不好, 裡面會失去響應式
      obj, // 這樣寫那麼外面就要都基於obj來調取, 類型{{obj.age}}
      ...toRefs(obj) // 必須是reactive生成的對象, 普通對象不可以, 他把每一項都拿出來包了一下, 我們可以這樣用了 {{age}}, 放心咱們多深的obj也可以響應
    }
  }
 }

7. 之前的ref何去何從

這個老兄被別人搶了關鍵詞, 也只能自己改改寫法了

  <div>
    <div ref="content">第一步, 在dom上面定義, 他會有一個回調</div>
  </div>
  <ul>
    <li>v-for 出來的ref</li>
    <li>可以寫為表達式的形式, 可以推導出vue是如何實現的</li>
    <li>vue2.x的時候v-for不用這麼麻煩, 直接寫上去會被組裝成數組</li>
    <li :ref="el => { items[index] = el }" v-for="(item,index) in 6" :key="item">{{item}}</li>
  </ul>
import { ref, onMounted, onBeforeUpdate } from "vue";
export default {
  setup() {
    // 2: 定義一個變量接收dom, 名字無所謂, 但是與dom統一的話會有很好的語義化
    const content = ref(null);
    const items = ref([]);

    // 4: 在生命周期下, 這個值已經完成了變化, 所以當然第一時間就拿到
    onMounted(() => {
      console.log(content.value);
      console.log("li標籤組", items.value);
    });

    // 5: 確保在每次變更之前重置引用
    onBeforeUpdate(() => {
      items.value = [];
    });

    // 3: 返出去的名稱要與dom的ref相同, 這樣就可以接收到dom的回調
    return {
      content,
      items
    };
  }
};

8. 生命周期

<template>
  <div>
    <button @click="add">點擊增加, 觸發updata</button>
    <p>{{obj.count}}</p>
  </div>
  <p>
    2.x與 3.0的對照
    beforeCreate -> 使用 setup()
    created -> 使用 setup()
    beforeMount -> onBeforeMount
    mounted -> onMounted
    beforeUpdate -> onBeforeUpdate
    updated -> onUpdated
    beforeDestroy -> onBeforeUnmount
    destroyed -> onUnmounted
    errorCaptured -> onErrorCaptured
  </p>
</template>

<script>

//這些生命周期註冊方法只能用在 setup 鉤子中
import { onMounted, onUpdated, onBeforeUnmount, reactive } from "vue";
export default {
  // 1: setup顯得冗長, 可以自己動手做一些插件來優化
  // 2: 本身更加明確意圖
  // 3: 需要樹立工程師的正確代碼意識
  // 4: 能力不足可能會寫出更差的代碼
  // 作者說: 提升上界的收益遠遠大於降低下界的損失。值得深思, 前端需要提高門檻
  // 5: 調用時機: 創建組件實例,然後初始化 props ,緊接著就調用setup 函數。從生命周期鉤子的視角來看,它會在 beforeCreate 鉤子之前被調用
  // 6: 這些生命周期鉤子註冊函數只能在 setup() 期間同步使用, 因為它們依賴於內部的全局狀態來定位當前組件實例(正在調用 setup() 的組件實例), 不在當前組件下調用這些函數會拋出一個錯誤。
  // 7: 原則上生命周期裡面不會放具體的邏輯,哪怕只有一句賦值一個三元都不可放, 這也正好符合當前的工程模式

  // 討論: 有多少種方式, 可以判斷出某個函數 當前處於哪個函數?
  //       比如有多層嵌套的組件是否有影響
  setup() {
    onMounted(() => {
      console.log("is mounted!");
    });
    onUpdated(() => {
      console.log("is onUpdated!");
    });
    onBeforeUnmount(() => {
      console.log("is onBeforeUnmount!");
    });
    const obj = reactive({
      count: 1
    });
    function add() {
      obj.count++;
    }
    return {
      obj,
      add
    };
  }
};
</script>

9. 路由

<template>
  <div>
    {{id}}
  </div>
</template>

<script>
import { getCurrentInstance, ref } from 'vue';
export default {
  setup(){
    const { ctx } = getCurrentInstance()
    // 1. 這樣也是為了去掉this
    // 2. 方便類型推導
    console.log(ctx.$router); // push等方法
    console.log(ctx.$router.currentRoute.value); // 路由實例
    // 這個其實沒有必要變成ref因為這個值沒必要動態
    // 但是他太長了, 這個真的不能忍
    const id = ref(ctx.$router.currentRoute.value.query.id)

    // 4: 頁面攔截器
    ctx.$router.beforeEach((to, from,next)=>{
      console.log('路由的生命周期')
      next()
    })
    return {
      id
    }
  }
}

</script>

10. vuex

import { createStore } from 'vuex'

// 難道前端趨勢只有函數這一種嗎
export default createStore({
  state: {
    name:'牛逼, 你拿到我了',
    age: 24,
    a:'白',
    b:'黑'
  },
  mutations: {
    updateName(state, n){
      state.name += n
    }
  },
  actions: {
    deferName(store) {
     setTimeout(()=>{
       // 必須只有commit可以修改值, 這個設定我比較反對, 可以討論
       // vuex本身結構就很拖沓, 定義域使用個人都不喜歡
      store.state.name = '牛逼, 你改回來了'
     },1000)
    }
  },
  getters: {
    fullName(state){ return `${state.a} - + -${state.b}` }
  },
  modules: {
  }
});
<template>
  <div>
    <p>{{name}}</p>
    <button @click="updateName('+')">點擊改變名字</button>
    <br />
    <button @click="deferName('+')">改回來</button>

    <p>{{fullName}}</p>
  </div>
</template>

<script>
import { useStore } from "vuex";
import { computed } from "vue";
export default {
  setup() {
    const store = useStore();
    // 1: 單個引入
    const name = computed(() => store.state.name);
    // 2: 引入整個state
    const state = computed(() => store.state);
    console.log("vuex的實例", state.value); // 別忘了.value

    // 3: 方法其實就直接從本體上取下來了
    const updateName = newName => store.commit("updateName", newName);

    // 4: action一個意思
    const deferName = () => store.dispatch("deferName");

    // 5: getter 沒變化
    const fullName = computed(() => store.getters.fullName);
    return {
      name,
      fullName,
      deferName,
      updateName,
    };
  }
};
</script>

11. composition(這個可能是最重要的改革了)

前端算是面向函數編程, 各種規範也都趨近於函數化

composition使得前端工程師的編程規範, 更接近於原生js, 三十年河東三十年河西, 幾年前前端需要模板來進行'規則化', 現在前端又想要更多的自由.

開發工程而不是插件的話, 還是不要使用mixin了, 這東西無法追溯來源, 搞得語義太差了, 我們要對它說'no'.

舉例子的變量命名有點low, 抱歉~~

<template>
  <div>
    <button @click="addN1">上面的增加</button>---> {{n1}}
  </div>
   <div>
    <button @click="addN2">下面的增加</button>---> {{n2}}
    <button @click="addN210">每次n2+10</button>
  </div>
  <div>
    <p>組件裡面也可以如此引用, 這就可以代替mixin一部分功能了</p>
    <button @click="addN3">n3的增加</button>---> {{n3.value}}
  </div>
  <div>
    <com></com>
  </div>
</template>

<script>
import { ref} from 'vue';
import n3Change from './mixin';
import com from '../components/composition.vue';

export default {
  components:{
    com
  },
  setup(){
     // 1: setup只是一個整合函數
     // 2: 甚至整個函數裡面可能會沒有具體的邏輯
     // 3: 以此推斷, ref等方式定義的變量, 會自動識別在哪個setup內部, 從而達到邏輯的復用
     // 4: 由此方法可以很好的代替mixin了
     // 5: 當然, 這裡也可以截獲數據,來做一些事情
     const {n2, addN2} = n2Change();
     function addN210(){
       n2.value += 10
     }
     return {
       ...n1Change(),
       ...n3Change(),
       n2,
       addN2,
       addN210
     }
  }
}
// 甚至已經可以寫在任何地方了, 響應式自由度大大提高
function n1Change(){
   const n1 = ref(1);
   let addN1 = ()=>{
     n1.value++
   }
   return {
     n1,
     addN1
   }
}

function n2Change(){
   const n2 = ref(1);
   let addN2 = ()=>{
     n2.value++
   }
   return {
     n2,
     addN2
   }
}
</script>

寫在任何地方, 然後導入就成了mixin


import { reactive } from 'vue';


export default ()=> {
  const n3 = reactive({
    name: 'mixin',
    value: 1
  })
  const addN3=()=>{
    n3.value++
  }
  return {
    n3,
    addN3
  }
}

12. 插件的新思路

// 開發插件並不一定要掛載到vue的原型上
// 導致vue原型臃腫, 命名衝突等等(比如兩個ui都叫 message)
// 原理就是 provide 和 inject, 依賴注入.

import {provide, inject} from 'vue';

// 這裡使用symbol就不會造成變量名的衝突了, 這個命名權交給用戶才是真正合理的架構設計
const StoreSymbol = Symbol()

export function provideString(store){
  provide(StoreSymbol, store)
}

export function useString() {

  const store = inject(StoreSymbol)

  return store
}

app.vue頁面統一的初始化一下

export default {
  setup(){
    // 一些初始化'配置/操作'可以在這裡進行
    // 需要放在對應的根節點, 因為依賴provide 和 inject
     provideString({
       a:'可能我是axios',
       b:'可能我是一個message彈框'
     })
  }
}

在需要使用的組件裡面接收

<template>
  <div>
    插件的演示
  </div>
</template>

<script>
import { useString } from '../插件';

export default {
  setup(){
    const store = useString();
    // 不光是拿到值, 可以由app定義什麼可以被拿到
    console.log('拿到值了',store)
  }
}

</script>

13. 新觀察者

<template>
  <div>
    <button @click="addn1">n1增加--{{n1}}</button>
    <button @click="addn2">n2增加--{{n2}}</button>
    <button @click="addn3">n3增加--{{n3}}</button>
  </div>
</template>

<script>
import { watch, ref } from "vue";
export default {
  setup() {
    const n1 = ref(1);
    const n2 = ref(1);
    const n3 = ref(1);
    // 1: 監聽一個
    // 第一個參數是函數返回值, 當然也可以 直接寫n1 
    // 如果監聽的是一個對象裡面的某個屬性, 那就需要這種函數的寫法了, 比2.x的字符串寫法高明很多

    watch(
      () => n1.value,
      (val, oldVal) => {
        console.log("新值", val);
        console.log("老值", oldVal);
      }
    );
    // 2: 監聽多個
    // 數組的形式定義多個, 這就出現問題了吧, 如果我觀察的對象就是個數組, 並且每一項都是一個返回值的函數, 豈不是會被他誤認為是多監控的結構, 苦惱
    watch(
      [() => n2.value, ()=>n3.value],
      ([val, val3],[val2, val4]) => {
        // val 是 n2的新值   val2是 n2的老值
        // val3 是 n3的新值  val4是 n3的老值
        console.log("新值 與 老值 是這種對應關係", val, val2);
        console.log("新值 與 老值 是這種對應關係", val3, val4);
      }
    );

    function addn1() {
      n1.value++;
    }
    function addn2() {
      n2.value++;
    }
     function addn3() {
      n3.value++;
    }
    return {
      addn1,
      addn2,
      addn3,
      n1,
      n2,
      n3
    };
  }
};
</script>

13. 新計算屬性

別看watchEffect帶個'watch',但是他的功能可以歸為計算屬性裡面

<template>
  <div>
    <button @click="addCount">點擊計算</button>
    <button @click="setCount(1)">點擊出發set</button>
    <p>count--{{count}}</p>
    <p>count2--{{count2}}</p>
    <p>count3--{{count3}}</p>
  </div>
</template>

<script>
// 弄得類似react了
import { computed, ref, watchEffect } from "vue";
export default {
  setup() {
    const count = ref(1);
    // 1. 默認的定義方式
    const count2 = computed(() => count.value * 2);
    console.log(count2.value); // 也要value因為可能是簡單類型
    // 2. getter與setter當然可以定義
    const count3 = computed({
      get: () => count.value * 3,
      set: val => {
        // 這裡重置了count
        count.value = val;
      }
    });
    // 3. watchEffect 更像是計算函數
    // 立即執行傳入的一個函數,並響應式追蹤其依賴,並在其依賴變更時重新運行該函數
    // 偵聽器會被連結到該組件的生命周期,並在組件卸載時自動停止。
    // Vue 的響應式系統會緩存副作用函數,並異步地刷新它, 比如同時改變了count與conut4此時watchEffect只是執行一次
    // 初始化運行是在組件 mounted 之前執行的。因此,如果你希望在編寫副作用函數時訪問 DOM(或模板 ref),請在 onMounted 鉤子中進行
    // 並不是返回值, 而是監聽裡面所有的值, 任何有變化都會重新執行, 他應該可以玩出點東西。
    const count4 = ref(1);
    const stop = watchEffect(() => {
      if (count4.value) {
        console.log("作為判斷條件也可以根據count4的變化而重新執行");
      }
      console.log(count.value);
    });
    setTimeout(() => {
      stop(); // 停止監聽
    }, 10000);
    function addCount() {
      count.value++;
      setTimeout(() => {
        count4.value++;
      }, 1000);
    }
    // 觸發setter
    function setCount() {
      count3.value = 2;
    }
    return {
      count,
      count2,
      addCount,
      count3,
      setCount
    };
  }
};
</script>

14. customRef防抖

當然這裡說的'防抖'不是重點, 重點是這種代碼的思維

<template>
  <div>
    <input type="text" v-model="text" />
  </div>
</template>

<script>
import { customRef, onUnmounted } from "vue";
export default {
  setup() {
    let timeout = null; // 並不需要響應式
    const text = useDebouncedRef("hello", (time) => {
      // 畢竟是延時的不用擔心獲取不到這個值
      console.log("延時執行回調", text.value);
      console.log('時間實例', time)
      timeout = time;
    });
    // 好習慣也是成為合格工程師的必要條件
    onUnmounted(()=>{
        clearTimeout(timeout);
    })
    return {
      text
    };
  }
};

// 並不用純粹的js編寫, 可以利用customRef來監控這個值的一舉一動
// 寫法一般, 但是思路又多了一條, 感謝
function useDebouncedRef(value, callback, delay = 200) {
  let timeout;
  // 兩個參數分別是用於追蹤的 track 與用於觸發響應的 trigger
  // 這兩個參數對 值的追蹤 在當前並沒有用,比如watchEffect的出發機制
  // 不調用這兩個值沒問題, 但是如果寫成插件的話還是要調用的, 因為別人沒準在追蹤這個值,

  // 注意:  這個函數不可以有太大的delay, 如果超過500的話就需要考慮在組件銷毀時候的清除定時器, 反而邏輯加深了, 此時我們可以每次把演示器的實例拿到
  return customRef((track,trigger) => {
    return {
      get() {
        track()
        return value;
      },
      set(newValue) {
        clearTimeout(timeout);
        // callback接受的太晚了, 可以在這裡用另一個函數或對象接收
        timeout = setTimeout(() => {
          value = newValue;
          trigger()
          callback(timeout);
        }, delay);
      }
    };
  });
}
</script>

15. 組件與注入

父級

<template>
  <div>
    組件:
    <zj :type="type" @ok="wancheng"></zj>
  </div>
</template>

<script>
import zj from "../components/子組件.vue";
import { ref } from 'vue';
import { provide } from 'vue'

export default {
  components: { 
    zj
  },
  setup() {
    provide('name','向下傳值'); // 基礎值
    provide('name2', ref('向下傳值')); // 監控值
    const type = ref('大多數');

    function wancheng(msg){
      console.log('子組件-->',msg)
      setTimeout(()=>{
        type.value = 'xxxxxxx'
      },2000)
    }
    return {
      type,
      wancheng
    }
  }
};
</script>

子組件

<template>
  <div>props的屬性不用setup去return --- {{type}}</div>
</template>

<script>
import { inject, ref } from 'vue'
// 為了讓 TypeScript 正確的推導類型,我們必須使用 createComponent 來定義組件:
export default {
  props: {
    type: String
  },
  // 1: props也是不可以解構的, 會失去響應式
  // 2: context是上下文, 我們可以獲取到slots emit 等方法
  // 3: props, context 分開也是為了ts更明確的類型推導
  // setup({type}){
  setup(props, context) {
    // 1: props
    console.log("props", props.type);
    console.log("上下文", context);
    context.emit('ok','傳遞完成')

    // 2: 注入
    console.log('inject',inject('name'));
    console.log('inject',inject('xxxx','我是默認值'))
    inject('name1', ref('默認值')) // 接收方也可以這樣
  }
};
</script>

16. 總結

每次看到新技術都會感覺挺好玩的, 一成不變的生活會太無趣了, 在某些方面講vue失去了一些本來的優勢, 但是人家可以兼容vue2.x那就沒的說了, 作為分享會的稿子的話時間差不多一個小時, 最好每個點都現場手敲, 光讓大家看已經寫好的代碼會走神的, 我在學習視頻的時候最不喜歡的就是老師說"這個我就不演示了".這次就這麼多, 希望和你一起進步.

推薦Vue學習資料文章:

《Vue 3.x 如何有驚無險地快速入門「進階篇」》

《「乾貨」微信支付前後端流程整理(Vue+Node)》

《帶你了解 vue-next(Vue 3.0)之 爐火純青「實踐」》

《「乾貨」Vue+高德地圖實現頁面點擊繪製多邊形及多邊形切割拆分》

《「乾貨」Vue+Element前端導入導出Excel》

《「實踐」Deno bytes 模塊全解析》

《細品pdf.js實踐解決含水印、電子簽章問題「Vue篇」》

《基於vue + element的後台管理系統解決方案》

《Vue仿蘑菇街商城項目(vue+koa+mongodb)》

《基於 electron-vue 開發的音樂播放器「實踐」》

《「實踐」Vue項目中標配編輯器插件Vue-Quill-Editor》

《基於 Vue 技術棧的微前端方案實踐》

《消息隊列助你成為高薪 Node.js 工程師》

《Node.js 中的 stream 模塊詳解》

《「乾貨」Deno TCP Echo Server 是怎麼運行的?》

《「乾貨」了不起的 Deno 實戰教程》

《「乾貨」通俗易懂的Deno 入門教程》

《Deno 正式發布,徹底弄明白和 node 的區別》

《「實踐」基於Apify+node+react/vue搭建一個有點意思的爬蟲平台》

《「實踐」深入對比 Vue 3.0 Composition API 和 React Hooks》

《前端網紅框架的插件機制全梳理(axios、koa、redux、vuex)》

《深入Vue 必學高階組件 HOC「進階篇」》

《深入學習Vue的data、computed、watch來實現最精簡響應式系統》

《10個實例小練習,快速入門熟練 Vue3 核心新特性(一)》

《10個實例小練習,快速入門熟練 Vue3 核心新特性(二)》

《教你部署搭建一個Vue-cli4+Webpack移動端框架「實踐」》

《2020前端就業Vue框架篇「實踐」》

《詳解Vue3中 router 帶來了哪些變化?》

《Vue項目部署及性能優化指導篇「實踐」》

《Vue高性能渲染大數據Tree組件「實踐」》

《尤大大細品VuePress搭建技術網站與個人博客「實踐」》

《10個Vue開發技巧「實踐」》

《是什麼導致尤大大選擇放棄Webpack?【vite 原理解析】》

《帶你了解 vue-next(Vue 3.0)之 小試牛刀【實踐】》

《帶你了解 vue-next(Vue 3.0)之 初入茅廬【實踐】》

《實踐Vue 3.0做JSX(TSX)風格的組件開發》

《一篇文章教你並列比較React.js和Vue.js的語法【實踐】》

《手拉手帶你開啟Vue3世界的鬼斧神工【實踐】》

《深入淺出通過vue-cli3構建一個SSR應用程式【實踐】》

《怎樣為你的 Vue.js 單頁應用提速》

《聊聊昨晚尤雨溪現場針對Vue3.0 Beta版本新特性知識點匯總》

《【新消息】Vue 3.0 Beta 版本發布,你還學的動麼?》

《Vue真是太好了 壹萬多字的Vue知識點 超詳細!》

《Vue + Koa從零打造一個H5頁面可視化編輯器——Quark-h5》

《深入淺出Vue3 跟著尤雨溪學 TypeScript 之 Ref 【實踐】》

《手把手教你深入淺出vue-cli3升級vue-cli4的方法》

《Vue 3.0 Beta 和React 開發者分別槓上了》

《手把手教你用vue drag chart 實現一個可以拖動 / 縮放的圖表組件》

《Vue3 嘗鮮》

《總結Vue組件的通信》

《Vue 開源項目 TOP45》

《2020 年,Vue 受歡迎程度是否會超過 React?》

《尤雨溪:Vue 3.0的設計原則》

《使用vue實現HTML頁面生成圖片》

《實現全棧收銀系統(Node+Vue)(上)》

《實現全棧收銀系統(Node+Vue)(下)》

《vue引入原生高德地圖》

《Vue合理配置WebSocket並實現群聊》

《多年vue項目實戰經驗匯總》

《vue之將echart封裝為組件》

《基於 Vue 的兩層吸頂踩坑總結》

《Vue插件總結【前端開發必備】》

《Vue 開發必須知道的 36 個技巧【近1W字】》

《構建大型 Vue.js 項目的10條建議》

《深入理解vue中的slot與slot-scope》

《手把手教你Vue解析pdf(base64)轉圖片【實踐】》

《使用vue+node搭建前端異常監控系統》

《推薦 8 個漂亮的 vue.js 進度條組件》

《基於Vue實現拖拽升級(九宮格拖拽)》

《手摸手,帶你用vue擼後台 系列二(登錄權限篇)》

《手摸手,帶你用vue擼後台 系列三(實戰篇)》

《前端框架用vue還是react?清晰對比兩者差異》

《Vue組件間通信幾種方式,你用哪種?【實踐】》

《淺析 React / Vue 跨端渲染原理與實現》

《10個Vue開發技巧助力成為更好的工程師》

《手把手教你Vue之父子組件間通信實踐講解【props、$ref 、$emit】》

《1W字長文+多圖,帶你了解vue的雙向數據綁定源碼實現》

《深入淺出Vue3 的響應式和以前的區別到底在哪裡?【實踐】》

《乾貨滿滿!如何優雅簡潔地實現時鐘翻牌器(支持JS/Vue/React)》

《基於Vue/VueRouter/Vuex/Axios登錄路由和接口級攔截原理與實現》

《手把手教你D3.js 實現數據可視化極速上手到Vue應用》

《吃透 Vue 項目開發實踐|16個方面深入前端工程化開發技巧【上】》

《吃透 Vue 項目開發實踐|16個方面深入前端工程化開發技巧【中】》

《吃透 Vue 項目開發實踐|16個方面深入前端工程化開發技巧【下】》

《Vue3.0權限管理實現流程【實踐】》

《後台管理系統,前端Vue根據角色動態設置菜單欄和路由》

作者:lulu_up

轉發連結:https://segmentfault.com/a/1190000022719461

關鍵字: