你可能不知道vue还能这样写(一)

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第2天,点击查看活动详情

前言

阅读这篇文章你将学到:

  1. 装饰器模式的大量运用
  2. this的灵活运用
  3. vue jsx tsx的写法

从vue2跨越到vue3是一大步,而在跨越之前社区就产生了很多解决方案:例如template替换为render函数、还有的直接使用jsx语法,更有甚者直接使用类组件的方式来进行编码,与React类组件非常相似;今天我们就来讲一讲使用类组件的方式来写vue,并且把我遇到的坑都给大家分享出来

先安装一下vue-class-component,开始我们今天的旅行

Component

Component:类组件的基石,必须调用这个函数才能使用类组件,同时需要扩展Vue这个类

@Component
expoort default class HelloWorld extends Vue{ }
复制代码

Component函数的参数类型:VueClass,也就是说它的参数就是Option API中的options,既然我们要使用类组件的方式那么我们一般不主动去调用Component函数,而是在类组件内部去定义

@Component({
    // 定义组件
    components:{
        ABC
    },
    computed:{
    
    },
    created(){
    
    }
})
expoort default class HelloWorld extends Vue{ }
复制代码

Data

在类组件上怎么定义data呢?就直接利用类的属性去定义就可以了

@Component
expoort default class HelloWorld extends Vue{
     dataSource=[] // 定义一个数组
     type=0        //定义一个数字
     string=''     //定义一个字符串
}
复制代码

如果需要设置初始空值,不能直接把属性设置为undefined,这样的话是非响应式属性;可以设置为null或者使用data来声明

expoort default class HelloWorld extends Vue{
    // 错误的设置方式
     undefined = undefined
     undefined;
     // 应该设置为null或者使用data hook
     null = null // 这个属性是响应式属性
     data(){
         return {
             // 也是响应式属性
             undefined:undefined
         }
     }
}
复制代码

注意由于vue2的问题,我们如果初始化一个空对象,那么后面新增属性的话,也是非响应式属性

总结一下:vue class组件中定义一个响应式属性需要把初始值设置为非undefined的值,如果只是临时存储一个对象则可以不给初始值,这样就不会进行响应式处理,节省了内存

Computed

Computed是直接使用get或者set访问器来进行设置的,但是需要借助一个data来进行值的修改,class组件的set访问器不支持返回值,与普通对象的set访问器不同,这里需要格外注意

扫描二维码关注公众号,回复: 14195750 查看本文章
expoort default class HelloWorld extends Vue{
    name="Hello"
    get myName(){
        return this.name + "World"
    }
    set myName(val){
        this.name = val
    }
}
复制代码

Hooks

生命周期函数与React class组件类似,例如mounted、created、destroyed、render,值得注意的是这个render函数其实是this.$createElement的语法糖,在编译阶段会转化为后者,正是由于这一点,我们需要格外注意这个render函数的使用,现在我们来和React组件做一个比较:

class ReactComp extends Component{
    renderSection = ()=>{
        reutrn <section>123</section>
    }
    render(){
        return <div>{this.renderSection()}</div>
    }
}

class VueComp extends Vue{
    renderSection = ()=>{
        reutrn <section  data={()=> <div>a</div>}>123</section>
    }
    renderMap={
        a:()=>{
            return <div>a</div>
        },
        b(){
            return <div>b</div>
        }
    }
    render(){
        return <div data={this.renderMap}>{this.renderSection()}
        </div>
    }
}
复制代码

最后Vue组件报错:“TypeError: Cannot read property '$createElement' of undefined”

为什么会报这个错误呢,肯定是this指向不正确,然后我们去函数内部打印this,发现打印不出来,应该是在编译阶段直接给报错了,这里的原因我们后面章节再讲,总之我们避免在类组件中写箭头函数,这和我们在options API中不能写箭头函数是一样的;同样的我们分析一下renderMap它在vue中也会报错,第一个a属性中箭头函数的this指向是正确的但是我们无法让编译正常通过,因此我们可以使用this.$createElement代替jsx;而b属性中的this指向了renderMap这个对象,肯定是报错的无法挽救;

最后我们在vue组件中尽量不要把组件属性提取出来而是直接在组件上写:就像renderSection中section的data属性一样

slots

类组件中的slots比template多一种表达方式,就是直接写在组件的属性中,在传统的vue2组件中我们是无法通过一个props来渲染一个组件或者DOM节点的,但是class组件能够实现这一点

// class组件可以使用以下两种方式
<ClassComp data={<Props/>}/>
// template只能使用slots
<ClassComp>
    <Props/>
</ClassComp>
复制代码

scoped slots怎么定义?其实就是我们上面所说的第一种方式,我们传递一个函数就可以了

总结:我们今天系统学习了vue类组件的写法,vue类组件有利于ts类型的声明,但是需要我们有深厚的基本功,如果我们连this都搞不懂那么一定用不好这个类组件

猜你喜欢

转载自juejin.im/post/7101831098807615496