vue 和 TypeScript 结合的状况下,不少写法和咱们平时的写法都不太同样,这里总结我项目开发过程当中遇到的问题和问题的解决方案 有些问题可能还没解决,欢迎各位大佬给与提点。 另外,使用本文前能够先看vue 官方文档关于 typescript 的使用讲解javascript
这里只写我后来为了解决问题改动的地方css
解决方案: 一、将 shims-vue.d.ts 文件一分为二。 二、在 shims-vue.d.ts 文件同级目录下新建 vue.d.ts(名字不必定叫 vue,如 xxx.d.ts 也能够),而后此文件包含代码以下html
// vue.d.ts
declare module '*.vue' {
import Vue from 'vue'
export default Vue
}复制代码
三、而原来的 shims-vue.d.ts 代码修改、新增以下:vue
// 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 配置java
// 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;复制代码
二、shims-vue.d.ts 配置webpack
// shims-vue.d.ts 新增以下
declare module 'vue/types/vue' {
interface Vue {
// ...
// 如下是在main.ts中挂载到Vue.prototype上的变量
$api: any;
$mock: any;
$configs: any;
}
}复制代码
注册ios
// main.ts
import Page from "@/components/page.vue";
import AllComponent from "@/common/AllComponent.vue";
Vue.component("Page", Page);
Vue.component("all-component", AllComponent);复制代码
使用git
写法一:
<Page />
写法二:
<all-component />复制代码
一個简陋的 demo,展现 ts 下的 vue 文件中,对于相关功能的使用,重点关注<Script>
里的代码github
<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>复制代码
// 计算属性
get computedKey() {
return this.selfKey1.length
}复制代码
import { Component, Vue, Prop, Watch } from 'vue-property-decorator'
@Watch('boxHeight')
getboxHeight(val) { // get+上边括号里的名字
// xxx
}复制代码
子组件监遵从父组件传过来的值 一、父组件用属性传值【前提是父组件引入子组件、注册并调用了】web
<ziZuJian :oneKey="oneKeyObj" />复制代码
二、子组件要使用的工具引入工做
import { Component, Vue, Prop, Watch } from "vue-property-decorator";复制代码
三、子组件 Prop 接受
export default class ZiZuJian extends Vue {
@Prop() private oneKey: object
}复制代码
四、子组件 Watch 监听
@Watch('oneKey')
getoneKey(newVal,oldVal) {
// 监听成功后要作
log(newVal)
this.myfunction(newVal)
}复制代码
五、父组件(内部)改动值,会被子组件监听
export default class FuZuJian extends Vue {
oneKeyObj = {}
...
mounted(){
$.ajax().then(()=>{
// 适时状况下改动props传递的值,就会被子组件监听到改变
oneKeyObj = {
name : '测试'
}
oneKeyObj.age = 18
})
}
}复制代码
主要思路是计算属性获取 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+上边括号里的名字也能够(虽然不太肯定为何,只是代码这么写成功了)
// 下同
// ...
}复制代码
定义:(在@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>复制代码
// 待补充复制代码
一、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;
}
}复制代码
二、main.ts 的设置
// main.ts
import { Component } from "vue-class-component";
Vue.config.productionTip = false;
Component.registerHooks([
"beforeRouteEnter", //进入路由以前
"beforeRouteLeave", //离开路由以前
"beforeRouteUpdate"
]);复制代码
三、须要监听路由钩子的 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();
}复制代码
基本同上 一、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;
}
}复制代码
二、main.ts 的设置
// main.ts
import { Component } from "vue-class-component";
Component.registerHooks([
"beforeRouteEnter", //进入路由以前
"beforeRouteLeave", //离开路由以前
"beforeRouteUpdate"
]);复制代码
三、须要监听路由钩子的 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>复制代码
父组件内部: 一、调用子组件、并绑定传值:
<ZiZuJian @chuanDiGuoQu="FuQinZiJiYong"></ZiZuJian>复制代码
准备好一会会被子组件触发的函数:
FuQinZiJiYong(){
console.log('我是父亲内部待被触发的方法')
}复制代码
子组件 ZiZuJian 内部在须要触发的地方执行$emit
export default class Menu extends Vue {
// 在须要触发的地方,执行以下代码
this.$emit('chuanDiGuoQu', '')
}复制代码
最后还有另外一种网友总结很麻烦的写法:参见地址
第一种: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 // 默认属性的默认值
}
}
})复制代码
// 待解决复制代码
安装
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 应用
<v-chart :options="echartsOptions" id="myCharts" ref="myCharts" />复制代码
// main.ts
import ElementUI from "element-ui";
Vue.use(ElementUI);复制代码
在 assets/styles 下新建_variable.scss 文件,用于存放 scss 变量。 而后再 vue.config.js 中设置全局变量
// vue.config.js
module.exports = {
css: {
loaderOptions: {
sass: {
prependData: ` @import "@/assets/styles/_variable.scss"; `
}
}
}
};复制代码
同时解决问题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
便可
一、扩展商店安装插件 - Path Intellisense
二、配置代码(vscode setting.json 中设置)
"path-intellisense.mappings": {
"@": "\${workspaceRoot}/src"
}复制代码
三、在 package.json 统计目录下建立 jsconfig.json 文件,并填入下边代码
// jsconfig.json
{
"compilerOptions": {
"paths": {
"@/*": ["src/*"]
}
}
}复制代码
持续更新中...