vue简单总结

166 阅读6分钟

安装命令

npm install -g @vue/cli
# OR
yarn global add @vue/cli

然后我们就可以通过vue create XXX来创建我们得vue项目

我们选中图中几项常用得就可以创建出我们得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的这么多信息 感觉等正式版出来后应该也是不错的