vue-cli 3.0新特性
概述
在9 月 30 日的Vue.js 伦敦大会上, 作者尤雨溪介绍了 Vue 下一个版本将要发布的内容,以及 Vue 3.0 的开发路线,和后面版本的发展情况。虽然,Vue 3.0版本的正式版还没有发布,不过作为vue 项目快速构建工具的vue-cli 早已发布,我们可以通过vue-cli来了解vue 3.0的一些情况。
作为Vue的主要版本,Vue 3.0带来了诸多的重大变更,不过,开发组也非常重视兼容性问题:除了渲染函数 API 和作用域插槽语法之外的所有内容都将保持不变,或者通过兼容性构建让其与 2.x 保持兼容。总的来说,Vue 3.0 虽然会对顶级 API 进行重大的修整,但依然会保持与 2.x 的兼容。此外,2.x 的最后一个次要版本将成为 LTS,并在 3.0 发布后继续享受 18 个月的 bug 和安全修复更新。
欲了解更多的详情,可以参考下面的链接:Vue 3.0版本发布计划
重构
代码结构
为了实现更清晰、更易维护的源代码架构,尤雨溪表示将从头开始重写 3.0,并将一些内部功能分解为单独的包,以便隔离复杂性。如下图是vue 3.0的源码目录结构图。前文说过,Vue团队打算在从零开始编写 3.0 版本,为的是“达到更加清晰和更易维护的架构,特别是为了让代码的贡献变得容易”。为了降低复杂性,对复杂性进行隔离,开发团队将一些内部功能拆分为了多个单独的包。例如,observer 模块将成为一个单独的包,拥有自己对外的 API 和自己的测试用例。
另外,代码库现在改为用 TypeScript 编写,虽然这会使得“熟练TypeScript”成为对新代码库进行贡献的一个前置要求,不过我们相信有类型信息配合 IDE 的支持,对于一个新的贡献者来说,要做出有意义的贡献,实际上反而会更加容易。
除此之外,Vue还对改进编译器、支持 IE 11、其他运行时改进和改进观察机制等方面内容。
监测机制
3.0 将带来一个基于 Proxy 的 observer 实现,它可以提供覆盖语言 (JavaScript——译注) 全范围的响应式能力,消除了当前 Vue 2 系列中基于 Object.defineProperty 所存在的一些局限,这些局限包括:
对属性的添加、删除动作的监测;
对数组基于下标的修改、对于 .length 修改的监测;
对 Map、Set、WeakMap 和 WeakSet 的支持;
另外,新的 observer还提供了如下的一些特性:
公开的用于创建 observable 的 API:这为小型到中型的应用提供了一种轻量级的、极其简单的跨组件状态管理解决方案。
默认为惰性监测(Lazy Observation)。在 2.x版本中,任何响应式数据,不管它的大小如何都会在启动的时候监测功能。如果数据量很大的话,在应用启动的时候就可能造成严重的性能消耗。而在3.x 版本中,只有应用的初始可见部分所用到的数据会被监测,更不用说这种监测方案本身其实也是更加快的。
更精准的变动通知:举个例子:在 2.x 系列中,通过 Vue.set 强制添加一个新的属性,将导致所有依赖于这个对象的 watch 函数都会被执行一次;而在 3.x 中,只有依赖于这个具体属性的 watch 函数会被通知到。
不可变监测对象:我们可以创建一个对象的“不可变”版本,以此来阻止对他的修改——包括他的嵌套属性,除非系统内部临时解除了这个限制。这种机制可以用来冻结传递到组件属性上的对象和处在 mutation 范围外的 Vuex 状态树。
更好的调试能力:通过使用新增的 renderTracked 和 renderTriggered钩子,我们可以精确地追踪到一个组件发生重渲染的触发时机和完成时机及其原因。
编译器
Vue 3.0与编译器相关的代码编译将会有一个大的提升,用一句话概括为:“摇树友好”的输出;更多的 AOT 优化;更良好的解析错误;支持 source map。
如果采用的是支持“摇树优化”的打包器,模板中使用到的那些可选特性,在生成的代码中将通过 ES的模块语法导入;而在打包后的文件中,那些没用到的可选特性就会被“摇掉”。
由于新的虚拟 DOM 实现所带来的提升,我们可以执行一些更加高效的编译耗时优化,如静态树提升(static tree hoisting)、静态属性提升(static props hoisting);以及为运行时提供一些来自编译器的提示,以此避开子组件的规范过程 (children normalization);提供VNode 快速创建路径等等。
解析器重写,以便在对模板进行编译发生错误时,可以提供错误发生的位置信息;除此之外还可以带来对模板的 source map支持;还可以支持第三方工具如 eslint-plugin-vue 和 IDE 的语言服务 (language services) 特性。
IE 11兼容
新的代码库目前只针对主流浏览器,而且我们假定他们都支持 ES2015。但是,哎,我们也知道在可预见的未来还有很多用户仍然需要支持 IE11。除了 Proxy 外,大多数 ES2015 的特性都可以用转译或者垫片的方式在 IE11 中使用。我们的计划是另外单独实现一个具有同样 API 的替代性 observer,不过是基于老式的 Object.defineProperty API;然后再通过单独构建一个使用这个实现的 Vue 3.x 版本 (build) 进行发布,不过这个单独的版本还是会有 Vue 2.x 在变动探测方面所存在的问题,所以它其实并不是一个完全兼容 3.x 的一个版本。我们也意识到这会给第三方库的作者们带来某些不便,因为他们需要考虑两个不同版本之间的兼容性问题,不过当我们真的推进到那个阶段时,那时我们肯定会确保提供一份清晰的指导。
当然,Vue 3.0还处于开发阶段,最早发布也会等到2019年了,让我们拭目以待吧。
vue-cli 3.0
vue-cli 是 vue 官方团队推出的一款快速开发 vue 项目的构建工具,具有开箱即用并且提供简洁的自定义配置等功能。 vue-cli 从 2.0 到 3.0 修改了众多的东西,下面就让我们来了解下。
创建项目
从vue-cli 3.0开始,vue的安装命令从vue-cli 改成了 @vue/cli。例如:
npm install -g @vue/cli
使用vue-cli 3.0创建项目的命令如下:
vue create my-project
除了命令创建外,3.0还增加了图形化界面创建以及管理vue项目的功能, 在创建新项目时还可以混合选用多种集成。当我们使用vue ui命令后即可使用图形化的方式来操作vue项目的源码。
需要说明的是,在初始化项目时系统会默认生成package.json和package-lock.json两个配置文件,它们的区别在于package.json只能锁定大版本号,而package-lock.json则能锁定安装时包的版本号,以保证多人开发时项目版本号的一致。同时,Vue在3.0版本删除了static目录,并新增了public目录,该目录主要用于存放不被webpack处理的文件和资源。
当我们使用create命令创建项目时,系统会要求我们选择一些东西。例如:
Vue CLI v3.0.3 ? Please pick a preset: default (babel, eslint) > Manually select features
Vue 3.0 版本支持预设配置 和 用户自定义配置,其中自定义功能配置包括以下功能:
TypeScript
Progressive Web App (PWA) Support
Router
Vuex
CSS Pre-processors
Linter / Formatter
Unit Testing
E2E Testing
可以发现,3.0 版本新加入了 TypeScript 以及 PWA 的支持。
1,在选择 CSS 预处理器后会提示选择哪一种预处理器?
Scss/Sass
Less
Stylus
2,eslint 规范的选择
ESLint with error prevention only
ESLint + Airbnb config
ESLint + Standard config
ESLint + Prettier
3,选择 Babel,PostCSS,ESLint 等自定义配置的存放位置
In dedicated config files
In package.json
目录结构
相比于Vue 2.0版本来说,Vue 3.0的目录结构则简洁很多,下面是Vue项目文件的具体含义及其作用说明。 * node_modules:项目依赖的第三方模块; * public:移除static目录,新增public目录,并且 index.html 移动到 public 中,该目录主要用于存放如图片、字体等静态资源和打包后的文件; * src:源码存放目录,主要可以存放的有assets资源文件和源代码; * babelrc:将es6代码转换成浏览器能够识别的代码; * editorconfig:定义项目编码规范,优先级高于编译器设置的优先级; * index.html:项目入口文件,可以配置meta 信息或统计代码等; * package.json:项目配置文件,该文件主要定义了项目所需要的各种依赖模块和项目的一些配置信息; * package-lock.json:锁定安装时包的版本号,多人协作开发会用到; * webpack.config.js:webpack模块化打包的一些配置;
自定义配置
从 3.0 版本开始,系统会在项目的根目录生成一个 vue.config.js 文件,可以在此文件中添加自定义的一些配置。下面是一些常用的自定义配置:
module.exports = { baseUrl: '/', outputDir: 'dist', lintOnSave: true, compiler: false, // 调整内部的 webpack 配置。 // 查阅 https://github.com/vuejs/vue-doc-zh-cn/vue-cli/webpack.md chainWebpack: () => {}, configureWebpack: () => {}, // 配置 webpack-dev-server 行为。 devServer: { open: process.platform === 'darwin', host: '0.0.0.0', port: 8080, https: false, hotOnly: false, // 查阅 https://github.com/vuejs/vue-doc-zh-cn/vue-cli/cli-service.md#配置代理 proxy: null, // string | Object before: app => {} } ....}
调整 webpack 配置最简单的方式就是在vue.config.js中的configureWebpack选项提供一个对象,该对象将会被webpack-merge合并入最终的 webpack 配置。例如:
module.exports = { configureWebpack: { plugins: [ new MyAwesomeWebpackPlugin() ] } }
如果想要修改插件选项的参数,读者可以阅读webpack-chain 的 API 获取更多相关的一些源码。例如:
// vue.config.jsmodule.exports = { chainWebpack: config => { config .plugin('html') .tap(args => { return [/* new args to pass to html-webpack-plugin's constructor */] }) } }
需要说明的是,当我们更改一个 webpack 配置的时候,可以通过vue inspect > output.js
输出完整的配置清单,注意它输出的并不是一个有效的 webpack 配置文件,而是一个用于审查的被序列化的格式。
ESLint、Babel、browserslist
Babel 可以通过.babelrc 或 package.json 中的 babel 字段进行配置。
ESLint 可以通过.eslintrc 或 package.json 中的 eslintConfig 字段进行配置。
package.json 中的 browserslist 字段指定了该项目的目标浏览器支持范围。
browserslist
我们可以在package.json配置文件中看到browserslist字段。例如:
> 1% last 2 versionsnot ie <= 8
使用 npx browserslist 可以查看项目的浏览器兼容情况,vue的支持情况如下表:
public目录
vue 约定public/index.html作为入口模板会通过html-webpack-plugin插件处理。在构建过程中,资源链接将会自动注入其中。除此之外,vue-cli 也自动注入资源提示(preload/prefetch),在启用 PWA 插件时注入manifest/icon/链接,并引入(inlines) webpack runtime / chunk manifest清单已获得最佳性能。
在 JavaScript 或者 SCSS 中通过 相对路径 引用的资源会经过 webpack 处理,放置在 public 文件夹的资源可以通过绝对路径引用,这些资源将会被复制,而不经过 webpack 处理。
并且,图片最好使用相对路径经过 webpack 处理,这样可以避免很多因为修改网站根目录导致的图片404问题。
新增功能
除此之外,Vue-cli还带来了两个比较有诱惑力的功能:对TypeScript和PWA的支持;
TypeScript 支持
从 3.0 版本开始中,系统选择启用 TypeScript 语法,从而大大的简化了代码,不过也带来了一些书写上的约束。例如:
import { Component, Emit, Inject, Model, Prop, Provide, Vue, Watch } from 'vue-property-decorator'const s = Symbol('baz')@Componentexport class MyComponent extends Vue { @Emit() addToCount(n: number){ this.count += n } @Emit('reset') resetCount(){ this.count = 0 } @Inject() foo: string @Inject('bar') bar: string @Inject(s) baz: string @Model('change') checked: boolean @Prop() propA: number @Prop({ default: 'default value' }) propB: string @Prop([String, Boolean]) propC: string | boolean @Provide() foo = 'foo' @Provide('bar') baz = 'bar' @Watch('child') onChildChanged(val: string, oldVal: string) { } @Watch('person', { immediate: true, deep: true }) onPersonChanged(val: Person, oldVal: Person) { } }
上面的代码等价于下面的代码:
const s = Symbol('baz') export const MyComponent = Vue.extend({ name: 'MyComponent', inject: { foo: 'foo', bar: 'bar', [s]: s }, model: { prop: 'checked', event: 'change' }, props: { checked: Boolean, propA: Number, propB: { type: String, default: 'default value' }, propC: [String, Boolean], }, data () { return { foo: 'foo', baz: 'bar' } }, provide () { return { foo: this.foo, bar: this.baz } }, methods: { addToCount(n){ this.count += n this.$emit("add-to-count", n) }, resetCount(){ this.count = 0 this.$emit("reset") }, onChildChanged(val, oldVal) { }, onPersonChanged(val, oldVal) { } }, watch: { 'child': { handler: 'onChildChanged', immediate: false, deep: false }, 'person': { handler: 'onPersonChanged', immediate: true, deep: true } } })
可以发现,使用TypeScript语法后,代码大为精简。
PWA 支持
当我们选择启用 PWA 功能时,在打包生成的代码时会默认生成 service-worker.js 和 manifest.json 相关文件。熟悉PWA的同学都知道service-worker.js 和 manifest.json 是PWA的重要配置文件。如果读者还不了解 PWA,点击 PWA官方文档 查看。
默认情况 service-worker 采用的是 precache,可以通过配置 pwa.workboxPluginMode 自定义缓存策略。例如:
module.exports = { // ...其它 vue-cli 插件选项... pwa: { workboxPluginMode: 'InjectManifest', workboxOptions: { // swSrc 中 InjectManifest 模式下是必填的。 swSrc: 'dev/sw.js', // ...其它 Workbox 选项... }, }, };
vue-cli 致力于将 Vue 生态中的工具基础标准化,并确保各种构建工具能够基于智能的默认配置即可平衡衔接,提高开发效率。虽然,vue 3.0还处于开发阶段,不过相信在不久的将来一定会给开发者带来惊喜,让我们拭目以待吧。
参考: http://www.php.cn/js-tutorial-400475.html https://github.com/vuejs/vue-cli/
https://github.com/vuejs/vue-cli/blob/dev/docs/README.md
单手撸了个springboot+mybatis+druid
【摘要】 本文旨在用最通俗的语言讲述最枯燥的基本知识最近身边的程序员掀起了学习springboot的热潮,说什么学会了springboot在大街上就可以横着走、什么有了springboot妈妈再也不担心我的编程了、什么BAT都喜欢的框架...听得作者那个心痒痒的,于是找了个时间,下载了个idea来玩一波springboot,对了...用springboot最好用idea,如果你还在用eclipse,删...
本文旨在用最通俗的语言讲述最枯燥的基本知识
最近身边的程序员掀起了学习springboot的热潮,说什么学会了springboot在大街上就可以横着走、什么有了springboot妈妈再也不担心我的编程了、什么BAT都喜欢的框架...听得作者那个心痒痒的,于是找了个时间,下载了个idea来玩一波springboot,对了...用springboot最好用idea,如果你还在用eclipse,删了吧。
在这里解释一下为什么是springboot+mybatis+druid,是因为作者认为但凡任何一个有灵魂的项目,都少不了数据库,作者不喜欢用JPA那种混SQL的语法,因此选了mybatis,而Druid是阿里系(真香~)的一种数据库连接池框架,在上一个项目作者用的屡试不爽,因此打算继续用,为啥屡试不爽?看文末吧。
文章提纲: 1. 创建springboot工程 2. 配置pom.xml 3. 配置数据源 4. 设置mybatis 5. hello world 6. 设置Druid监控配置
1. 创建springboot工程
只要你有idea,创建一个springboot工程,就跟捏死一个蚂蚁一样简单,因为idea里深度集成了对springboot项目的支持,你直接不停的next到最后,它就会帮你创建出一个springboot工程。 1. 首先打开idea->Create New project->选择项目类型:这里选择spring initializr,然后next。
创建项目,填写项目名称,注意:不要能驼峰写法,可以用中横线,填写完毕后继续next。
选择依赖,所谓依赖就是你在设计这个项目的框架时,分析这个项目需要用到哪些jar或者组件,比如缓存要用到Redis,数据库要用到MySQL等...这里因为演示项目,就不选择太多其它乱七八糟的依赖了。
选好依赖之后,又是一路狂点next,直到最后finish一下,一个springboot项目就创建好了。
2. 配置pom.xml
想想,我们需要哪些jar? 数据库要用到mybatis,数据库连接池要用到Druid、MySQL桥接器要用到mysql-connector,因此要maven仓库(点我去仓库)中找到搜索这些pom加进去。注意,mybatis要用mybatis-spring-boot-starter。
<dependency> <groupid>mysql</groupid> <artifactid>mysql-connector-java</artifactid> <version>5.1.6</version> </dependency> <dependency> <groupid>com.alibaba</groupid> <artifactid>druid</artifactid> <version>1.1.10</version> </dependency> <dependency> <groupid>org.mybatis.spring.boot</groupid> <artifactid>mybatis-spring-boot-starter</artifactid> <version>1.3.2</version> </dependency>
把上面这些pom放到pom.xml的dependencies中细心的老铁会发现,MySQL的version里的内容是红色的,这是什么原因呢? 这是因为我们引入pom时,这些版本的jar在本地maven仓库还没有,而Druid的pom里的version没有显示红色,是因为之前的项目用到了这个版本的Druid,已经被下载到本地Maven仓库里了。 因此我们需要把本地没有的jar下载到本地仓库,右键pom.xml弹出菜单,选择Maven,弹出菜单选择reimport
Reimport过程中再idea底部会有进度条显示,等进度条消失,在观察pom.xml,红色已经消失,说明依赖已经装备完成。
配置数据源
接下来就是要多springboot项目做一个全局配置,默认会在src->main->resource目录下生产空白文件application.properties,作者喜欢用yml因此直接改名成yml即可。 首先是数据源的配置,下面是一份数据源的配置,每个参数的解释都写了注释,因此读者可以直接复制一下内容进去,只需要改一下url、username、password
spring: #profiles: dev messages: basename: i18n/Messages,i18n/Pages datasource: type: com.alibaba.druid.pool.DruidDataSource # 配置当前要使用的数据源的操作类型 driver-class-name: org.gjt.mm.mysql.Driver # 配置MySQL的驱动程序类 url: jdbc:mysql://localhost:3306/wkt_stat # 数据库连接地址 username: root # 数据库用户名 password: root # 数据库连接密码 dbcp2: # 进行数据库连接池的配置 min-idle: 5 # 数据库连接池的最小维持连接数 initial-size: 5 # 初始化提供的连接数 max-total: 5 # 最大的连接数 max-wait-millis: 200 # 等待连接获取的最大超时时间
4. 设置mybatis
继续在application.yml中设置mybatis,mybatis的配置也简单, 主要是为了设置mybatis的配置文件已经mapper文件所在。 1. 首先在resource目录下创建一个mybatis-config.xml文件,文件内容为:
<configuration> <mappers> </mappers></configuration>
在main包中的根目录下创建一个存放mapper实体的资源文件,在resource文件下创建一个文件夹mapper用来存放mapper的xml文件。
配置好资源文件路径之后,就可以在application.yml中加入mybatis的配置了,如下是一个mybatis的配置内容:
#mybatis的mapper配置文件 mybatis: config-location: classpath:mybatis-config.xml # mybatis配置文件所在路径 #mapper-locations: classpath:mapper/*.xml # 所有的mapper映射文件 type-aliases-package: com.becl.dao.mapper # 定义所有操作类的别名所在包 debug: true
最终application.yml的内容如下图:4. 此时需要有一个数据库表来做测试,我们在数据库创建一个表,并且插入一条数据:
CREATE TABLE Memeber ( `id` int(11) NOT NULL AUTO_INCREMENT , `name` varchar(255) NULL , PRIMARY KEY (`id`) ); INSERT INTO memeber VALUES(1,"jas")
在mapper包中创建Memeber的mapper接口:
public interface MemeberMapper { /** * 根据ID获取记录 * @param id * @return */ public Map findObjectById(Integer id); }
在resource中的mapper文件夹创建memberMapper.xml,并且在mapper中增加一个findObjectById的SQL查询语句。
<mapper namespace="com.example.mybatisanddruid.mapper.MemeberMapper">#根据ID查询记录<select id="findObjectById" parametertype="Integer" resulttype="Map"> select * from memeber where id = #{value} </select></mapper>
5. hello world
走到这一步,基本上已经是大功告成了,我们来写一个测试类试试,在根目录创建一个controller的包,在包中创建一个Java类,如下:
@Controller@RequestMapping("/test")public class TestController { @Resource private MemeberMapper memeberMapper=null; @RequestMapping("/one") @ResponseBody public Map testdb(){ return memeberMapper.findObjectById(1); } }
创建完之后,我们运行项目,找到启动类MybatisAndDruidApplication右键run,发现报错,提示没有扫描到mapper包,为什么呢?那是mapper需要手动在启动类中加入:
@MapperScan("com.example.mybatisanddruid.mapper")
这样启动类就变成:
@SpringBootApplication@MapperScan("com.example.mybatisanddruid.mapper")public class MybatisAndDruidApplication { public static void main(String[] args) { SpringApplication.run(MybatisAndDruidApplication.class, args); } }
再次运行,没有报错,在浏览器输入:http://localhost:8888/test/one 输出了ID为1的记录:
{"name":"jas","id":1}
由此可见,springboot-mybatis已经搭建成功,此时有人会问,那Druid呢?
设置Druid监控配置
druid的使用需要做一些配置,现在我们来在根目录下创建一个包config,在config包中间创建一个叫做DruidConfig.java,并且在里写入下面的内容:
@Configurationpublic class DruidConfig { @Bean public ServletRegistrationBean druidServlet() { // 主要实现WEB监控的配置处理 ServletRegistrationBean servletRegistrationBean = new ServletRegistrationBean(new StatViewServlet(), "/druid/*"); // 进行druid监控的配置处理操作 servletRegistrationBean.addInitParameter("allow", "127.0.0.1,192.168.1.159"); // 白名单 servletRegistrationBean.addInitParameter("deny", "192.168.1.200"); // 黑名单 servletRegistrationBean.addInitParameter("loginUsername", "stat"); // 用户名 servletRegistrationBean.addInitParameter("loginPassword", "Wkt_sTat_1031"); // 密码 servletRegistrationBean.addInitParameter("resetEnable", "false"); // 是否可以重置数据源 return servletRegistrationBean ; } @Bean public FilterRegistrationBean filterRegistrationBean() { FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean() ; filterRegistrationBean.setFilter(new WebStatFilter()); filterRegistrationBean.addUrlPatterns("/*"); // 所有请求进行监控处理 filterRegistrationBean.addInitParameter("exclusions", "*.js,*.gif,*.jpg,*.css,/druid/*"); return filterRegistrationBean ; } @Bean @ConfigurationProperties(prefix = "spring.datasource") public DataSource druidDataSource() { return new DruidDataSource(); } }
配置中的内容就不一一细讲, 有兴趣的直接百度一下druid就出来很多答案了,现在重新运行一下项目,运行成功之后,在浏览器中输入:http://localhost:8888/druid 这时候,druid监控平台就出现了
此时我们输入在DruidConfig中设置的loginUsername和loginPassword点击登录,一个完整的druid监控管理平台就呈现在我们啦~
Druid非常强大,在这里你可以查看SQL的执行情况、慢SQL、API请求情况等,根据这些可以做一些性能的调优,至于详细的用法,就靠大家自行学习啦~
如果有老铁需要项目源码,请加我微信:sisi-ceo。
本文转载自异步社区
原文链接:https://www.epubit.com/articleDetails?id=N29ab0be5-f131-4cdb-9d44-367479006490
- 点赞
- 收藏
- 关注作者
评论(0)