ts watch路由 参数变化_Vue + TypeScript 踩坑总结

本文总结了在Vue和TypeScript结合的项目中遇到的问题,包括Vue组件、原型链挂载、全局组件注册、SFC单文件组件的写法、监听器的使用、过滤器、路由监听等方面的问题及解决方案,旨在帮助开发者解决类似问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

前言

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;

// 以下是在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);

使用

写法一:

写法二:

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

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

结构示例

{{ selfKey1 }}

{{ item }}

追加文字

:class="['default-class', selfKey1.length > 10 ? 'one' : 'two']"

/>

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 += ",追加文字!";

}

}

@import "@/assets/styles/demo.scss";

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、父组件用属性传值【前提是父组件引入子组件、注册并调用了】

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 单词)

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 {

// ...

}

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

{{showValue | filterValue}}

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

// 待补充

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 组件:

// 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();

}

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

@Watch('$route')

routeWatch() {

this.loadData();

}

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

基本同上

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

Component.registerHooks([

"beforeRouteEnter", //进入路由之前

"beforeRouteLeave", //离开路由之前

"beforeRouteUpdate"

]);

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

// 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();

}

父子传值 - 子组件修改触发父组件的方法执行

父组件内部:

1、调用子组件、并绑定传值:

准备好一会会被子组件触发的函数:

FuQinZiJiYong(){

console.log('我是父亲内部待被触发的方法')

}

子组件 ZiZuJian 内部在需要触发的地方执行$emit

export default class Menu extends Vue {

// 在需要触发的地方,执行如下代码

this.$emit('chuanDiGuoQu', '')

}

最后还有另一种网友总结很麻烦的写法:参见地址

@Prop 默认参数

第一种:github 找到的 demo 这样。如下代码中hideHeader就是由默认参数的父组件传过来的属性

export default class ComponentName extends Vue {

@Prop({

type: Boolean,

required: false,

default: false // 默认属性的默认值

})

private hideHeader!: boolean | undefined

}

第二种:vue 原生的写法,并写到了@component 构造器中就好了:

如果不传值此函数默认就是 true,传 false 就是 false 了。并且能严格判断只能传 Boolean 类型。挺好。

@Component({

props: {

hideHeader: {

type: Boolean,

required: false,

default: false // 默认属性的默认值

}

}

})

中央总线注册与使用【待解决】

// 待解决

vue + ts 中使用 vue-echarts

安装

npm i -S vue-echarts echarts

main.ts 中引入并注册

// main.ts

// 引用

import ECharts from "vue-echarts";

// 用到的模块要单独引用

import "echarts/lib/chart/line"; // 线图为例,其他图一样

import "echarts/lib/component/title.js"; // 标题

import "echarts/lib/component/legend"; // 图例

import "echarts/lib/component/tooltip"; // 提示框

import "echarts/lib/component/toolbox"; // 工具(如下载功能与按钮)

// 注册

Vue.component("v-chart", ECharts);

vue.config.js 中设置

// vue.config.js

module.exports = {

// For Vue CLI 3+, add vue-echarts and resize-detector into transpileDependencies in vue.config.js like this:

transpileDependencies: ["vue-echarts", "resize-detector"]

};

tsconfig.json 中也要设置

// tsconfig.json

{

"compilerOptions": {

"types": ["webpack-env", "echarts"]

}

}

SFC 应用

vue + ts 中使用 Element-ui

// main.ts

import ElementUI from "element-ui";

Vue.use(ElementUI);

全局 scss 变量

在 assets/styles 下新建_variable.scss 文件,用于存放 scss 变量。

然后再 vue.config.js 中设置全局变量

// vue.config.js

module.exports = {

css: {

loaderOptions: {

sass: {

prependData: `

@import "@/assets/styles/_variable.scss";

`

}

}

}

};

alias 别名设置

同时解决问题alias 配置的路径别名,在 vscode 中报错模块查找失败和问题vue-cli 配置了 resolve alias 来声明的路径别名,在引用了 ts 后,vscode 会报错不能识别、模块查找失败。其中,vscode 报错在 win 环境还需要一个插件安装,解决方案见下边

vue.config.js 配置

// vue.config.js

module.exports = {

chainWebpack: config => {

// 别名配置

config.resolve.alias

.set("comp", resolve("src/components"))

.set("css", resolve("src/assets/styles"));

// ...同上,路径核对好就行

}

};

jsconfig.json 配置。注意这里的名字要和上边 set 后边的名字保持一致

// jsconfig.json

{

"compilerOptions": {

"paths": {

"@/*": [

"src/*" // 这个本来就有

],

// 后边追加

"comp/*": [

"src/components/*"

],

"css/*": [

"src/assets/styles/*"

],

// ... 同上,路径核对好就行

},

}

};

SCF 使用设定的别名

// main.ts

import MyError from "view/error/Error.vue";

/* SCF单页中scss路径引用 */

@import "css/_variable.scss";

请求接口的代理设置

vue.config.js 配置

// vue.config.js

module.exports = {

devServer: {

proxy: {

"/api": {

target: "http://11.11.11.111/", // 示例ip地址,也可以填域名,需要的是后端接口地址的相同部分

changeOrigin: true,

pathRewrite: {

"^/api": ""

}

}

}

}

};

axios 请求地址时的写法:

注意/api一定要有,且在路径的最前边,代替相同的路径。

axios

.get("/api/wo/de/di/zhi") // 前边的'/api'一定要有,它代表的就是vue.config.js中proxy.target的路径

.then(() => {

// 接口成功...

});

本地服务域名修改

vue.config.js 配置

// vue.config.js

module.exports = {

devServer: {

disableHostCheck: true, // 用域名代替localhost,禁用主机检查

host: "www.haha.com"

// 另外端口也可以在这里改,只不过我写到了package.json总,见下边

}

};

package.json dev 命令的配置

{

"scripts": {

"dev": "npm run serve",

"serve": "vue-cli-service serve --port 80 --open", # 端口设置为80,--open运行完毕后自动打开地址

}

}

本地 host 配置

127.0.0.1 www.haha.com # 这里注意和vue.config.js中的host的值对应

此时,npm run dev成功后,浏览器跑项目输入地址http://www.haha.com即可

vue + ts 在 vscode 中的问题

vue-cli 配置了 resolve alias 来声明的路径别名,在引用了 ts 后,vscode 会报错不能识别、模块查找失败:

1、扩展商店安装插件 - Path Intellisense

2、配置代码(vscode setting.json 中设置)

"path-intellisense.mappings": {

"@": "\${workspaceRoot}/src"

}

3、在 package.json 统计目录下创建 jsconfig.json 文件,并填入下边代码

// jsconfig.json

{

"compilerOptions": {

"paths": {

"@/*": ["src/*"]

}

}

}

2019/12/09 ...持续更新中...

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值