Vue3+Vite2+typescript的基础用法(2)

1,887 阅读3分钟

前言

发布完Vue3+Vite2+typescript的基础用法(1) 后我自己也仔细的看了一边,发现写的内容跟我一开始想的有很大的区别。比如一开始我想的是先挨个展示vue2vue3的代码区别,比如vue2 datavue3 setup 中的data,但是我只写了vue3的。而且我也只用了vite脚手架去创建了一个项目,在文章的内容中也没有再次提到vite。既然已经跑偏了,那就先按跑偏了的来吧😂

主要内容

  1. 搭建vue3+vite2+ts的项目
  2. ⭐⭐vue3 setup语法糖与composition api各种写法
  3. ⭐⭐vue3生命周期展示
  4. ⭐⭐集成 vuex@4和axios
  5. 集成vue-router@4
  6. ts介绍和配置
  7. vite介绍与配置 ...(大家想到有什么想要了解的可以留言,我会在后续文章中去更新它)

上篇已经把如何搭建项目简单的写了一下,也介绍了propsrefreactivetoReftoRefs。这次要给大家展示的是computedwatchwatchEffectvue的生命周期和项目集成vuexvue-router

setup 语法糖与composition api各种写法

computed

vue2 computed的使用方法

<script lang="ts">
import { defineComponent } from "vue";
export default defineComponent({
  data() {
    return {
      count: 0
    }
  },
  computed: {
    plusOne() {
      return this.count++
    }
  },
})

目前我知道computedvue3中的用法有2种。在setup中可以把computed写在reactive上,还可以通过set get方法对computed赋值,总的来说比vue2更加的灵活多变了

<template>
  <div>
    <h1>count: {{ count }}</h1>
    <button @click="handleAdd">Add count</button>
    <h1>count: {{ count1.count }}</h1>
    <h1>double: {{ count1.double }}</h1>
    <button @click="count1.count++">Add count1</button>
    <h1>plusOne -> {{ plusOne }}</h1>
    <h1>count2 {{ count2 }}</h1>
    <h1>plusOne2 {{ plusOne2 }}</h1>
    <button @click="count2++">count2++</button
    ><button @click="plusOne2 = 0">count2 init</button>
  </div>
</template>
<script setup lang="ts">
import { computed, reactive, ref } from "vue";
type Count = {
  count: number;
  double: number;
};
const count = ref(0);
const count1: Count = reactive({
  count: 0,
  double: computed(() => count1.count * 2),
});
const plusOne = computed(() => count.value + count1.count);
const count2 = ref(0);
const plusOne2 = computed({
  get: () => count2.value + 1,
  set: (val) => {
    count2.value = val;
  },
});
const handleAdd = () => {
  count.value++;
};
</script>

watch

watchvue3vue2中区别不是很大,用法也是非常的像

<template>
  <div>
    <h1>count -> {{ count }}</h1>
    <button @click="count++">add one</button>
    <h1>count1.count -> {{ count1.count.count }}</h1>
    <button @click="count1.count.count++">add one</button>
  </div>
</template>
<script setup lang="ts">
import { reactive, ref, watch } from "vue";
const count = ref(0);
watch(
  () => count.value,
  (count, prevCount) => {
    console.log("count", count);
    console.log("prevCount", prevCount);
  }
);
const count1 = reactive({ count: { count: 0 } });
// 跟vue2一样,层次比较深的话没办法直接被watch到,需要加上deep:true
watch(() => count1.count, (count, prevCount) => {
  console.log("count", count);
  console.log("prevCount", prevCount);
}, {
  deep: true,
  immediate: false
})
</script>

watchEffect

watchEffectvue2vue3中区别也不大

<template>
  <h1>{{ msg }}</h1>
  <h1>{{num}}</h1>
</template>

<script setup lang="ts">
/**
* 1.不需要手动传入依赖
* 2.不是lazy初始化执行分析依赖
* 3.无法获取原始值
* 4.一些异步操作放里面更加的合适
* 5.wacth第三个参数处理副作用的第一个参数
*/
import { ref, defineProps, watchEffect, onMounted } from "vue";
defineProps({
  msg: String
});
const num = ref(0);
onMounted(() => {
  console.log("onMounted")
});
const stop = watchEffect((onInvalidate) => {
  console.log("watchEffed之前调用", num.value);
  onInvalidate(() => {
      /** 清楚副作用 */
  })
}, {
  flush:"sync",
  onTrigger(e) {
      //debugger;
  }
})
const interval = setInterval(() => {
  num.value++;
  if(num.value === 10) {
    //停用监听
    stop()
    clearInterval(interval)
  }
}, 1000);

</script>

vue3生命周期

vue3的生命周期和vue2的生命周期基本一样,就名字改了一下

<template>
  <h1>{{ msg }}</h1>
</template>

<script setup lang="ts">
// 开发 Hooks
/*   2.x与 3.x对比
 beforeCreate -> use setup()
 created -> use setup()
 beforeMount -> onBeforeMount
 mounted -> onMounted
 beforeUpdate -> onBeforeUpdate
 updated -> onUpdated
 beforeDestroy -> onBeforeUnmount
 destroyed -> onUnmounted
 errorCaptured -> onErrorCaptured
*/
import {
  onBeforeMount,
  onMounted,
  onBeforeUpdate,
  onUpdated,
  onBeforeUnmount,
  onUnmounted,
  onErrorCaptured,
  defineProps
} from "vue";

defineProps({
  msg: String
});
onBeforeMount(() => {
  console.log("onBeforeMount");
});
onMounted(() => {
  console.log("onMounted!");
});
onBeforeUpdate(() => {
  console.log("onBeforeUpdate!");
});
onUpdated(() => {
  console.log("onUpdated!");
});
onBeforeUnmount(() => {
  console.log("onBeforeUnmount!");
});
onUnmounted(() => {
  console.log("onUnmounted!");
});
onErrorCaptured(() => {
  console.log("onErrorCaptured!");
});
</script>

集成 vuex@4axios

vuexaxios应该不用介绍它们是什么吧😂

下面还是给大家分享它们在composition api中的使用方法

vuex@4

vue3vuex的版本已经是V4了,首先我们按照官方文档来安装依赖

npm install vuex@next --save

首先创建store/index.ts,这里把state,mutations,actions,getters, modules的使用方法全部演示一边。

首先是src/store/index.ts

import { createStore } from 'vuex'
import { Counter, Person } from './module'
const store = createStore({
  modules: {
    Counter,
    Person
  }
})
export { store  }

然后在src/store/创建StateType.d.ts用来声明变量类型

import { Commit } from 'vuex'

interface TPerson {
  name: string,
  age: number,
}

interface TCount {
  count: number,
  double: number,
}

interface ActionType {
  state: TPerson,
  commit: Commit,
  rootState: TPerson
}

export { TPerson, TCount, ActionType }

然后在src/store/下创建module/index.tsCounter.tsPerson.ts

module/index.ts

import { Counter } from './Counter'
import { Person } from './Person'

export {
  Counter,
  Person,
}

module/Counter.ts

import { TCount, ActionType } from "../StateType"
const Counter = {
  namespaced: true,
  state: () => ({
    count: 0,
    double: 0
  }),
  mutations: {
    plusOne(state: TCount) {
      state.count++
      state.double = state.count * 2
    }
  },
  actions: {
    delayPlus({ commit }: ActionType) {
      // commit('plusOne')
      setTimeout(() => {
        commit('plusOne')
      }, 1000);
    }
  },
  getters: {
    composeNum(state: TCount) {
      return state.count + state.double
    }
  }
}
export { Counter }

module/Person.ts

import { TPerson, ActionType } from '../StateType'
const Person = {
  namespaced: true,
  state: () => ({
    name: '',
    age: 0
  }),
  mutations: {
    setInfo(state: TPerson, info: TPerson) {
      state.name = info.name
      state.age = info.age
    }
  },
  actions: {
    getPersonInfo({ state, commit, rootState }: ActionType) {
      // if((state))
      console.log(state);
      console.log(rootState);
      setTimeout(() => {
        const info: TPerson = {
          name: 'XiaoMing',
          age: 22,
        }
        commit('setInfo', info)
      }, 1000);
    }
  },
  getters: {
    sayHi(state: TPerson) {
      return `my name is ${state.name} I'm ${state.age} years old`
    }
  }
}
export { Person }

最后在src/mian.ts下把store加进去就好了

src/main.ts

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

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

这样整个store的配置就算完成了。接下来给大家展示一下怎么使用

⭐需要注意的是,在setup()中无法使用this.$store官网文档上是

import { useStore } from 'vuex'
export default {
  setup () {
    const store = useStore()
  }
}

而我的使用方法如下

<template>
  <div>
    <h1>count: {{ count }}</h1>
    <h1>double: {{ double }}</h1>
    <h1>composeNum: {{ composeNum }}</h1>
    <button @click="handlePlusOne">plusOne</button>
    <button @click="handlePlusDelayOne">plusOne</button>
  </div>
</template>
<script setup lang="ts">
import { computed, toRefs } from "vue";
import { store } from "../store";

console.log(store);
const composeNum = computed(() => store.getters["Counter/composeNum"]);
const { count, double } = toRefs(store.state.Counter);
const handlePlusOne = () => {
  console.log(store.getters["Counter/composeNum"]);
  store.commit("Counter/plusOne");
};
const handlePlusDelayOne = () => {
  store.dispatch("Counter/delayPlus");
};
</script>

本来还想把mapState, mapGetters, mapActions, mapMutations这几个方法挨个演示一遍的,但是一直没弄出来,后续有实现的话我会在仓库中把这块内容给加上的。到这vuex的演示就结束了。接下来我们进入vue-router

axios集成

本来这里是想写vue-router@4的,但是发现内容实在太多了,放这里的话篇幅又太长,而axios的话就简单配置一下,这样下次文章写vue-router和介绍ts就刚好了

接下来我们来说一下axios的安装和配置,axiosvue的版本没有关系,就装最新的就可以了

npm i axios -S

因为Axios属于工具,所以我放到了src/utils/axios.ts

import Axios from 'axios'

const baseURL = 'https://api.github.com'

const axios = Axios.create({
  baseURL,
  timeout: 20000 // 请求超时 20s
})
// 前置拦截器(发起请求之前的拦截)
axios.interceptors.request.use(
  (response) => {
    /**
     * 根据你的项目实际情况来对 config 做处理
     * 这里对 config 不做任何处理,直接返回
     */
    return response
  },
  (error) => {
    return Promise.reject(error)
  }
)
// 后置拦截器(获取到响应时的拦截)
axios.interceptors.response.use(
  (response) => {
    /**
     * 根据你的项目实际情况来对 response 和 error 做处理
     * 这里对 response 和 error 不做任何处理,直接返回
     */
    return response
  },
  (error) => {
    if (error.response && error.response.data) {
      const code = error.response.status
      const msg = error.response.data.message
      console.error(`Code: ${code}, Message: ${msg}`)
      console.error(`[Axios Error]`, error.response)
    } else {
      console.error(`${error}`)
    }
    return Promise.reject(error)
  }
)
export default axios

在需要使用Axios文件里,引入Axios配置文件,代码如下:

<template>
  <div>axios</div>
</template>

<script setup lang="ts">
import axios from "../utils/axios";
axios
  .get("/users/cxyxxx0924")
  .then((res) => {
    console.log("res: ", res);
  })
  .catch((err) => {
    console.log("err: ", err);
  });
</script>

<style scoped>
</style>

总结

种一棵树最好是十年前其次是现在

虽然vue3vite发布已经是很长的一段时间了,但是很多大框架还是没有适配上vue3vite。所以现在学起来,等vue3的生态跟vue2完全重合的时候,那我们就可以在公司的项目上or自己的项目上大展手脚。学习不怕晚,就怕你轻易放弃

下篇文章主要会写一下vite, ts的配置, vue-router@4的使用。希望各位靓仔,靓女们多多关注,多多点赞。有问题可以留言,我会第一时间回复你们的

项目地址&友情链接

  1. Vue3+Vite2+typescript的基础用法(1)
  2. 项目源代码:github
  3. 项目源代码:gitee

学习资料:

  1. 从 0 开始手把手带你搭建一套规范的 Vue3.x 项目工程环境
  2. 【阿崔cxr】vue3 的 script setup 语法糖定稿啦 快来看看香不香!!!