Vue3.0+vue-router-next+vuex4.0+typescript項目搭建

Vue3.0

Vue3.0是2020年4月剛剛發佈了beta版本的全新Vue版本

項目地址:

https://github.com/kaiqiangren/vue-next-ts-preview

一、Vue3.0與Vue2.0的對比:

優點:

  1. 將Vue內部的絕大部分api對外暴露,使Vue具備開發大型項目的能力,例如compile編譯api等
  2. webpack的treeshaking支持度友好
  3. 使用Proxy進行響應式變量定義,性能提高2-3倍
  4. 可在Vue2.0中單獨使用composition-api插件,或者直接用它開發插件
  5. 對typescript支持更加友好
  6. 面向未來:對於尤雨溪最近創新的vite開發服務器(捨棄webpack、底層爲Koa框架的高性能開發服務器),直接使用的Vue3.0語法

缺點:

  1. 只支持IE11及以上
  2. 對於習慣了Vue2.0開發模式的開發者來說,增加了心智負擔,對開發者代碼組織能力有考驗

同時也是能力提升的機會吧,特別喜歡Vue作者的設計初心:讓開發者隨着框架一起成長!

二、Vue3.0正確的打開方式

1、項目搭建

  1. 需要安裝vue-cli4代最新腳手架,可以通過執行如下npm 命令安裝/更新腳手架版本
npm i @vue/cli -g
  1. 然後在創建項目後,執行vue add vue-next向項目添加Vue3.0
vue create [projectName]
cd [projectName]
vue add vue-next
  1. 如下例子爲使用typescript + Vue3.0 開發的項目依賴,也可以直接使用
{
  "name": "vue-next-ts-preview",
  "version": "0.1.0",
  "private": true,
  "scripts": {
    "build": "vue-cli-service build",
    "lint": "vue-cli-service lint",
    "dev": "vue-cli-service serve"
  },
  "dependencies": {
    "core-js": "^3.6.4",
     "normalize.css": "^8.0.1",
     "vue": "^3.0.0-beta.14",
     "vue-router": "^4.0.0-alpha.12",
     "vuex": "^4.0.0-beta.2"
  },
  "devDependencies": {
    "@typescript-eslint/eslint-plugin": "^2.26.0",
    "@typescript-eslint/parser": "^2.26.0",
    "@vue/cli-plugin-babel": "~4.3.0",
    "@vue/cli-plugin-eslint": "~4.3.0",
    "@vue/cli-plugin-router": "~4.3.0",
    "@vue/cli-plugin-typescript": "~4.3.0",
    "@vue/cli-plugin-vuex": "~4.3.0",
    "@vue/cli-service": "~4.3.0",
    "@vue/compiler-sfc": "^3.0.0-beta.1",
    "@vue/eslint-config-typescript": "^5.0.2",
    "eslint": "^6.7.2",
    "eslint-plugin-vue": "^7.0.0-alpha.0",
    "node-sass": "^4.12.0",
    "sass-loader": "^8.0.2",
    "typescript": "~3.8.3",
    "vue-cli-plugin-vue-next": "~0.1.2"
  }
}

2、使用文檔

  1. 項目入口main.ts
import { createApp } from 'vue';
import App from './App.vue'
import router from './router'

const app = createApp(App)
app.use(router)
app.mount('#app')

3、語法相關

  1. 響應式變量聲明
import { ref, reactive } from 'vue'
// 方式一: 可傳入任意類型的值,改變值的時候必須使用其value屬性,例 refData.value = 2
const refData = ref(0)

// 方式二: 只能傳入引用類型的值
const data = reactive({
  tableData: [
    {
      name: '姓名1'
    }
  ]
})

// 使用響應式變量前,必須在Vue文件的setup函數中 執行/return 出去
setup (props, context){
  return {
    refData,
    data
  }
}
  1. computed
import { watch, watchEffect, computed } from 'vue'

// 1、創建只讀的計算屬性
const computedCount = computed(() => count.value + 1)


// 2、創建可讀可寫的計算屬性
const computedCount2 = computed({
      get: () => writeCount.value + 2,
      set: (val) => {
        return writeCount.value =  val + 2
      }
})

// 可以直接修改computed的值,在Vue2.x中無法修改
// computedCount2 = 123 
  1. watch & watchEffect
import { ref, watch, watchEffect } from 'vue'
const count = ref(0)
// watchEffect會自動收集響應式依賴
watchEffect(() => console.log(count.value))

// 監聽指定基礎類型數據
watch(count, (now, prev) => {
      console.log(now, prev, 'count')
})

const data = reactive({
  tableData: [
    {
      name: '姓名1'
    }
  ]
})
// 監聽reactive創建的響應式變量,可以直接監聽對象,必須使用內聯函數
watch(() => data.tableData, (now, prev) => {
   console.log(now, prev, 'tableData')
})
  1. provide & inject
import { reactive, provide , inject} from 'vue'

const data = reactive({
  tableData: [
    {
      name: '姓名1'
    }
  ]
})
// 根級/父級組件
// provide 這裏如果提供的是響應式變量,inject也會觸發響應
provide('provideName', 'provideData')
provide('provideReactive', data.tableData)


// 子級/孫級組件
setup () {
  const provideData = inject('provideName')
  const provideReactive = inject('provideReactive')
  return {
    provideData,
    provideReactive
  }
}
  1. 生命週期
Vue3.0生命週期         說明                                                   對應的Vue2.0生命週期
setup               | 初始化數據階段的生命週期,介於beforeCreate與created之間  相當於beforeCreate、created的合併
onBeforeMount       | 組件掛載前                                          beforeMount
onMounted           | 實例掛載完畢                                         mounted
onBeforeUpdate      | 響應式數據變化前                                      beforeUpdate
onUpdated           | 響應式數據變化完成                                    updated
onBeforeUnmount     | 實例銷燬前                                           beforeDestroy
onUnmounted         | 實例已銷燬                                           destroyed
onErrorCaptured     | 錯誤數據捕捉                                            --
  1. 路由
// 組件內部路由攔截器的使用方式
import { useRouter, useRoute } from "vue-router"

setup() {
  // 組件內路由
  const router = useRouter()
  router.beforeEach((to, from, next) => {
    next()
  })
  // 組件內路由信息
  const route = useRoute()
}

7.vuex

創建Store

import { createStore } from 'vuex'

const store = createStore({
  state: {
    userInfo: {
      name:'renkq'
    }
  },
  mutations: {
    getUserInfo (state, name) {
      state.userInfo.name = name
    }
  },
  actions: {
    asyncGetUserInfo ({ commit }) {
      setTimeout(() => {
        commit("getUserInfo", +new Date() + 'action')
      },2000)
    }
  },
  getters: {
    userInfoGetter (state) {
      return state.userInfo.name
    }
  }
})

export default store

組件內使用store

import {
  useStore,
  // mapState,
  // mapMutations,
  // mapActions,
  // mapGetters
} from 'vuex'

export default {
  name: 'self',
  setup() {
    const store = useStore()
    console.log(store, 'store')
    console.log(store.getters, 'getters')
    const state = store.state
    const getters = store.getters
    // console.log(mapState(store.state),'mapState')
    // console.log(mapMutations(store._mutations),'mapMutations')
    // console.log(mapActions(store._actions),'mapActions')
    // console.log(mapGetters(store.getters),'mapGetters')
    const methods = {
      // 處理commit
      handleMutation: () => {
        store.commit('getUserInfo', +new Date)
      },
      // 處理dispatch
      handleAction: () => {
        store.dispatch('asyncGetUserInfo')
      }
    }
    return {
      state,
      getters,
      ...methods
    }
  }
}
  1. v-model
// 自定義v-model組件時,需要使用update:modelValue事件進行觸發
setup(props, { emit }){
   const handleClick = () => {
      emit('update:modelValue', params)
   }
   return {
      handleClick
  }
}
  1. directive

定義指令

import { ObjectDirective } from 'vue'
// 使用ObjectDirective聲明指令類型即可,因爲源碼內部指定了默認類型說明
export const customDirective: ObjectDirective = {
  beforeMount(el, binding, vnode, prevVnode) {
    console.log(el, binding, vnode, prevVnode)
  },
  mounted() { console.log('mounted') },
  beforeUpdate() { console.log('beforeUpdate') },
  updated() { console.log('updated') },
  beforeUnmount() { console.log('beforeUnmount') },
  unmounted() { console.log('unmounted') }
}


全局註冊指令

const app = createApp(App)
app.use(router)
app.use(store)
app.directive('custom', customDirective)
app.mount('#app')

組件內使用指令

import { customDirective } from '../../directive/directive'
export default {
  setup() {
    return {}
  },
  directives: {
    custom: customDirective
  }
}
  1. nextTick
import { nextTick, onBeforeMount } from 'vue'

{
  setup () {
    
    onBeforeMount(() => {
      nextTick(() => {
        
      })
    })
    
  }
}
  1. 定義組件defineAsyncComponent & defineComponent

同步組件與異步組件的區別:
同步組件:在組件加載時自動加載;
異步組件:在渲染時加載;

// 一、定義同步組件
const syncComponent = defineComponent({
  setup () {
    return () => `我是同步組件`
  }
})


// 二、定義異步組件
// 方式1 
const asyncComponent = defineAsyncComponent({
  loader: () => import("./asyncComponents.vue"),
  loadingComponent: loadingComponent,
  errorComponent: loadingComponent,
  delay: 2000,
  timeout: 3000
});
// 方式2
const asyncComponent = defineAsyncComponent(() => import('./syncComponents.vue'));
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章