随着vue3.0更新潮流,vue+ts应该是未来vue项目的一个主流方向。
以前就算用vue-class-component用来写也会有很多暗坑,但是现在vue3.0版本完美支持tsx,终于可以快乐的尝尝鲜了。
首先明确2点:
Q:ts有什么用?
A:类型检查、直接编译到原生js、引入新的语法糖
Q:为什么用ts?
A:TypeScript的设计目的应该是解决JavaScript的“痛点”:弱类型和没有命名空间,导致很难模块化,不适合开发大型程序。另外它还提供了一些语法糖来帮助大家更方便地实践面向对象的编程。
Vue 项目初始化
第一步,安装 vue-cli:
npm install -g @vue/cli
安装成功后,我们即可使用 vue 命令,测试方法:
$ vue -V
@vue/cli 4.3.1
第二步,初始化 vue 项目:
vue create vue-next-test
输入命令后,会出现命令行交互窗口,这里我们选择 Manually select features:
Vue CLI v4.3.1
? Please pick a preset:
default (babel, eslint)
❯ Manually select features
随后我们勾选:Router、Vuex、CSS Pre-processors 和 Linter / Formatter,这些都是开发商业级项目必须的:
Vue CLI v4.3.1
? Please pick a preset: Manually select features
? Check the features needed for your project:
◉ Babel
◯ TypeScript
◯ Progressive Web App (PWA) Support
◉ Router
◉ Vuex
◉ CSS Pre-processors
❯◉ Linter / Formatter
◯ Unit Testing
◯ E2E Testing
注意:Vue 3.0 项目目前需要从 Vue 2.0 项目升级而来,所以为了直接升级到 Vue 3.0 全家桶,我们需要在 Vue 项目创建过程中勾选 Router 和 Vuex,所以避免手动写初始化代码
回车后会自动安装依赖,为了加速安装速度,我们可以使用淘宝源来加快初始化速度:
vue create -r https://registry.npm.taobao.org vue-next-test
项目创建完毕后,目录结构如下:.
├── README.md
├── babel.config.js
├── package-lock.json
├── package.json
├── public
│ ├── favicon.ico
│ └── index.html
└── src
├── App.vue
├── assets
│ └── logo.png
├── components
│ └── HelloWorld.vue
├── main.js
├── router
│ └── index.js
├── store
│ └── index.js
└── views
├── About.vue
└── Home.vue
创建路由
项目开发中,我们通常需要创建新页面,然后添加路由配置,我们在 /src/views 目录下创建 Test.vue:
<template>
<div class="test">
<h1>test page</h1>
</div>
</template>
<script>
export default {
}
</script>
<style lang="less" scoped>
.test {
color: red;
}
</style>
之后在 /src/router/index.js 中创建路由配置:
import {
createRouter, createWebHashHistory } from 'vue-router'
import Home from '../views/Home.vue'
const routes = [
{
path: '/',
name: 'Home',
component: Home
},
{
path: '/about',
name: 'About',
component: () => import(/* webpackChunkName: "about" */ '../views/About.vue')
},
{
path: '/test',
name: 'Test',
component: () => import(/* webpackChunkName: "test" */ '../views/Test.vue')
}
]
const router = createRouter({
history: createWebHashHistory(),
routes
})
export default router
初始化 Vue Router 的过程与 3.0 版本变化不大,只是之前采用构造函数的方式,这里改为使用 createRouter 来创建 Vue Router 实例,配置的方法基本一致,配置完成后我们还需要在 App.vue 中增加链接到 Test.vue 的路由:
<template>
<div id="app">
<div id="nav">
<router-link to="/">Home</router-link> |
<router-link to="/about">About</router-link> |
<router-link to="/test">Test</router-link>
</div>
<router-view/>
</div>
</template>
Vue组件的几种形式:
1.类组件扩展组件函数组件
类组件是我们在ts项目中使用频率最高的组件,它可以使用我们的装饰器,使组件完美的使用typescript.
<script lang="ts">
import {
Component, Vue } from 'vue-property-decorator'
@Component({
name: 'Demo'
})
export default class extends Vue{
}
</script>
20扩展组件
和平时使用vue的方式完全相同,但是不能使用装饰器。
<script lang="ts">
import Vue from 'vue'
export default Vue.extend({
})
</script>
3.函数组件
如果使用过react的话会知道react中有函数式组件,并且性能相比于其他组件要好一点但是没有生命周期。
<template functional>
<div>
<h3>函数型组件</h3>
</div>
</template>
常用方法尝试:
1.Component
@Component 装饰器可以接收一个对象作为参数,可以在对象中声明 components ,filters,directives等未提供装饰器的选项
<script lang="ts">
import {
Component, Vue } from 'vue-property-decorator'
import HeaderComponent from '@/components/HeaderComponent.vue'
import ResizeMixin from "../mixins"
@Component({
name: 'Demo',
components: {
// 组件
HeaderComponent
},
directives: {
// 局部指令
test(el: HTMLElement, binding) {
console.log(el, binding);
}
},
filters: {
// 局部过滤
addOne(num: number) {
return num + 1;
}
},
mixins: [ResizeMixin],
})
export default class extends Vue{
}
</script>
2.@Prop --> 数据接受参数
@Prop() str1!: string; // 必传
@Prop() str2: string | undefined; // 非必传
@Prop({
default: "默认值" }) str3: string | undefined;
3.data --> 数据绑定
private name = "张三";
private age = 18;
private userInfo: UserInfo = {
name: "李四",
age: 39
};
4.methods --> 方法
private addAge() {
this.btn.style.background = "yellow";
this.age += 1;
}
5.computed --> 计算属性
get initUser() {
return "计算后的age" + this.age;
}
6.@Watch --> 监听数据的变化
interface UserInfo {
name: string;
age: number;
}
@Watch("age")
handelChangeAge(newVal: number, oldVal: number) {
console.log("新数据" + newVal, "老数据" + oldVal);
}
// 深度监听
@Watch("userInfo", {
deep: true, immediate: false })
handelChangeUserInfo(newVal: UserInfo, oldVal: UserInfo) {
console.log("新数据" + newVal, "老数据" + oldVal);
}
7.@Ref --> 获取元素
<button type="button" ref="btn" @click="addAge" class="btn">
测试ref
</button>
@Ref("btn") btn!: HTMLButtonElement;
addAge() {
this.btn.style.background = "yellow";
}
8.@Emit --> 发布事件
// Child
<button @click="addStrClick">addStrClick</button>
<button @click="addStrClick2('1')">addStrClick</button>
@Emit()
addStrClick() {
return "1";
}
@Emit()
addStrClick2(str) {
return str + 1;
}
// father
<Child @addStrClick="***" @addStrClick2="***" />
生命周期
created() {
console.log("created");
}
mounted() {
console.log("mounted");
}
总结
需要不断尝试新鲜事物(踩坑)