欢迎您访问 最编程 本站为您分享编程语言代码,编程技术文章!
您现在的位置是: 首页

Vue和TypeScript的使用经验与常见问题汇总

最编程 2024-01-12 09:45:21
...

Vue+TS 踩坑记录与方案总结

点击跳转-原文地址

  • 前言
  • 整个 vue 项目的目录结构
    • main.ts 中,提示`import App from './App.vue'`处,找不到 App.vue 这个模块
    • main.ts 中,往 Vue 的原型 prototype 上挂载全局变量
  • 全局组件注册
  • SFC 单 vue 文件组件的基本写法和结构
  • computed 计算属性的写法
  • watch 监听器的使用
    • 同一个 vue 页面中使用
    • 父子两个 vue 页面传值后使用 watch 监听
  • Watch 监听 store 中的数据改变
  • vue+ts 中,使用 filter 过滤器
  • 自定义指令 过滤器【待补充】
  • watch 监听 router 的变化
  • main.ts 中注册路由导航守卫并在组件中使用路由钩子函数
  • 父子传值 - 子组件修改触发父组件的方法执行
  • @Prop 默认参数
  • *总线注册与使用【待解决】
  • vue + ts 中使用 vue-echarts
  • vue + ts 中使用 Element-ui
  • 全局 scss 变量
  • alias 别名设置
  • 请求接口的代理设置
  • 本地服务域名修改
  • vue + ts 在 vscode 中的问题
    • vue-cli 配置了 resolve alias 来声明的路径别名,在引用了 ts 后,vscode 会报错不能识别、模块查找失败:

前言

vue 和 TypeScript 结合的情况下,很多写法和我们平时的写法都不太一样,这里总结我项目开发过程中遇到的问题和问题的解决方案
有些问题可能还没解决,欢迎各位大佬给与提点。
另外,使用本文前可以先看vue 官方文档关于 typescript 的使用讲解

整个 vue 项目的目录结构

  • 大体用 vue-cli 创建的项目,结构基本不变。

这里只写我后来为了解决问题改动的地方

main.ts 中,提示import App from './App.vue'处,找不到 App.vue 这个模块

解决方案: 1、将 shims-vue.d.ts 文件一分为二。
2、在 shims-vue.d.ts 文件同级目录下新建 vue.d.ts(名字不一定叫 vue,如 xxx.d.ts 也可以),然后此文件包含代码如下

// vue.d.ts
declare module '*.vue' {
  import Vue from 'vue'
  export default Vue
}

3、而原来的 shims-vue.d.ts 代码修改、新增如下:

// shims-vue.d.ts
import Vue from 'vue'
import VueRouter, { Route } from 'vue-router'
import { Store } from 'vuex'

declare module 'vue/types/vue' {
interface Vue {
$router: VueRouter;
$route: Route;
$store: Store<any>;
// 以下是在main.ts中挂载到Vue.prototype上的变量
$api: any;
$mock: any;
$configs: any;
}
}

main.ts 中,往 Vue 的原型 prototype 上挂载全局变量

1、main.ts 配置

// main.ts
import api from "./api/request";
import mock from "./api/mock";
import configs from "./utils/config";

Vue.prototype.\(api = api; Vue.prototype.\)mock = mock;
Vue.prototype.$configs = configs;

2、shims-vue.d.ts 配置

// shims-vue.d.ts 新增如下
declare module 'vue/types/vue' {
  interface Vue {
    // ...
    // 以下是在main.ts中挂载到Vue.prototype上的变量
    $api: any;
    $mock: any;
    $configs: any;
  }
}

全局组件注册

注册

// main.ts
import Page from "@/components/page.vue";
import AllComponent from "@/common/AllComponent.vue";
Vue.component("Page", Page);
Vue.component("all-component", AllComponent);

使用

写法一:
<Page />
写法二:
<all-component />

SFC 单 vue 文件组件的基本写法和结构

一個简陋的 demo,展示 ts 下的 vue 文件中,对于相关功能的使用,重点关注<Script>里的代码

<template>
  <!-- 结构示例,指令基础用法同vue -->
  <div class="minos-system-setting" v-if="hideHeader">
    <h3>结构示例</h3>
    <span>{{ selfKey1 }}</span>
    <ul>
      <li :key="item" v-for="item in fatherKey">{{ item }}</li>
    </ul>
    <button @click="addText">追加文字</button>
    <AnotherVue
      :class="['default-class', selfKey1.length > 10 ? 'one' : 'two']"
    />
  </div>
</template>

<script lang="ts">
import { Component, Vue, Prop, Watch } from "vue-property-decorator";
import { Route } from "vue-router";
import AnotherVue from "@/components/AnotherVue.vue";
@Component({
// 组件注册
components: {
AnotherVue
// 'another-vue': AnotherVue
},
// 过滤器
filters: {
filterFn1() {}
},
// 属性传递
props: {
hideHeader: {
type: Boolean,
required: false,
default: false // 默认属性的默认值
}
}
})
export default class ComponentName extends Vue {
@Prop({
type: Boolean,
required: false,
default: false // 默认属性的默认值
})
private hideHeader!: boolean | undefined;
@Prop() private fatherKey: string[]; // 其他没有默认值的传值
selfKey1: string = "自己的一个变量";
// 生命周期
created() {}
mounted() {}
// 计算属性
get computedKey() {
return this.selfKey1.length;
}
// 监听器
@Watch("computedKey")
getcomputedKey(newVal) {
console.log(newVal);
}
// 导航守卫函数
private beforeRouteEnter(to: Route, from: Route, next: () => void): void {
console.log("beforeRouteEnter", to, from, next);
next();
}
// 方法
addText() {
this.selfKey1 += ",追加文字!";
}
}
</script>
<style lang="scss" scoped>
@import "@/assets/styles/demo.scss";
</style>

computed 计算属性的写法

// 计算属性
get computedKey() {
  return this.selfKey1.length
}

watch 监听器的使用

同一个 vue 页面中使用

import { Component, Vue, Prop, Watch } from 'vue-property-decorator'

@Watch('boxHeight')
getboxHeight(val) { // get+上边括号里的名字
// xxx
}

父子两个 vue 页面传值后使用 watch 监听

子组件监听从父组件传过来的值 1、父组件用属性传值【前提是父组件引入子组件、注册并调用了】

<ziZuJian :oneKey="oneKeyObj" />

2、子组件要使用的工具引入工作

import { Component, Vue, Prop, Watch } from "vue-property-decorator";

3、子组件 Prop 接受

export default class ZiZuJian extends Vue {
  @Prop() private oneKey: object
}

4、子组件 Watch 监听

@Watch('oneKey')
getoneKey(newVal,oldVal) {
  // 监听成功后要做
  log(newVal)
  this.myfunction(newVal)
}

5、父组件(内部)改动值,会被子组件监听

export default class FuZuJian extends Vue {
  oneKeyObj = {}
  ...
  mounted(){
    $.ajax().then(()=>{
      // 适时情况下改动props传递的值,就会被子组件监听到改变
      oneKeyObj = {
        name : '测试'
      }
      oneKeyObj.age = 18
    })
  }
}

Watch 监听 store 中的数据改变

主要思路是计算属性获取 state 里的数据,watch 再监听计算属性

import { Component, Vue, Prop, Watch } from 'vue-property-decorator' // 引入Watch
get stateSomeKey() { // 计算属性
  // 监听state下的stateSomeKey对象中的keyName属性,return返回该值
  return this['$store'].state.stateSomeKey.keyName
}
@Watch('stateSomeKey') // 与上边计算属性同名
getstateSomeKey(val) { // get+上边括号里的名字
  // 监听到变化后,执行对应的内容
  this.myFunction()
  ...
}

其中,第七行,监听器那里也可以這麽写

@Watch('stateSomeKey') // 与上边计算属性同名
watchMenuState(val) { // 这里可以这么写:或用watch+上边括号里的名字也可以(虽然不太确定为什么,只是代码这么写成功了)
  // 下同
  // ...
}

vue+ts 中,使用 filter 过滤器

定义:(在@Component 里边,写 filters,注意 s 单词)

<script lang="ts">
  import { Component, Vue, Prop } from "vue-property-decorator";
  @Component({
    filters: {
      filterValue(value) {
        return Number(value).toLocaleString();
      }
      // otherFilterFn(value) { 其他filter示例
      //   return ...
      // }
    },
    components: {}
  })
  export default class Container extends Vue {
    // ...
  }
</script>

使用:同之前,正常使用:

<span v-if="showSpan">{{showValue | filterValue}}</span>

自定义指令 过滤器【待补充】

// 待补充

watch 监听 router 的变化

1、shims-vue.d.ts 的设置

// shims-vue.d.ts
import Vue from 'vue'
import VueRouter, {Route} from 'vue-router';

declare module 'vue/types/vue' {
interface Vue {
$router: VueRouter; // 这表示this下有这个东西
$route: Route;
}
}

2、main.ts 的设置

// main.ts
import { Component } from "vue-class-component";
Vue.config.productionTip = false;
Component.registerHooks([
  "beforeRouteEnter", //进入路由之前
  "beforeRouteLeave", //离开路由之前
  "beforeRouteUpdate"
]);

3、需要监听路由钩子的 SCF 组件:

<script lang="ts">
  // xxx.vue 的script标签内
  import { Component, Vue, Prop, Watch } from "vue-property-decorator";
  import { Route, RawLocation } from 'vue-router';
  // # 下边两段,看你需要什么了:

// 1/监听路由变化
@Watch('$route',{ immediate: true })
private changeRouter(route: Route){
console.log(route)
}

// 2/定义路由钩子函数
private beforeRouteEnter(to: Route, from: Route, next: () => void): void {
console.log('beforeRouteEnter', to, from, next)
next(); // 没有next将不会进入路由内部,跟vue文档用法一致
}
private beforeRouteUpdate(to: Route, from: Route, next: () => void): void {
console.log('beforeRouteUpdate'); // 暂时不生效,版本问题
next();
}
private beforeRouteLeave(to: Route, from: Route, next: () => void): void {
console.log('beforeRouteLeave');
next();
}
</script>

监听路由的第二种写法 (如果只是想更新视图的话可以考虑监听路由)

@Watch('$route')
routeWatch() {
	this.loadData();
}

main.ts 中注册路由导航守卫并在组件中使用路由钩子函数

基本同上
1、shims-vue.d.ts 的设置

// shims-vue.d.ts
import Vue from 
						

上一篇: Vue实例对象中常见$开头属性与方法概览

下一篇: Vue中的全局变量和方法如何使用?

推荐阅读