安装命令
npm install -g @vue/cli
# OR
yarn global add @vue/cli
然后我们就可以通过vue create XXX来创建我们得vue项目

vue-cli3脚手架生成项目目录说明
│ .browserslistrc
│ .gitignore
│ .postcssrc.js // postcss 配置
│ babel.config.js
│ package.json // 依赖
│ README.md // 项目 readme
│ tsconfig.json // ts 配置
│ tslint.json // tslint 配置
│ vue.config.js // webpack 配置(~自己新建~)
│ yarn.lock
│
├─public // 静态页面
│ │—favicon.ico
│ │—index.html
│
├─src // 主目录
│ ├─assets // 静态资源
│ │ logo.png
│ │
│ ├─components
│ │ HelloWorld.vue
│ │
│ │─views // 页面
│ │ About.vue
│ │ Home.vue
│ │
│ │ App.vue // 页面主入口
│ │
│ │ main.ts // 脚本主入口
│ │
│ ├─router // 路由配置
│ │ index.ts
│ │
│ │ registerServiceWorker.ts // PWA 配置
│ │
│ │ shims-tsx.d.ts // jsx语法的声明
│ │ shims-vue.d.ts // vue的声明
│ │ shims-global.d.ts // 声明一些全局模块或第三方插件(自己创建)
│ │ shims-mount-vue.d.ts // 声明挂载在vue上的模块(自己创建)
│ │
│ │
│ ├─store // vuex 配置
│ │ index.ts
│ │
│ ├─typings // 全局注入(~自己新建~)
│ │
│ ├─utils // 工具方法(axios封装,全局方法等)(~自己新建~)
│ │ index.ts
│ │
│ ├─system // 配置系统方法及组件
│ │ Initialization.ts 初始化基础配置 在main.ts中使用
shims-vue.d.ts文件说明
由于 TypeScript 默认并不支持 .vue 后缀的文件,所以在 vue 项目中引入的时候需要创建一个shims-vue.d.ts 文件,放在项目项目对应使用目录下,例如 src/shims-vue.d.ts,用来支持.vue 后缀的文件;
shims-mount-vue.d.ts文件说明
声明挂载在vue上得一些组件及方法 比如:
import { Route } from 'vue-router';
declare module 'vue/types/vue' {
interface Vue {
$router: VueRouter; // 这表示this下有这个东西
$route: Route;
$http: http //封装得http方法;
$_toast: any; // 自己封装得组件,可以直接通过this调用
commonStr: string; // 全局使用得动态数据 比如动态图片链接等
}
vue中router编写
vue中路由编写比较简单我们只需导入vue-router
import Vue from 'vue';
import Router from 'vue-router';
Vue.use(Router);
export default new Router({
mode: 'hash',
base: process.env.BASE_URL,
routes: [
{
path: '/home',
name: 'home',
component: () => import(/* webpackChunkName: "h5Webview" */ '../pages/index.vue'),
meta:{
keepAlive:true
} //这个地方编写一些自定义得属性 比如keepAlive以及路由鉴权等
},
]
});
// 使用需要在跟文件使用
<template>
<keep-alive :include="includeComponents">
<router-view class="view-transition"></router-view>
</keep-alive>
</template>
</transition>
vue中组件和方法得封装
vue中组件得封装和React是不同得 Vue组件分为全局注册和局部注册,在react中都是通过import相应组件,然后模版中引用 props是可以动态变化的,子组件也实时更新,在react中官方建议props要像纯函数那样,输入输出一致对应,而且不太建议通过props来更改视图
子组件一般要显示地调用props选项来声明它期待获得的数据。而在react中不必需,另两者都有props校验机制
每个Vue实例都实现了事件接口,方便父子组件通信,小型项目中不需要引入状态管理机制,而react必需自己实现
使用插槽分发内容,使得可以混合父组件的内容与子组件自己的模板
多了指令系统,让模版可以实现更丰富的功能,而React只能使用JSX语法
Vue增加的语法糖computed和watch,而在React中需要自己写一套逻辑来实现 那我们现在简单封装一个vue组件
// 在ts中vue一些vue方法建议使用装饰器来修饰 @Component({}) 一种依赖注入的方法,为了降低代码的耦合度引用组件在这个里面进行 @prop()--> props接受数据 private:私有数据类似state
// get computed计算方法 @Emit 组件传值使用
<template>
<button :class="clsStyle" :disabled="disabled" @click="clickHandler">
<span :style="{color:this.color}"><slot></slot></span>
</button>
</template>
<script lang="ts">
import { Component, Vue, Prop, Emit } from 'vue-property-decorator';
@Component({
name: 'common-button',
})
export default class CommonButton extends Vue {
@Prop({default: ''}) type?: String;
@Prop({default: ''}) shape?: String;
@Prop({default: ''}) icon?: String;
@Prop({default: false}) disabled?: Boolean;
@Prop({default: false}) block?: Boolean;
@Prop({default: false}) small?: Boolean;
@Prop({default: false}) label?: Boolean;
@Prop({default: ''}) color?: String;
get clsStyle() {
let cls = 'common-button ';
cls += `${this.disabled ? '' : this.type} ${this.shape}`;
cls += this.small ? ' small' : '';
cls += this.block ? ' block' : '';
cls += this.label ? ' label' : '';
if(!this.$slots.default) {
if(this.small) {
cls += ' no-txt-small';
}else {
cls += ' no-txt';
}
}
return cls;
}
@Emit('click')
clickHandler() {}
}
</script>
那我们想使用这个组件就可以通过import使用了 但有人感觉每次都要import很麻烦 我们就可以把他挂载到vue全局上
import { VueConstructor } from 'vue';
import Button from './button.vue';
import './button.scss';
Button.install = function(Vue: VueConstructor) {
Vue.component(Button.name, Button);
};
export default Button;
然后在我们main.ts中Vue.use(Button)j就可以了 这样就可以全局使用 但是有些情况,使用提示类得组件我们想挂载在this上使用会更方便,这样得话我们就需要单独处理了比如我们常用得继续以我们button组件为例
// _button.ts
import Vue from 'vue';
import settings from './button.vue';
interface iInst extends Vue {
vm: Vue;
visible: boolean;
}
let ButtonConstructor = Vue.extend(settings); //集成button组件
let inst: iInst;
let Button = function (options: {
id: string;
}) {
options.id = options.id || 'common-button-default-id';
inst = new ButtonConstructor({
propsData: Object.assign(options, { openFromMethod: true })
});
inst.vm = inst.$mount();
let buttonDom: HTMLElement | null = document.querySelector('#' + options.id);
if (options.id && buttonDom && buttonDom.parentNode) {
buttonDom.parentNode.replaceChild(inst.$el, buttonDom);
} else {
document.body.appendChild(inst.$el);
}
Vue.nextTick(() => {
inst.visible = true;
});
};
export default Button;
```然后只需要修改上面得函数
```js
import { VueConstructor } from 'vue';
import ButtonVue from './button.vue';
import Button from './_button';
import './button.scss';
const ButtonArr: any = [Button, ButtonVue];
ButtonArr.install = function(Vue: VueConstructor) {
Vue.prototype['$_Button'] = Select;
Vue.component(Button.name, Button);
};
export default Button;
这样我们就能通过 this.$_button来使用这个组件 但是这中用法比较适合那些弹出类组件 这儿只是做个例子 以上就是vue项目搭建得大致流程 目前vue2.0 对ts的支持并不友好建议3.0后升级ts
vue3.0初体验
3.0目前了解的不太多,就只针对2.0的一些体验不好的地方看了一下
目前 Vue2 的代码模式下存在的几个问题。
随着功能的增长,复杂组件的代码变得越来越难以维护。尤其发生你去新接手别人的代码时。根本原因是Vue的现有API通过「选项」组织代码,但是在大部分情况下,通过逻辑考虑来组织代码更有意义。
缺少一种比较「干净」的在多个组件之间提取和复用逻辑的机制。
类型推断不够友好。
针对以上举个简单的例子 在Vue2中如果我需要请求一份数据,并且在loading和error时都展示对应的视图,一般来说,我们会这样写:
<template>
<div v-if="error">failed to load</div>
<div v-else-if="loading">loading...</div>
<div v-else>hello {{fullName}}!</div>
</template>
<script>
export default {
data() {
// 集中式的data定义 如果有其他逻辑相关的数据就很容易混乱
return {
data: {
firstName: '',
lastName: ''
},
loading: false,
error: false,
},
},
async created() {
try {
// 管理loading
this.loading = true
// 取数据
const data = await this.$axios('/api/user')
this.data = data
} catch (e) {
// 管理error
this.error = true
} finally {
// 管理loading
this.loading = false
}
},
computed() {
// 没人知道这个fullName和哪一部分的异步请求有关 和哪一部分的data有关 除非仔细阅读
// 在组件大了以后更是如此
fullName() {
return this.data.firstName + this.data.lastName
}
}
}
</script>
这段代码,怎么样都谈不上优雅,凑合的把功能完成而已,并且对于loading、error等处理的可复用性为零。 在3.0中我们就可以这样写了
<template>
<div v-if="error">failed to load</div>
<div v-else-if="loading">loading...</div>
<div v-else>hello {{fullName}}!</div>
</template>
<script>
import useSWR from 'vue-swr'
// 类似umi-hooks
export default createComponent({
// setup 函数,就相当于 vue 2.0 中的 created
setup() {
const { data, loading, error } = useSWR('/api/user', fetcher)
// 计算属性
const fullName = computed(() => data.firstName + data.lastName)
return { data, fullName, loading, error }
}
})
</script>
Vue3.0 函数式组件基本模板
<template>
<div>
<span>count is {{ count }}</span>
<span>plusOne is {{ plusOne }}</span>
<button @click="increment">加一</button>
</div>
</template>
<script>
import { value, computed, watch, onMounted } from 'vue'
export default {
setup(props) {
// 初始数据
const count = value(0)
// 计算属性
const plusOne = computed(() => count.value + 1)
// 方法
const increment = () => { count.value++ }
// 每次count改变执行
watch(() => count.value, val => {
console.log(val)
})
// 生命周期
onMounted(() => {
console.log(`mounted`)
})
// expose bindings on render context
return {
count,
plusOne,
increment
}
}
}
</script>
在vue3.0中我们也可以想react编写hooks 比如一个简单控制boolean的hooks
import { useState, useCallback } from 'react';
function useBoolean( defaultValue = false) {
const [value,setValue] = useState(defaultValue)
const toggle = useCallback(
(value) => {
setState(value);
},
[state],
);
return {
value,
toggle
};
}
export default useBoolean;
在vue3.0中我们可以这样写
import { value } from 'vue'
function useBoolean(defaultValue=false) {
const state = value(defaultValue)
const toggle = value => {
state.value = value
}
return {
state,
toggle
};
}
export default useBoolean;
使用也并没有什么区别都是 const {state,toggle} = useBoolean(defalueValue)
语法区别vue中没有useCallBack useMemo等性能优化方案 具体原因不太清楚 感觉应该是使用Proxy的原因
要注意的是,vue3.0中 返回的是一个对象,通过 .value 才能访问到其真实值 类似react里的useRef,但是在模板中使用可以直接用
目前了解的就是vue3.0的这么多信息 感觉等正式版出来后应该也是不错的