提早熟悉Vue3.0 + Ts

可怜的前端程序员们又要开始一轮新的学习,心好累,学习的进度准是赶不上创造的速度。两个月前尤大大公布了 vue 3.0 的源码,目前仍是 pre-alpha 状态,预计年后会发布正式版本。

3.0的目标

  • 更小
  • 更快
  • 增强 TypeScript 支持
  • 增强 API 设计一致性
  • 提升自身可维护性
  • 开放更多底层功能


什么是Hooks?

hooks翻译过来是钩子的意思,这个可能有一些模糊,简单点说hooks就是一个函数(能够复用的函数)
javascript

例如:业务中很难避免的一个问题就是-- 逻辑复用,一样的功能,一样的组件,在不同的场合下,咱们有时候不得不去写2+次,为了不耦合咱们出现了一些概念(mixin,高级组件,slot插槽)

上述这些方法均可以实现逻辑上的复用,可是都有一些额外的问题:


mixin的问题:

  • 不一样的mixin中的方法,属性可能会相互冲突(命名空间冲突);
  • mixin很是多时,会形成数据来源不清晰


HOC的问题:

  • 须要在原组件上进行包裹或者嵌套,将会产生很是多的嵌套,调试起来不容易;
  • props命名空间冲突(多个高级组件的props冲突)
  • props 数据来源不清晰(不知道这个属性究竟是那个高级组件传递的)
  • 额外的组件实例消耗性能


做用域插槽:

没有命名冲突和数据来源不清晰的问题,可是建立了额外的组件

因此,hook的出现是划时代的,它经过function抽离的方式,实现了复杂逻辑的内部封装在vue中的hooks主要是为了
逻辑代码的复用
不存在命名冲突,数据来源不清晰的问题
减少了代码体积:由于在打包时候咱们用了那些函数就会打包那些不用的不会打包,并且在打包的时候会对函数进行混淆压缩变得更小
没有this的烦恼,不须要经过this访问一些内容了,嗨皮



什么是TypeScript?


其实TypeScript并非一门新的语言,它是 JavaScript 类型的超集,typeScript那并非一个新语言,能够理解为增强JavaScript的buff,TypeScript最大的优点源于强大的类型系统,还有就是在编写代码的时候就能够检测出咱们可能由于粗心形成的没必要要的错误css


为何要学习TypeScript ?

  • 将来趋势,目前来看发展,和应用趋势很快
  • vue3.0发布后,基本就离不开ts了
  • 使用 TypeScript 能够帮助咱们防止在编写 JavaScript 代码时由于数据类型的转换形成的意想不到的错误。
    提早帮咱们发现代码出现错的风险。
  • 团队成员使用 JavaScript 时很容易瞎写,不受规范约束。
    可是若是使用TypeScript那你们都不得不遵照规范。
  • TypeScript 紧跟 JavaScript 的发展,ES7 、ES八、ES9 相关语言的新特性都支持,比浏览器支持的速度更快。


什么样的项目须要TypeScript ?

  • 团队多人开发的大项目
  • 开源项目
  • 企业对代码有高质量要求的项目

如何使用Ts


Vue3.0 最重要的就是 RFC,即 Function-based API。Vue3.0 将抛弃以前的 Class API 的提案,选择了 Function API。目前,vue 官方 也提供了 Vue3.0 特性的尝鲜版本,前段时间叫 vue-function-api,目前已经更名叫 composition-api。

使用官方脚手架Vue-cli建立一个ts项目
npm install -g @vue/cli
# OR
yarn global add @vue/cli复制代码


新的 VueCLI工具容许开发者 使用 TypeScript 集成环境 建立新项目。
只需运行 vue create tsvue3demo。
而后,命令行会要求选择预设。使用箭头键选择 Manually select features。
这样一个可使用ts的vue基础架构就构建完成了

目录架构
.
├── README.md
├── babel.config.js
├── package.json
├── postcss.config.js
├── public│
   ├── favicon.ico│
   └── index.html├── src│
   ├── App.vue│
   ├── assets│
   │   └── logo.png│
   ├── components│
   │   └── HelloWorld.vue│
   ├── main.ts│
   ├── router│
   │   └── index.ts│
   ├── shims-tsx.d.ts 容许你以 .tsx结尾的文件,在 Vue项目中编写 jsx代码│
   ├── shims-vue.d.ts 主要用于 TypeScript 识别 .vue 文件│
   ├── store│
   │   └── index.ts│
   └── views│
       ├── About.vue│
       └── Home.vue
├── tsconfig.json
└── yarn.lock复制代码
在这个建立好的目录中咱们打开 HelloWord.vue 文件能够看到不同的组件写法
<template>
  <div class="hello">
    <h1>{{ msg }}</h1>
    ...
  </div>
</template>
​<script lang="ts">
import { Component, Prop, Vue } from 'vue-property-decorator'
​@Componentexport default class HelloWorld extends Vue {
  @Prop() private msg!: string;
}
</script>复制代码
以上的写法是在vue3.0之前,强化Vue组件使用typeScript的写法


须要引入:
vue-class-component:强化 Vue 组件,使用 TypeScript/装饰器 加强 Vue 组件
vue-property-decorator:在 vue-class-component 上加强更多的结合 Vue 特性的装饰器
ts-loader:TypeScript 为 Webpack 提供了 ts-loader,其实就是为了让webpack识别 .ts .tsx文件
tslint-loader跟tslint:我想你也会在.ts .tsx文件 约束代码格式(做用等同于eslint)
tslint-config-standard:tslint 配置 standard风格的约束

可是在vue3.0里面废弃了class component

Vue3.0的用法

Vue3.0尚未正式发布,可是官方提供了Vue 2.x 可以提早体验此API的库@vue/composition-api
html


安装
npm i @vue/composition-api -S复制代码


使用
import Vue from 'vue'
import VueCompositionApi from '@vue/composition-api'

​Vue.use(VueCompositionApi)复制代码

若是项目是用的 TS,须要使用 createComponent 来定义组件,这样你才能使用类型推断,若是没有使用,可直接抛出一个对象
<template>
  <div id="app">​
  </div>
</template>
<script lang="ts">
import { createComponent } from '@vue/composition-api'
export default createComponent({  ...})
</script>

复制代码

实例:这是VueConf 2019尤大大在介绍的时候给出的一个例子,改为ts版本前端

<template>
  <div id="app">
    <div class="hooks-one">
      <h2>{{ msg }}</h2>
      <p>count is {{ count }}</p>
      <p>plusOne is {{ plusOne }}</p>
      <button @click="increment">count++</button>
    </div>
    <!-- <router-view/> -->
  </div>
</template>
<script lang="ts">
import { ref, computed, watch, onMounted, Ref, createComponent } from '@vue/composition-api'
​interface Props {
  name: string
}
​export default createComponent({
  props: {
    name: {
      type: String,
      default: 'ssss'
    }
  },
  components: {},
  setup (props: Props, context) {
    const count: Ref<number> = ref(0)
    // computed
    const plusOne = computed(() => count.value + 1)
    // method
    const increment = () => {
      count.value++
    }
    // watch
    watch(() => count.value * 2, val => {
      console.log(`count * 2 is ${val}`)
    })
    // 生命周期
    onMounted(() => {
      console.log('onMounted')
    })
    // expose bindings on render context
    return {
      count,
      plusOne,
      increment,
      msg: `hello ${props.name}`
    }
  }
})
</script>复制代码

详解:vue

setup

setup函数是Vue Function API 构建的函数式写法的主逻辑,当组件被建立时,就会被调用,函数接受两个参数,分别是父级组件传入的props和当前组件的上下文context。context上下文(this的替代者能够理解为),setup 是在组件实例被建立时, 初始化了 props 以后调用,处于 created 前。
setup() 和 data() 很像,均可以返回一个对象,而这个对象上的属性则会直接暴露给模板渲染上下文:

<template>
    <div id="app">
      {{ msg }}
      {{ count }}
    </div>
</template>

<script lang="ts">
import { createComponent } from '@vue/composition-api'
export default createComponent({
    props: {
      name: String
    },
    setup (props) {
      const count: Ref<number> = ref(0)
      return {
        msg: `hello ${props.name}`,
        count
      }
    }
})
</script>复制代码

组件 API(Composition API)


组件 API 是 Vue 的下一个主要版本中最经常使用的讨论和特点语法。这是一种全新的逻辑重用和代码组织方法。

当前,咱们使用所谓的 Options API 构建组件。为了向 Vue 组件添加逻辑,咱们填充(可选)属性,例如 data、methods、computed等。这种方法的最大缺点是其自己并非有效的 JavaScript 代码。你须要确切地知道模板中能够访问哪些属性以及 this 关键字的行为。在后台,Vue 编译器须要将此属性转换为工做代码。所以咱们没法从自动建议或类型检查中受益。
java

组件 API 旨在经过将组件属性中当前可用的机制公开为 JavaScript 函数来解决这个问题。Vue 核心团队将组件 API 描述为 “一组基于函数的附加 API,能够灵活地组合组件逻辑。” 用组件 API 编写的代码更具备可读性


reactive和ref

reactive(): 转换响应式对象
ref(): 转换原始类型为响应式对象


二者的区别
reactive 代理初始化一个对象,ref 只是一个 .value 值,在函数中使用都要一直使用 .value 引着
<template>
  <div id="app">
    <div class="hooks-one">
      {{state.double}}
      {{state.count}}
      <p>count is {{ count }}</p>
      <button @click="increment">count++</button>
    </div>
    <!-- <router-view/> -->
  </div>
</template>
<script lang="ts">
import { ref, computed, reactive, Ref, createComponent } from '@vue/composition-api'
​interface State {  count: number,  double: number}
​export default createComponent({  setup (props, context) {
    const count: Ref<number> = ref(0)
    const state: State = reactive({
      count: 0,
      double: computed(() => state.count * 2)
    })
    // method
    const increment = () => {
      count.value++  // 须要.value获取,改变
      state.count++
    }
    // expose bindings on render context
    return {
      increment,
      state
    }
  }
})
</script>复制代码

watch & computed

watch和computed的基本概念与 Vue 2.x 的watch和computed一致,watch能够用于追踪状态变化来执行一些后续操做,computed用于计算属性,用于依赖属性发生变化进行从新计算。
computed返回一个只读的包装对象,和普通包装对象同样能够被setup函数返回,这样就能够在模板上下文中使用computed属性。能够接受两个参数,第一个参数返回当前的计算属性值,当传递第二个参数时,computed是可写的。=

生命周期

全部现有的生命周期都有对应的钩子函数,经过onXXX的形式建立,但有不一样的是,destoryed钩子函数须要使用unmounted代替,删除了onBeforeCreate和onCreated:
import { onMounted, onUpdated, onUnmounted, createComponent } from '@vue/composition-api';
export default createComponent({
      setup() {
            onMounted(() => {
                  console.log('mounted!');
            });
            onUpdated(() => {
                  console.log('updated!');
            });
            // destroyed 调整为 unmounted
            onUnmounted(() => {
                  console.log('unmounted!');
            });
      },
});复制代码


结语:

但愿你们坚持,努力,学习是件有意思的事情,加油同志们。
若是有不对的地方但愿指正。
若是你们有须要的东西能够私信我。
若是你们有好的内容但愿能够一块儿分享

参考:

https://zhuanlan.zhihu.com/p/68477600
https://www.yuque.com/vueconf/2019
https://vue-composition-api-rfc.netlify.com/api.html
https://juejin.im/post/5dca71f8f265da4cef191581
https://juejin.im/post/5d836458f265da03d871f6e9
https://segmentfault.com/a/1190000020205747?utm_source=tag-newest


关注公众号

相关文章
相关标签/搜索