vue-typescript
栏目: JavaScript · 发布时间: 5年前
内容简介:自尤大神去年9月推出vue对typescript的支持后,一直想开箱尝试vue+ts,最近一个新项目准备入手typescript,也遇到了很多坑,下面就一步步来吧!!!全局安装 vue-cli脚手架等待安装完成后开始下一步,检查是否安装成功: Vue -v
教你搭建typescript的vue项目
自尤大神去年9月推出vue对typescript的支持后,一直想开箱尝试vue+ts,最近一个新项目准备入手typescript,也遇到了很多坑,下面就一步步来吧!!!
1. 项目创建和初始化
1.1 安装脚手架与创建项目
全局安装 vue-cli脚手架
$ npm install -g @vue/cli 复制代码
等待安装完成后开始下一步,检查是否安装成功: Vue -v
1.2. 初始化项目
$ vue create vue-ts 复制代码
- 选择预设的模板
选择更多功能
Manully select features
回车后来到选择插件 - 选择插件
这边选择了(Babel、Typescript、Router、Css预处理器、Linter / Formatter 格式检查、Unit测试框架)
使用键盘空格选择插件 - 自动检测typescript(yes)
- 路由模式选择
是否使用 history模式的路由 (Yes) - 选择一个css预处理器 (Sass/SCSS)
- 选择格式检查规则(什么时候进行 tslint 校验: Line on save)
- 是否保存这份预设配置?(yes)
选是的话,下次创建一个vue项目,可以直接使用这个预设文件,而无需再进行新的配置,直接使用选择的模板创建项目
等待所有的依赖完成
下面这些功能是基于lentoo大神的vuecli3-project的进行升级改造的
2. 通过node来生成组件
安装chalk
$ npm install chalk --save-dev 复制代码
在根目录中创建一个 scripts 文件夹,
2.1. 通过node来生成组件
新增一个generateComponent.js文件,放置生成组件的代码、
新增一个template.js文件,放置组件模板的代码 template.js文件
/** * 将驼峰命名转为中横杠例如:PlInputGroup --> pl-input-group * @param str */ function toMiddleLine (str) { let temp = str.replace(/[A-Z]/g, function (match) { return "-" + match.toLowerCase() }); if (temp.slice(0, 1) === '-') { //如果首字母是大写,执行replace时会多一个-,这里需要去掉 temp = temp.slice(1) } return temp; } /** * 首字母大写 * @param {*} str 字符串 * @returns */ function initialToUp (str) { return str.slice(0, 1).toUpperCase() + str.slice(1); } module.exports = { vueTemplate: componentName => { return `<template> <div class="${toMiddleLine(componentName)}"> ${toMiddleLine(componentName)} </div> </template> <script lang="ts"> import { Vue, Component, Prop, Watch, Emit, Provide, Inject } from 'vue-property-decorator' @Component({}) export default class ${initialToUp(componentName)} extends Vue { } </script> <style lang="scss" scoped> @import './style.scss'; .${toMiddleLine(componentName)} {} </style>` }, styleTemplate: componentName => { return `.${toMiddleLine(componentName)} {}` }, entryTemplate: `import Main from './main.vue' export default Main ` } 复制代码
generateComponent.js文件
const chalk = require('chalk') const path = require('path') const fs = require('fs') const resolve = (...file) => path.resolve(__dirname, ...file) const log = message => console.log(chalk.green(`${message}`)) const successLog = message => console.log(chalk.blue(`${message}`)) const errorLog = error => console.log(chalk.red(`${error}`)) const { vueTemplate, entryTemplate, styleTemplate } = require('./template') const generateFile = (path, data) => { if (fs.existsSync(path)) { errorLog(`${path}文件已存在`) return } return new Promise((resolve, reject) => { fs.writeFile(path, data, 'utf8', err => { if (err) { errorLog(err.message) reject(err) } else { resolve(true) } }) }) } log('请输入要生成的组件名称、如需生成全局组件,请加 global/ 前缀') let componentName = '' process.stdin.on('data', async chunk => { const inputName = String(chunk).trim().toString() /** * 组件目录路径 */ const componentDirectory = resolve('../src/components', inputName) /** * vue组件路径 */ const componentVueName = resolve(componentDirectory, 'main.vue') /** * 入口文件路径 */ const entryComponentName = resolve(componentDirectory, 'index.ts') /** * style样式路径 */ const styleComponentName = resolve(componentDirectory, 'style.less') const hasComponentDirectory = fs.existsSync(componentDirectory) if (hasComponentDirectory) { errorLog(`${inputName}组件目录已存在,请重新输入`) return } else { log(`正在生成 component 目录 ${componentDirectory}`) await dotExistDirectoryCreate(componentDirectory) // fs.mkdirSync(componentDirectory); } try { if (inputName.includes('/')) { const inputArr = inputName.split('/') componentName = inputArr[inputArr.length - 1] } else { componentName = inputName } log(`正在生成 vue 文件 ${componentVueName}`) await generateFile(componentVueName, vueTemplate(componentName)) log(`正在生成 entry 文件 ${entryComponentName}`) await generateFile(entryComponentName, entryTemplate) log(`正在生成 style 文件 ${styleComponentName}`) await generateFile(styleComponentName, styleTemplate(componentName)) successLog('生成成功') } catch (e) { errorLog(e.message) } process.stdin.emit('end') }) process.stdin.on('end', () => { log('exit') process.exit() }) function dotExistDirectoryCreate (directory) { return new Promise((resolve) => { mkdirs(directory, function () { resolve(true) }) }) } // 递归创建目录 function mkdirs (directory, callback) { var exists = fs.existsSync(directory) if (exists) { callback() } else { mkdirs(path.dirname(directory), function () { fs.mkdirSync(directory) callback() }) } } 复制代码
配置package.json
"new:comp": "node ./scripts/generateComponent" 复制代码
执行 npm / cnpm / yarn run new:comp 生成组件
2.2. 通过node来生成页面组件
在scripts目录下新建一个generateView.js文件
generateView.js文件
const chalk = require('chalk') const path = require('path') const fs = require('fs') const resolve = (...file) => path.resolve(__dirname, ...file) const log = message => console.log(chalk.green(`${message}`)) const successLog = message => console.log(chalk.blue(`${message}`)) const errorLog = error => console.log(chalk.red(`${error}`)) const { vueTemplate } = require('./template') const generateFile = (path, data) => { if (fs.existsSync(path)) { errorLog(`${path}文件已存在`) return } return new Promise((resolve, reject) => { fs.writeFile(path, data, 'utf8', err => { if (err) { errorLog(err.message) reject(err) } else { resolve(true) } }) }) } log('请输入要生成的页面组件名称、会生成在 views/目录下') let componentName = '' process.stdin.on('data', async chunk => { const inputName = String(chunk).trim().toString() /** * Vue页面组件路径 */ let componentVueName = resolve('../src/views', inputName) // 如果不是以 .vue 结尾的话,自动加上 if (!componentVueName.endsWith('.vue')) { componentVueName += '.vue' } /** * vue组件目录路径 */ const componentDirectory = path.dirname(componentVueName) const hasComponentExists = fs.existsSync(componentVueName) if (hasComponentExists) { errorLog(`${inputName}页面组件已存在,请重新输入`) return } else { log(`正在生成 component 目录 ${componentDirectory}`) await dotExistDirectoryCreate(componentDirectory) } try { if (inputName.includes('/')) { const inputArr = inputName.split('/') componentName = inputArr[inputArr.length - 1] } else { componentName = inputName } log(`正在生成 vue 文件 ${componentVueName}`) await generateFile(componentVueName, vueTemplate(componentName)) successLog('生成成功') } catch (e) { errorLog(e.message) } process.stdin.emit('end') }) process.stdin.on('end', () => { log('exit') process.exit() }) function dotExistDirectoryCreate (directory) { return new Promise((resolve) => { mkdirs(directory, function () { resolve(true) }) }) } // 递归创建目录 function mkdirs (directory, callback) { var exists = fs.existsSync(directory) if (exists) { callback() } else { mkdirs(path.dirname(directory), function () { fs.mkdirSync(directory) callback() }) } } 复制代码
配置package.json
"new:view": "node ./scripts/generateView" 复制代码
执行 npm / cnpm / yarn run new:view 生成页面
3. vue与typescript结合
3.1. 首先组件声明
若对vue-property-decorator库不了解的,请点击 vue-property-decorator 的更多详解
创建组件如下:
<script lang="ts"> import { Component, Prop, Vue, Watch, Emit, Provide, Inject } from 'vue-property-decorator' @Component export default class Test extends Vue {} </script> 复制代码
3.2. data定义
若对ts的基本类型不了解的, 请点击typescript中文文档
private listTotal: number = 50 private form: any = { addText: [], addTextarea: [], text: '', textarea: '', imgUrl: '' } 复制代码
3.3 props声明
// align justify 弹性布局对齐方式 @Prop({default: 'center'}) private align!: string @Prop({default: 'flex-start'}) private justify!: string // 千万不要这样定义 @Prop private align: string = 'center' ---> 踩 </script> 复制代码
3.4 vue生命周期及自定义方法
methods不需要像vue里面 methods: { text () {return console.log(222)} }
public created (): void {} public mounted (): void {} public handleClick () {} // methods定义 复制代码
3.5 Watch
// 监听路由变化 @Watch('$route') onRouteChanged(route: any, oldRoute: any):void { console.log(route, oldRoute) } 复制代码
3.6 computed
public get msg () { return 'from typescript' } 复制代码
3.7 Emit
@Emit('change') private methodName(x: number, y: string) { console.log('child to parent a value') } 复制代码
5. 踩坑
5.1 tinymac富文本编辑器的结合ts的使用,tiny中文文档
引入tinymac的时候,会报错
解决方法:src目录下面新建一个shims-tinymce.d.ts文件
declare module 'tinymce/tinymce' 复制代码
重新启动项目就ok了
5.2 主题、样式、语言配置
- 主题
引入主题报错import 'tinymce/themes/modern/theme'
可以使用sliver主题
import 'tinymce/themes/silver/theme' 复制代码
- 样式及语言汉化
在public目录新建的static文件
2.1 将node_modules/tinymce/skins文件拷贝到static中
2.2zh_CN.js 下载,拷贝到static文件中
5.3 引入主题,样式,语言包
配置如下
public editorInit: any = { language_url: '/static/zh_CN.js', language: 'zh_CN', selector: 'textarea', skin_url: '/static/skins/ui/oxide', height: 300, browser_spellcheck: true, // 拼写检查 branding: false, // 去水印 // elementpath: false, //禁用编辑器底部的状态栏 statusbar: false, // 隐藏编辑器底部的状态栏 paste_data_images: true, // 允许粘贴图像 plugins: setPlugins, toolbar: setToolbar, // 启用菜单栏并显示如下项 [文件 编辑 插入 格式 表格] menubar: 'file edit insert view format table', // 配置每个菜单栏的子菜单项(如下是默认配置) menu: { file: { title: 'File', items: 'newdocument' }, edit: { title: 'Edit', items: 'undo redo | cut copy paste pastetext | selectall' }, insert: { title: 'Insert', items: 'link media | template hr' }, view: { title: 'View', items: 'visualaid' }, format: { title: 'Format', items: 'bold italic underline strikethrough superscript subscript | formats | removeformat' }, table: { title: 'Table', items: 'inserttable tableprops deletetable | cell row column' } }, // 覆盖默认的字体单位为pt fontsize_formats: '8px 10px 12px 14px 16px 18px 20px 24px 36px', /** * 下面方法是为tinymce添加自定义插入图片按钮 * 也可以借助elementui的Upload组件,上传图片 */ images_upload_url: '/api/image', // 上传图片接口地址 images_upload_handler: (blobInfo: any, success: any, failure: any) => { let xhr: any = null let formData: any = null xhr = new XMLHttpRequest() xhr.withCredentials = false xhr.open('POST', this.$store.state.imgUrl) xhr.onload = () => { if (xhr.status < 200 || xhr.status >= 300) { failure(xhr.status) return } let json = JSON.parse(xhr.responseText) if (json.code === 0) { success(json.data[0].newFileName) } else { failure('HTTP Error: ' + json.msg) } } formData = new FormData() formData.append('file', blobInfo.blob(), blobInfo.filename()) xhr.send(formData) } } 复制代码
附上效果图:
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Java 8实战
厄马(Raoul-Gabriel Urma)、弗斯科(Mario Fusco)、米克罗夫特(Alan Mycroft) / 陆明刚、劳佳 / 人民邮电出版社 / 2016-4-1 / CNY 79.00
本书全面介绍了Java 8 这个里程碑版本的新特性,包括Lambdas、流和函数式编程。有了函数式的编程特性,可以让代码更简洁,同时也能自动化地利用多核硬件。全书分四个部分:基础知识、函数式数据处理、高效Java 8 编程和超越Java 8,清晰明了地向读者展现了一幅Java 与时俱进的现代化画卷。一起来看看 《Java 8实战》 这本书的介绍吧!