Vue2 + Ts 类式组件

942 阅读4分钟

项目搭建

  • 安装 Vue-cli 3.0 版本
  • 可使用默认模板建立Vue项目或使用自己选择的模板进行创建【vue2 + ts 或 vue3 + ts】

vue create vuePorject

1642236582247.png

1642236622086.png

目录结构

  • Vue2 + ts 的项目中要安装 vue property descorator 修饰器插件
  • Vue3 + ts 项目中则是安装了vue-class-componets 修饰器组件

参考博客:www.cnblogs.com/zxuedong/p/…

Vue 2 + ts

1642236994084.png

Vue3 + ts

1642236962338.png

Vue 3

1642236889560.png

Vue 2 + ts 和 Vue 2 语法使用上的区别

参考博客:www.jianshu.com/p/d8ed3aa76…

Vue 2 + ts 和 Vue 2 语法使用上的区别

参考博客:www.jianshu.com/p/d8ed3aa76…

Vue 基本语法

script 区别

<script></script>  // vue 2 
<script lang="ts"></script> // vue2 + ts

vue2 + ts 要在组件中引入 修饰器插件,从插件中进行获取修饰器

import { Component, Prop, Vue } from 'vue-property-decorator';
@Component (完全继承于vue-class-component)
@Emit
@Inject
@Provice
@Prop
@Watch
@Model
Mixins (在vue-class-component中定义);

组件命名

export default {
    name:'about'      // vue 2 
    
}  
​
@Component({
    name:'about'   // vue2 + ts 
})
要使用 Component 修饰器,该修饰器是独立的无需依赖vue

组件命名

export default {
    name:'about'      // vue 2 
    
}  
​
@Component({
    name:'about'   // vue2 + ts 
})
要使用 Component 修饰器,该修饰器是独立的无需依赖vue

组件对外暴露方法不同

exprot default {    xxxxx  } // vue 2 
export default class HelloWorld(组件名称) extends Vue { xxxx }  // vue 2 + ts 

Component注册不同

import about from './about'
export default {
    name:'home',
    components:{
        about
    }
}
//=============== vue 2 + ts ============
import about from './about.vue' // .vue 不可省略
import { Component, Prop, Vue } from 'vue-property-decorator';
@Component({
    name:'home',
    components:{
        about
    }
})
export default class home extends Vue {
    xxxx
}

data 中的数据不同

// vue 2 
export default {
    data(){
        return {
            a:10
        }
    }
}
​
// vue 2 + ts 
import { Component, Prop, Vue } from 'vue-property-decorator';
export default class Home extends Vue {
    a:numner = 10
}

props 不同

export default {
    props:['age']
    // props:{type:String,default:() => ('xxxx')
    // props:{type:[String,Number],default:() => ('xxxx')
}
import { Component, Prop, Vue } from 'vue-property-decorator';
// 这里 !和可选参数?是相反的, !告诉TypeScript我这里一定有值.
export default class about extends Vue {
    @Prop(Number) age!:number
    @Prop([String,Number]) age2!:string|number
    @Prop({type:[String,Number],default:() => (2000)}) age3!:number | string
}

watc 不同

export default {
    data(){
        return {
            age:12,
            num:0,
        }
    }
    
      watch:{
            age(newData,oldData){
              console.log(newData,oldData)
            },
            num:{
              immediate:true,
              deep:true,
              handler(newData,oldData){
                console.log(newData,oldData)
              }
            }
  },
}
​
// 监视的是@Watch()传递的参数,跟后者的方法名无关
import { Component, Prop, VueWatch} from 'vue-property-decorator';
   @Watch('age') handlerAage(newData:number,oldData:number) {
        console.log(newData + oldData)
    }
   @Watch('age2',{immediate:true,deep:true}) handlerAge2(newData:number,oldData:number) {
        console.log(newData,oldData)
    }

Computed 不同

export default {
    computed:{
        userName(){
            return this.a + this.b
        }
    }
}
​
// 使用去内置的 get 计算数据名(){}方法 或 set 计算属性名(){} 方法实现
export default class about extends Vue {
    num1:number = 10
    num2:number = 20
    
    get result():number{
        return this.num1 + this.num2
    }
    get result2():number{
        return this.num2 + this.num1
    }
}

$emit()【自定义事件】

// 子组件传递
export default {
    methods:{
        hanlder(){
            this.$emit('myChange',this.a,this.b)
        }
    }
}
// 父组件接收
<About @myChange="handler"><About>
​
    
// 子组件传递
    <button @click="changeAge(10,'xxxx')">传递事件</button>
    <button @click="changeName('xxxxxx')">事件传递二</button>
import { Component, Prop, VueWatchEmit} from 'vue-property-decorator';
export default class about extends Vue {
     // 会将其函数的返回值作为参数传出去,return 可以省略不写
    @Emit('change-age') changeAge(a:number,b:string){}
    // 不写时间名称时,会将其后面的驼峰名称转为 change-name 作为时间名称供父组件使用
    @Emit() changeName(name:string){}
}
​
// 父组件接受
<About @change-age="handler" @change-name="handler2"><About>

emit 和 on 【全局事件总线】

// 创建Vue时在钩子中再次绑定this 
new Vue({
  beforeCreate() {
    Vue.prototype.$bus = this
  },
  store,
  render: h => h(App),
​
}).$mount('#app')
​
// 兄弟1 接收
 export default{
  mounted() {
    this.$bus.$on('changeName',this.getName)
  },
  methods: {
    getName(name){
      alert(`收到${name}`)
    }
  },
 }
// 兄弟二发送
export default {
  methods: {
    handler(){
      this.$bus.$emit('changeName','xxxx')
    }
  },
}
​
// Vue 2 + ts 同样操作

Inject与Provide[props 加强版]

// 父组件
export default {
    provide:{
        age:10
    }
    // provide(){
        //  return {
                // age:10
          //}
    // }
}
​
// 子组件和孙组件
exprot default {
    inject:['age']
}
​
// 父组件 
import { Component, Prop, Vue ,Provide} from 'vue-property-decorator';
export default class HelloWorld extends Vue {
      @Provide('getName') getName(age:number){alert(age)}
}
​
// 子组件
import { Component, Prop, Vue ,Provide} from 'vue-property-decorator';
export default class HelloWorld extends Vue {
     @Inject('getName') getName:any
}

model

// 子组件
export default {
  props:['vaule'] // 若只想让父组件收到则可省略
  model:{
    prop:'value',
    event:'change'
  },
}
​
// 父组件
<Sub v-mode="value"><Sub>
    
// 子组件
import {Emit,Vue,Component,Model} from 'vue-property-decorator'
@Component({
    name:'Sub'
})
export default class Sub extends Vue {
    // @model 第一个为 event , 参数二为 props配置【非必传】  后面跟着 props 
    @Model('change',{type:String}) name!:string
    // 通过 emit 事件 实现 父子数据同步
    @Emit('change') change(name:string){return name}
    
}
   
// 父组件 
<sub v-mode="myName"></sub>
export default class HelloWorld extends Vue {
    myName:string = 'wwww'
}
​

方法书写

export default {
    methods:{
        handlerSearch(){
            xxxxxxx
        }
    }
}
// 直接书写方法即可
export default class about extends Vue {
    handlerSearch(){
        xxxxxx
    }
}

Vuex基本语法

Vue 模块化 Vuex

// home 模块
const state = {
    userName:"axxx"
} 
const mutations = {} 
const actions = {
    getUserName({commit},params){
    }
}
export default {
    namespaced: true,  // 模块化后必须开启,否则找不到actions方法
    state,
    mutations,
    actions
}
// store index.js 
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
import home from './models/home'
export default new Vuex.Store({
    state:{},
    mutations:{},
    getters:{},
    actions:{},
    modules:{
        home
    }
})
​
// 组件中使用
this.$store.dispatch('home/getUserName','xxxx')
​

vu2 + ts

  • 使用Ts语法去书写vue2 中的veux方式实现
// index.ts
import Vue from 'vue'
import Vuex from 'vuex'
import Home from './model/home'
Vue.use(Vuex)
​
export default new Vuex.Store({
  state: {
  },
  mutations: {
  },
  actions: {
  },
  modules: {
    Home
  }
})
// Home.ts
const state = {
 a:10
}
const mutations = {}
const actions = {
    getUserName({commit}:{commit:any},params:any){ // 解构赋值要给定其类型
        console.log(params)
    }
} 
const getters = {
    
} 
export default {
    namespaced:true,
    state,
    mutations,
    actions,
    getters
}
​
// 组件内使用:
import {Component,Vue} from 'vue-property-decorator'
@Component({
  name:'HelloWord'
})
export default class HelloWord extends Vue {
  handler(){
    this.$store.dispatch('Home/getUserName','xxx')
  }
}
  • 使用vuex-module-decorators简化vuex

参考:github.com/championswi…

博客“blog.csdn.net/weixin_4457…

npm install -D vuex-module-decorators
//index.ts import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
// 引入对应模块数据
import { IterHomeState } from './model/home'
// //接受home的接口,暴露它应有的属性
interface IterRootSate {
  Home:IterHomeState
}
//暴露所有接口,暴露所有接口的属性
export default new Vuex.Store<IterRootSate>({})
// home.tsimport { Module, VuexModule, Mutation, Action, getModule } from 'vuex-module-decorators'
import store from '../index'
// 模拟API
const getList = () => {
    return new Promise<Array<number>>(resolve => {
        setTimeout(() => {
            resolve([1, 2, 3, 4, 5, 6])
        }, 500)
    })
}
​
//暴露接口
export interface IterHomeState {
    count: number;
    list: Array<number>;
}
//这里配置仓库的一些基础配置
@Module({
    name: "home",
    dynamic: true,
    store
})
​
export default class Home extends VuexModule implements IterHomeState {
​
//这里是仓库所具有的一些属性【state】
    count = 1;
    list = [1, 2, 3, 4];
//使用get修饰,代替了以前的getters
    get filterList() {
        return this.list.filter(item => item % 2 === 0)
    }
    get num() {
        return this.count
    }
//使用@mutation修饰器修饰,代替以前的mutation
    @Mutation
    updateCount(payload: number) {
        this.count += payload
    }
    @Mutation
    updateList(payload: Array<number>) {
        this.list = payload
    }
//使用@Action修饰器修饰,代替以前的Action
    @Action
    async getList(): Promise<boolean> {
        // const res=await xxx()
        //这里模拟了请求数据再给属性赋值
        const res: Array<number> = await getList()
        this.updateList(res)
        return Promise.resolve(true)
    }
​
}
//暴露仓库
export const HomeStore = getModule(Home)
​
// home组件中使用import {Component,Vue} from 'vue-property-decorator'
import {HomeStore} from '@/store/model/home'
@Component({
  name:'home'
})
export default class home extends Vue {
  handler(){
    HomeStore.getList()
  }
}

Vue-router 基本语法

跟Vue2 一样