#vue3与vue2区别以及vue3优点

  1. 默认进行懒观察(lazy observation)在 2.x 版本里,不管数据多大,都会在一开始就为其创建观察者。当数据很大时,这可能会在页面载入时造成明显的性能压力。3.x 版本,只会对「被用于渲染初始可见部分的数据」创建观察者,而且 3.x 的观察者更高效。
  2. 更精准的变更通知。2.x 版本中,使用 Vue.set 来给对象新增一个属性时,这个对象的所有 watcher 都会重新运行;3.x 版本中,只有依赖那个属性的 watcher 才会重新运行。
  3. 3.0 新加入了 TypeScript 以及 PWA 的支持
  4. 部分命令发生了变化:
    a.下载安装 npm install -g vue@cli
    b.删除了vue list
    c.创建项目 vue create
    d.启动项目 npm run serve
  5. 默认项目目录结构也发生了变化:
    移除了配置文件目录,config 和 build 文件夹
    移除了 static 文件夹,新增 public 文件夹,并且 index.html 移动到 public 中
    在 src 文件夹中新增了 views 文件夹,用于分类 视图组件 和 公共组件

移除data 取而代之使用 setup
在新版当中setup等效于之前2.0版本当中得到beforeCreate,和created,它是在组件初始化的时候执行,甚至是比created更早执行。值得注意的是,在3.0当中如果你要想使用setup里的数据,你需要将用到值return出来,返回出来的值在模板当中都是可以使用的。
假设如果你不return出来,而直接去使用的话浏览器是会提醒你:
如果要想在页面中使用生命周期函数的,根据以往2.0的操作是直接在页面中写入生命周期,而现在是需要去引用的,这就是为什么3.0能够将代码压缩到更低的原因。

如何知道数据发生了变化,Vue3 之前使用了 ES5 的一个 API Object.defineProperty。Vue3 中使用了 ES6 的 Proxy,都是对需要侦测的数据进行 变化侦测 ,添加 getter 和 setter ,这样就可以知道数据何时被读取和修改。
如何知道数据变化后哪里需要修改,Vue 对于每个数据都收集了与之相关的 依赖 ,这里的依赖其实就是一个对象,保存有该数据的旧值及数据变化后需要执行的函数。每个响应式的数据变化时会遍历通知其对应的每个依赖,依赖收到通知后会判断一下新旧值有没有发生变化,如果变化则执行回调函数响应数据变化(比如修改 dom)。


#vue3生命周期

vue3中使用的生命周期
使用defineComponent 构建应用及绑定事件
使用setup(props,content)父子通信
使用 reactive 绑定数据
使用 ref ( torefs ) 绑定数据
使用 getCurrentInstance 获取当前实例化对象上下文信
watch、watchEffect 数据监听
生命周期+axios数据请求
简单的 TodoList 点餐功能
computed 对应vue2中computed,使用方法不同

生命周期
setup() :开始创建组件之前,在beforeCreate和created之前执行。创建的是data和method
onBeforeMount() : 组件挂载到节点上之前执行的函数。
onMounted() : 组件挂载完成后执行的函数。
onBeforeUpdate(): 组件更新之前执行的函数。
onUpdated(): 组件更新完成之后执行的函数。
onBeforeUnmount(): 组件卸载之前执行的函数。
onUnmounted(): 组件卸载完成后执行的函数
若组件被 keep-alive 包含,则多出下面两个钩子函数。
onActivated(): 被包含在中的组件,会多出两个生命周期钩子函数。被激活时执行
onDeactivated(): 比如从 A组件,切换到 B 组件,A 组件消失时执行。
VUE2 VUE3
beforeCreate setup()
created setup()
beforeMount onBeforeMount
mounted onMounted
beforeUpdate onBeforeUpdate
updated onUpdated
beforeDestroy onBeforeUnmount
destroyed onUnmounted
activated onActivated
deactivated onDeactivated
import {ref,onBeforeMount,onMounted,onBeforeUpdate,onUpdated,onBeforeUnmount,onUnmounted,onErrorCaptured,onRenderTracked,onRenderTriggered} from 'vue'export default {setup() {let test = ref('测试');// 挂载开始之前被调用onBeforeMount(() => {console.log('onBeforeMount组件挂载到节点上之前执行的函数', test.value)});// 实例被挂载后调用,不会保证所有的子组件也被挂载完onMounted(() => {console.log('onMounted组件挂载完成后执行的函数', test.value)});// DOM更新前onBeforeUpdate(() => {console.log('onBeforeUpdate组件更新之前执行的函数', test.value)});// DOM更新后,不会保证所有的子组件也都一起被重绘onUpdated(() => {console.log('onUpdated组件更新完成之后执行的函数', test.value)});// 卸载组件实例之前,此时实例仍然是完全正常的onBeforeUnmount(() => {console.log('onBeforeUnmount组件卸载之前执行的函数', test.value)});// 卸载组件实例后调用。调用此钩子时,组件实例的所有指令都被解除绑定,所有事件侦听器都被移除,所有子组件实例被卸载。onUnmounted(() => {console.log('onUnmounted组件卸载完成后执行的函数', test.value)});// 当捕获一个来自子孙组件的错误时被调用onErrorCaptured(() => {console.log('onErrorCaptured当捕获一个来自子孙组件的错误时被调用', test.value)});// onRenderTracked和onRenderTriggered是用来调试的,这两个事件都带有一个DebuggerEvent,它使我们能够知道是什么导致了Vue实例中的重新渲染。。onRenderTracked(() => {console.log('onRenderTracked跟踪虚拟 DOM 重新渲染时调用', test.value)});onRenderTriggered(() => {console.log('onRenderTriggered当虚拟 DOM 重新渲染', test.value)});return {test};}}

#demo使用各依赖版本

{"name": "vue3-typescript","version": "0.1.0","private": true,"scripts": {"serve": "vue-cli-service serve","build": "vue-cli-service build"},"dependencies": {"axios": "^0.21.1","core-js": "^3.6.5","element-plus": "^1.2.0-beta.6","vue": "^3.0.0","vue-router": "^4.0.0-0","vuex": "^4.0.0-0"},"devDependencies": {"@types/node": "^17.0.0","@types/webpack-env": "^1.16.3","@vue/cli-plugin-babel": "~4.5.0","@vue/cli-plugin-router": "~4.5.0","@vue/cli-plugin-typescript": "~4.5.0","@vue/cli-plugin-vuex": "~4.5.0","@vue/cli-service": "~4.5.0","@vue/compiler-sfc": "^3.0.0","image-webpack-loader": "^7.0.1","less": "^3.0.4","less-loader": "^5.0.0","typescript": "~4.1.5","vuex-module-decorators": "^1.0.1"}
}

#vue3+typescript+element-plus

PS:搭建项目就不赘述了,网上好多很好的文章。
大佬文章: vue3项目搭建传送门
typescript的特性就是类型检测以及interface接口,既然决定使用typescript那么就要用,尽量不用any;
可以定义一个全局的interface接口,按需引入就可以。

//在src目录下建一个types目录创建一个store.ts
export interface TestObject {name: string,value: number
}
//在需要使用interface 接口.vue文件或者.ts文件引入
//以.vue文件举例
import { defineComponent, reactive} from 'vue';
import { TestObject } from '@/types/store';//引入类型interface dataType {//定义setup reactive中的数据类型testData: Array<TestObject>,//设置数组<对象>类型
}export default defineComponent({setup(){const data:dataType = reactive({testData: [{ name: '测试', value: 0 }]})}
})

以上是在vue3中typescript基本使用


element-plus是一个支持vue3.x的UI框架
element-plus官网

//全局引入与按需引入element-plus
//main.ts
import { createApp } from 'vue'
import App from './App.vue'
...
import ElementPlus from 'element-plus';
//import { ElButton } from 'element-plus';   //按需导入
import 'element-plus/dist/index.css'
//element-plus默认是英文,需要自己配置中文
import locale from 'element-plus/es/locale/lang/zh-cn'
const app = createApp(App);
//注册组件
//app.component('ElButton',ElButton)
...
app.use(ElementPlus, { size: 'small', zIndex: 3000, locale });

#vue3+typescript router

vue2与vue3中router还是有点区别的,尤其是加上typescript;
在main.ts中引入与注册我就不过多赘述了,主要说一下router的基础配置吧。

//在router>index.ts
import { createRouter, createWebHistory, RouteRecordRaw } from 'vue-router'const routes: Array<RouteRecordRaw> = [//RouteRecordRaw 当前记录的嵌套路由。{path: '/',name: 'Homeg',component: () => import(/* webpackChunkName: "Home" */ '../views/Home.vue')},{path: '/about',name: 'About',component: () => import(/* webpackChunkName: "about" */ '../views/About.vue')},{path:'/test',name:'test',component: () => import(/* webpackChunkName: "test" */ '../views/test.vue')}
];
// Vue-router新版本中,需要使用createRouter来创建路由
// createWebHashHistory hash模式 createWebHistory History模式
const router = createRouter({history: createWebHistory(),routes
});router.afterEach((value) => {//路由监听console.log(value);
});export default router
<!-- 使用路由 -->
<template><div id="nav"><router-link to="/">Home</router-link> |<router-link to="/about">About</router-link> |</div><router-view/>
</template>

#vue3+typescript 组件传值

基础用法:

<!-- 父组件 -->
<template><el-row><el-col><el-card><el-row><h2><b>父组件</b></h2><el-col> <b>父组件msg1值:</b>{{ msg1 }} </el-col><el-col> <b>父组件msg2值:</b>{{ msg2 }} </el-col></el-row></el-card></el-col><el-col><el-divider></el-divider></el-col><el-col><el-card><!-- :msg1="msg1" @setMsg1="getMsg1" 使用基础的使用方式与vue2.x基本一致 --><!-- 但是在vue3.x中移除了.sync语法糖 使用v-model替代 --><Childrens :msg1="msg1" v-model:msg2="msg2" @setMsg1="getMsg1"></Childrens></el-card></el-col></el-row>
</template><script lang='ts'>
import { defineComponent, reactive, toRefs } from "vue";
import Childrens from "./components/children.vue";
interface DataPType {msg1: string;msg2: string;
}
export default defineComponent({name: "",components: { Childrens },setup() {const data: DataPType = reactive({msg1: "父组件msg1",msg2: "父组件msg2",});const getMsg1 = (val:string) =>{data.msg1 = val};return {...toRefs(data),getMsg1};},
});
</script>

关于vue2.x与vue3.x中语法变化,比如 .sync等语法糖的移除请看vue3语法官网

<!-- 子组件 -->
<template><el-row><h2><b>子组件</b></h2><el-col> <b>子组件使用msg1值:</b>{{ msg1 }} </el-col><el-col :span="24"> <b>子组件使用msg2值:</b>{{ msg2 }} </el-col><el-col><el-divider></el-divider></el-col><el-col><el-button type="primary" @click="getPropData">获取父组件传过来的值</el-button><el-button type="primary" @click="setMsg1">修改父组件msg1值</el-button><el-button type="primary" @click="setMsg2">修改父组件msg2值</el-button></el-col></el-row>
</template><script lang='ts'>
import { defineComponent, reactive, toRefs } from "vue";export default defineComponent({name: "Childrens",props: {msg1: String,msg2: { type: String, default: "" },},//setup(props)第一个参数props 以用于获取父组件传过来的值//setup(props,rex)第二个参数rex上下文对象(emit,slots,attrs)可以用 {emit} 或者直接 rex.emit//{emit} 使用 emit("XXX",需要修改的值)//rex 使用 rex.emit("XXX",需要修改的值)setup(prop, { emit }) {const getPropData = () => {console.log(prop);alert(prop.msg1);alert(prop.msg2);};const setMsg1 = () => {//基础用法 与 vue2.x 改动不大emit("setMsg1", "这是子组件修改的值(msg1)");};const setMsg2 = () => {emit("update:msg2", "这是子组件修改的值(msg2)");//同等于 vue2.x中this.$emit("update:msg2", "这是子组件修改的值(msg2)")//父组件在接收时不是在使用 msg2.sync="msg2" 而使用v-model:msg2="msg2"};return {getPropData,setMsg1,setMsg2,};},
});
</script>

PS:关于toRefs的使用与介绍(大佬文章: 传送门);说一下比较实用的吧。

<template><el-row><!-- <el-col>注1: {{ data.msg }} </el-col> --><el-col>注2: {{ msg }} </el-col></el-row>
</template><script lang='ts'>
import { defineComponent, reactive, toRefs } from "vue";
interface DataPType {msg: string;
}
export default defineComponent({setup() {const data: DataPType = reactive({msg: "1",});return {//data,//直接把 data 抛出去在 template中使用需要 data.msg (注1)...toRefs(data),//使用了 toRefs(data) 的话,在template直接可以访问 msg (注2)};},
});
</script>

#vue3+typescript+watch

上代码

<template><div><h1>watch、watchEffect 数据监听</h1><p>msg: {{msg}}</p><p>msg2: {{msg2}}</p><p><button @click="changeMsg">changeMsg</button></p><p><button @click="changeMsg2">changeMsg2</button></p></div>
</template>
<script>
import {defineComponent, reactive, watchEffect, watch, toRefs} from 'vue';export default defineComponent({setup() {const state: any = reactive({// 使用响应式函数reactive构建proxy响应式对象statemsg: 'value1',msg2: 'value2',changeMsg2: () => {state.msg2 = '改变value2'}});const changeMsg = () => {// 在外边定义methodsstate.msg = '改变value1';};// watch监听只能是 getter/effect 函数、ref、reactive对象或数组// 简单监听watch(state, () => {// 只要state中的值有变化,就会打印console.log('观察整个state中的属性变化'+ '%c' + '《' +  state.msg + '》','color:red');});// 监听指定的信息watch(() => state.msg, (newVal, oldVal) => {console.log('01-msg的新值是: ' + '%c' + '《' +  newVal + '》','color:red');console.log('01-msg的旧值是: ' + '%c' + '《' +  oldVal + '》','color:red');});// 监听多个属性(数组形式)watch([() => state.msg, () => state.msg2], (newVal, oldVal) => {console.log('02-msg的新值是: ' + '%c' + '《' +  JSON.stringify(newVal) + '》','color:yellow');console.log('02-msg的旧值是: ' + '%c' + '《' +  JSON.stringify(oldVal) + '》','color:yellow');});// 不需要指定监听的属性watchEffect(_ => {// 程序运行时,初始化就会执行一次,完成监听准备工作// 有点像computed计算属性,用到的数据发生改变才会执行console.log('03-watchEffect监听 state 中数据变化'+'%c' + '《' + state.msg + '》','color:lime')});return {...toRefs(state),changeMsg,}}})
</script>

#vue3+typescript 使用axios模块化

axios中文文档

说一下我根据以前vue2.x常用的axios的配置改为vue3.x+typescript的配置

//先说一下啊目录结构
src
--http
---index.ts
---request.ts
---api
----queryAip.ts
//http>index.ts/** 请求封装 **/import axios from 'axios';
import {Payload} from '@/types/store'
//export interface Payload {//可以规定一下后端返回的数据类型
//  code: string,
//  msg?: string,
//  data?: any
//}//封装post(get、delete...与下面没有太大差异)
export const POST = (url: string, params: object) => {return new Promise<Payload>((resolve, reject) => {axios.post(url, params).then(res => {resolve(res.data)}).catch(err => {reject(err)})})
};
//http>request.ts/** 请求拦截 **/import axios, {AxiosInstance, AxiosRequestConfig, AxiosResponse} from 'axios';//axios 拦截export class Request {// 初始化拦截器public static initInterceptors() {axios.defaults.headers.post['Content-Type'] = 'application/json';/*** 请求拦截器* 每次请求前,如果存在token则在请求头中携带token*/axios.interceptors.request.use((config: AxiosRequestConfig) => {config.headers.token = '';return config;},(error: any) => {console.log(error);},);// 响应拦截器axios.interceptors.response.use(// 请求成功(response: AxiosResponse) => {//...},// 请求失败(error: any) => {const {response} = error;if (response) {//...} else {// 处理断网的情况// eg:请求超时或断网时,更新state的network状态// network状态在app.vue中控制着一个全局的断网提示组件的显示隐藏// 关于断网组件中的刷新重新获取数据,会在断网组件中说明console.log('网络连接异常,请稍后再试!');}});}/*** http握手错误* @param res 响应回调,根据不同响应进行不同操作*/private static errorHandle(res: any) {// 状态码判断switch (res.status) {case 401:break;case 403:break;case 404:console.log('请求的资源不存在');break;default:console.log('连接错误');}}
}
//http>api>queryApi.ts/** 请求接口封装 **/import { POST } from '@/http/index';
import {postType} from '@/types/store';
//export interface postType{//  limit: number,
//  start: number
//}//封装接口
const GetList = (obj: postType) => POST('/list',obj);export {GetList}
//全局引入与注册
//main.ts
import { createApp } from 'vue'
import App from './App.vue'import { Request } from '@/http/request'
const app = createApp(App);
...
app.use(Request.initInterceptors);//初始化拦截器
//使用请求数据
<script lang='ts'>
import { defineComponent, reactive, onMounted } from 'vue';
import { GetList } from '@/http/api/textApi'
import { InstanceType } from '@/types/store';//export interface InstanceType {//定义返回数据类型
//  resultList: {}[],
//  start: number,
//  limit: number,
//}interface dataType {tableData: InstanceType[]
}export default defineComponent({setup() {let data: dataType = reactive({tableData: []});const getAxiosData = (start: number = 1) => {GetList ({ start, limit: 10 }).then(res => {if (res.code === '000000') {data.tableData = res.data.resultList;}});};onMounted(() => {getAxiosData()});return {getAxiosData,//return出去可以在页面绑定}},});
</script>

#vue3+typescript vuex

在vue2.x中使用vuex的结构基本同步移动vue3.x中

//看一下目录结构
src
--store
---index.ts
---actions.ts
---mutations.ts

上代码

//store > index.ts
import {createStore} from 'vuex'//引入vuex 在vuex4版本中需要使用 createStore来构建
import actions from './actions';//引入actions
import mutations from './mutations';//引入mutationsinterface StoreType {//定义 state 中数据类型vuexValue:string,
}export default createStore({state:<StoreType> {vuexValue:'初始值'},mutations,actions,
})
//store > actions.ts
import {Commit} from 'vuex'//引入 Commit 类型const Actions = {setVuexValue(context: { commit: Commit }, value: string) {context.commit('SET_VUEX_VALUE', value)}
};export default Actions
//store > mutations.ts
const Mutations = {SET_VUEX_VALUE(state: any, data: string){state.vuexValue = data},
};export default Mutations

以上是vuex基本使用,其他的也不多少说了;下面介绍一下在.vue里面使用;

<template><el-row><el-col>VUEX-vuexValue值: {{ vuexValue }}</el-col><el-col><el-button type="primary" @click="setVuexValue('VUEX数据修改')">修改VUEX数据</el-button></el-col></el-row>
</template><script lang='ts'>
import { defineComponent, reactive, toRefs, computed } from "vue";
// import { useStore } from "vuex"; // 1 => 使用vuex方式
import store from '@/store'// 2 => 使用vuex方式interface DataPType {}
export default defineComponent({name: "vuex4",setup() {const data: DataPType = reactive({});// const store = useStore();  //1 => 使用vuex方式 //vuex实例化const setVuexValue = (value: string) => store.dispatch("setVuexValue", value); // 1,2 => 使用vuex方式const vuexValue = computed(() => store.state.vuexValue); // 1,2 => 使用vuex方式return {...toRefs(data),setVuexValue,vuexValue,};},
});
</script>

#vue3+typescript vuex进阶

说一下vuex配合vuex-module-decorators的用法吧;
vuex-module-decorators的安装看一下官方的文档吧;传送门

//看一下目录结构
src
--store
---index.ts
---module
----test.ts

上代码!

//index.ts
import { createStore } from 'vuex'
import { config } from 'vuex-module-decorators' //引入 vuex-module 中的 config
config.rawError = true;//如果不设置  module层会拦截报错 会给出module层报错信息 设置为true 报错会正常
export default createStore({})
//test.ts
import { Module, VuexModule, Mutation, Action, getModule } from 'vuex-module-decorators'
import store from '../index'// dynamic: true: 动态创建动态模块,即在 index.ts export default createStore({})里面不用注册的.空着就行,
// store,当前模块注册到store上.也可以写在getModule上,即getModule(PassengerStore,store)
// namespaced: true,
// name: 'passenger' 命名空间@Module({ dynamic: true, store, name: 'TEST' })export default class test extends VuexModule {// 定义变量需要 使用 public 不然外面访问不到/*** public 默认共有属性* private 私有属性* protected 私有属性,派生类中仍可访问* readonly 只读属性* static 静态属性* abstract 抽象类或方法* **/public vuexValue: string = '';//可直接使用 computed(() => TestModule.vuexValue)get GetVuexValue(): string { //也可使用 computed(() => TestModule.GetVuexValue)return this.vuexValue}// @Mutation // 注意:每一个 Mutation、Action... 都需要在前面声明 @XXX// XXX(data: string) {//     this.XXX = data;// };// 在 class 中 this 指向的是当前 class@MutationSET_VUEX_VALUE(data: string) {this.vuexValue = data;};@Actionpublic setVuexValue(value: string) {this.SET_VUEX_VALUE(value)};
}export const TestModule = getModule(test)

在 .vue 中使用

<template><el-row><el-col>vuex数据: {{ testValue }}</el-col><el-col><el-button type="primary" @click="setVuexValue('改变vuex值')">改变vuex值</el-button></el-col></el-row>
</template><script lang='ts'>
import { defineComponent, reactive, toRefs, computed } from "vue";
import { TestModule } from "@/store/module/test"; //引入 vuex moduleinterface DataPType {testValue: string;
}
export default defineComponent({name: "",setup() {const data: DataPType = reactive({testValue: computed(() => TestModule.vuexValue), //也可以直接调用setVuexValue: (value: string) => TestModule.setVuexValue(value), //也可以直接调用,不过不建议这样});// 把 TestModule.setVuexValue 赋值到 setVuexValue 中, 也可以直接调用 TestModule.setVuexValue()// const setVuexValue = (value: string) => TestModule.setVuexValue(value);//第一种使用setVuexValue// const vuexValue = computed(() => TestModule.vuexValue);//第一种使用vuexValuereturn {...toRefs(data),// setVuexValue,//第一种使用setVuexValue// vuexValue,//第一种使用vuexValue};},
});
</script>

vue3+ts+element-plus(包含vuex、router) 随笔相关推荐

  1. vue3+ts+element封装一个简易的curd

    vue3+ts+element封装一个简易的curd 闲来无趣做一个简单的table封装,不喜勿喷 首先创建一个公共的Table.vue/pagination.vue文件 Table.vue < ...

  2. vue3+ts+element 简单的登陆案例 (一)

    第一步 创建vue3项目 项目名字不能使用驼峰命名 创建好项目目录 我们需要引入自己的css文件来重订样式 再index.html 文件夹中引入css html, body, div, span, a ...

  3. Vue3+TS+Vite+Element Plus搭建后台管理系统

    Vue3+TS+Vite+Element Plus搭建后台管理系统 1.简介 2.效果图 3.技术栈 4.项目目录 5.setting.js(全局配置文件) 6.路由router 7.状态管理stor ...

  4. vue vite创建项目的使用(使用技术栈vue3+vuex+router+ts+element plus)

    文章目录 前言 创建vite项目 vite.config.ts配置 自动化引入组件配置以及.env配置的引用 创建src/vite-env.d.ts main.ts配置 api/request.ts ...

  5. 使用Vite创建Vue3+TS项目并整合Element Plus框架等一条龙服务

    记录一下使用Vite创建Vue3+TS项目以及整合Element Plus框架,还有Less.Pinia.Vue-router.monaco-editor等插件或组件. 一.使用Vite创建Vue3+ ...

  6. vue3 使用Element Plus <script lang=“ts“ setup>加上lang=“ts“后编译错误

    vue3 使用Element Plus <script lang="ts" setup>加上lang="ts"后编译错误 目录 vue3 使用Ele ...

  7. 前端实战:electron+vue3+ts开发桌面端便签应用

    前端时间我的一个朋友为了快速熟悉 Vue3 开发, 特意使用 electron+vue3+ts 开发了一个桌面端应用, 并在 github 上开源了, 接下来我就带大家一起了解一下这个项目, 在文章末 ...

  8. vue3+ts+el-tabs+keep-alive

    vue3+ts+el-tabs+keep-alive 先写一下我的需求,那就是tabs切换页,普普通通的切换页也就算了,但是得加上keep-alive缓存,加上缓存也就算了 ,而且这个要切换的tabs ...

  9. vite+vue3+ts项目搭建之集成qiankun让其成为子应用模板(vite+vue3+ts+qiankun项目)—新增主应用在线地址可以进入vue2/vue3子应用

    前言 以下操作,是续接之前 第四步 --即:vite+vue3+ts+pinia+element-plus项目已完成搭建好,可以直接业务开发了 主应用技术栈:vue2+webpack+js 集成qia ...

最新文章

  1. Day11多态部分-1 【1.1 多态的体现】
  2. python模拟点击网页按钮_网页自动化开发(第一章)
  3. java mic波形识别_会议季Mic Drop:您不应该错过的13场Java演讲
  4. Java 算法 学做菜
  5. java线程池 的方法_JAVA线程池的实现方法
  6. 机械制图符号_?《机械制图》课程 试题库(中专)
  7. opencv 提取图像线条 霍夫线检测
  8. OpenGL学习笔记_图形渲染管线及典型渲染流程(绘制一个三角形)
  9. 抓包工具charles青花瓷的基本使用(android)
  10. pdf文件如何在线转换为jpg图片 1
  11. MT6765/MT6762/MT6761平台能否使用ACC/Gyro/A+G与AP之间的I2C接口
  12. android 导入离线地图,Android版百度地图SDK离线包导入相关
  13. 腾讯邱跃鹏:解密腾讯亿级产品背后网络架构故事
  14. 易趋携手电气风电,推进产品研发项目管理能力进阶
  15. 微软Google人才战主角首次开口:Google让我震撼(转)
  16. Android当方法总数超过64K时(Android Studio)
  17. Mac流程图制作工具:Diagrams
  18. MATLAB设置图片输出的尺寸大小与字体(适用科研论文)
  19. Springboot毕业设计毕设作品,汽车租赁系统 开题报告
  20. 股票实盘交易接口用什么编程的?

热门文章

  1. 手机端页面 自适应解决方案-收集
  2. Games104现代游戏引擎入门-lecture12游戏引擎的粒子和声效系统
  3. 网易云音乐、QQ音乐一键下载工具(Go语言)
  4. vue中this.$nextTick()使用解析
  5. SyntaxError (语法错误)
  6. oracle安装在非图形,非图形化静默安装Oracle 11g
  7. 问题 A: 深入浅出学算法044-最大整数
  8. Unity3d制作菜单栏
  9. 第二届全国高校计算机能力挑战赛-Java程序设计赛
  10. html中的ppt文字不清晰,PPT文字太少怎么办!高手必备的PPT救场技巧