TypeScript (下面简称ts)越来越火爆(框架,github开源项目,公众号,文章都在增加ts相关内容…),不久的将来会成为前端必备技能(学不动了啊),记录怎样在vue项目中使用ts(写一些简单的demo)以及vue的多种写法。
npx vue create vue-ts
? Please pick a preset: Manually select features
? Check the features needed for your project:Babel, TS, Router, Vuex, CSS Pre-processors, Linter
// CSS Pre-processors 使用less sass/scss stylus
// 是否使用class风格的语法
? Use class-style component syntax? (Y/n)y
// 是否使用babel转换ts之外的内容
// 选择之后还可以自动处理polyfills 转换JSX
? Use Babel alongside TypeScript (required for modern mode, auto-detected polyfills, transpiling JSX)? (Y/n) y
// 是否使用history模式 服务端渲染必须使用history模式
? Use history mode for router? (Requires proper server setup for index fallback in production) (Y/n)n
? Pick a CSS pre-processor (PostCSS, Autoprefixer and CSS Modules are supported by default):Less
? Pick a linter / formatter config:Standard
// 什么情况下触发ESLinter校验代码
? Pick additional lint features: Lint on save, Lint and fix on commit
// 怎样生成配置文件
? Where do you prefer placing config for Babel, PostCSS, ESLint, etc.?In dedicated config files
? Save this as a preset for future projects?(y/N)n
package.json变动
HellowWord示例说明
总结:增加一些ts相关的配置,以及组件的写法
优点:强类型语言,编译阶段避免类型引起的作用,类型提示
已有项目可以根据变动增加相应的内容,即可使用ts进入开发,详细内容参考官方文档
<script lang="ts">
// 常规写法
export default {
data () {
return {
message: 'Hellow World'
}
},
created () {
}
}
</script>
<script lang="ts">
import Vue from 'vue'
export default Vue.extend({
name: 'Foo',
data () {
return {
message: 'Hellow World'
}
},
created () {
}
})
</script>
组件继承自Vue,类型更明确
<script lang="ts">
import {
Component, Vue } from 'vue-property-decorator'
// 装饰器:一个函数用来拓展 Vue
// 目前装饰器语法还不稳定,没有发布正式版不推荐
@Component
// 类名:组件的 name
export default class Foo extends Vue {
message: string = 'Hellow World'
}
</script>
在App.vue中使用Foo组件
在Class写法中更改了data、methods、computed、watch等内容,详情请参考官方文档
代码
<!-- Foo -->
<template>
<div id="">
<h1>Foo 组件</h1>
<p @click="test">{
{
size}}</p>
</div>
</template>
<script lang="ts">
// Class APIs
import {
Component, Vue, Watch } from 'vue-property-decorator'
// 装饰器:一个函数用来拓展 Vue
@Component
// 类名:组件的 name
export default class Foo extends Vue {
message = 'Hellow World'
count = 10
// methods
test () {
console.log('Foo')
}
get size () {
return this.message + '!'
}
// Watch 需要从 vue-property-decorator 中导入
// @Watch('xx') 来监听某个属性
@Watch('message')
// 后续跟着处理函数,如果想要多个处理函数 可以在后面继续写
getMessage (newVal: string, oldVal: string) {
console.log('getMessage', newVal, oldVal)
}
getMessages (newVal: string, oldVal: string) {
console.log('getMessages', newVal, oldVal)
}
@Watch('count')
counts (newVal: string, oldVal: string) {
console.log('counts', newVal, oldVal)
}
created () {
setTimeout(() => {
this.message = 'aaa'
this.count++
}, 3000)
}
}
</script>
进一步的提升了 Class APIs 的语法
详情参考文档(不是官方的)
尤大大在B站 直播分享了vue-next v3.0.0-beta.1 版本
提出了6大亮点
由于版本还没有定稿,就不分享了,初体验网上到处都是大家随便看看,体验体验…
详细 API 请查看官网 (ps:还是官网)
realworld:提供了页面模板以及数据接口(示例:一个论坛)
示例
<!-- layout -->
<template>
<div id="">
<!-- 头部导航栏 -->
<nav class="navbar navbar-light">
<div class="container">
<a class="navbar-brand" href="index.html">conduit</a>
<ul class="nav navbar-nav pull-xs-right">
<li class="nav-item">
<!-- Add "active" class when you're on that page" -->
<a class="nav-link active" href="">Home</a>
</li>
<li class="nav-item">
<a class="nav-link" href="">
<i class="ion-compose"></i> New Post
</a>
</li>
<li class="nav-item">
<a class="nav-link" href="">
<i class="ion-gear-a"></i> Settings
</a>
</li>
<li class="nav-item">
<a class="nav-link" href="">Sign up</a>
</li>
</ul>
</div>
</nav>
<!-- 子路由出口 -->
<router-view />
<!-- 尾部 -->
<footer>
<div class="container">
<a href="/" class="logo-font">conduit</a>
<span class="attribution">
An interactive learning project from <a href="https://thinkster.io">Thinkster</a>. Code & design licensed under MIT.
</span>
</div>
</footer>
</div>
</template>
<script lang='ts'>
import Vue from 'vue'
export default Vue.extend({
name: 'LayoutIndex'
})
</script>
import Vue from 'vue'
import VueRouter, {
RouteConfig } from 'vue-router'
Vue.use(VueRouter)
const routes: Array<RouteConfig> = [
// 使用异步路由
{
path: '/',
component: () => import('@/views/layout/index.vue'),
children: [
]
}
]
const router = new VueRouter({
routes
})
export default router
<template>
<div id="app">
<!-- 跟路由出口 -->
<router-view />
</div>
</template>
<script lang="ts">
import Vue from 'vue'
export default Vue.extend({
})
</script>
项目正常运行,且 Header 和 Footer 展示正常
{
path: '/',
component: () => import('@/views/layout/index.vue'),
children: [
{
path: '', // 默认子路由 path为空是会将内容默认渲染到组件当中
name: 'home',
component: () => import('@/views/home/index.vue')
}
]
}
启动项目,页面展示正常
{
path: '/',
component: () => import('@/views/layout/index.vue'),
children: [
{
path: '', // 默认子路由 会将path为空的路由默认渲染到父路由当中
name: 'home',
component: () => import('@/views/home/index.vue')
},
{
path: '/login',
name: 'login',
component: () => import('@/views/login/index.vue')
}
]
}
修改地址链接http://localhost:8080/#/login,进入 login 路由正常
使用 realworld 提供的 requese API
安装 axios
创建 utils 文件夹以及 request.ts
简易封装 axios
创建 api 文件夹
封装 register 接口
修改 eslint 配置,接口不使用分隔符
.eslintrc.js 修改 rules
新增
'@typescript-eslint/member-delimiter-style': 'off'
<!-- login/register -->
<template>
<div class="auth-page">
<div class="container page">
<div class="row">
<div class="col-md-6 offset-md-3 col-xs-12">
<h1 class="text-xs-center">Sign up</h1>
<p class="text-xs-center">
<a href="">Have an account?</a>
</p>
<ul class="error-messages">
<li>That email is already taken</li>
</ul>
<form @submit.prevent="onSubmit">
<fieldset class="form-group">
<input v-model="user.username" class="form-control form-control-lg" type="text" placeholder="Your Name">
</fieldset>
<fieldset class="form-group">
<input v-model="user.email" class="form-control form-control-lg" type="text" placeholder="Email">
</fieldset>
<fieldset class="form-group">
<input v-model="user.password" class="form-control form-control-lg" type="password" placeholder="Password">
</fieldset>
<button class="btn btn-lg btn-primary pull-xs-right">
Sign up
</button>
</form>
</div>
</div>
</div>
</div>
</template>
<script lang='ts'>
import Vue from 'vue'
import {
register } from '@/api/auth'
export default Vue.extend({
name: 'LoginIndex',
data () {
return {
user: {
username: '',
email: '',
password: ''
}
}
},
methods: {
onSubmit () {
try {
// 获取表单数据
// 表单验证
// 提交表单
const data = register({
user: this.user
})
console.log(data)
// 根据返回结果处理后续操作
this.$router.push({
name: 'home'
})
} catch (error) {
console.log('提交失败...', error)
}
}
}
})
</script>
完成,接口访问正常,注册正常