前言
在过去的十年时间里,我们的网页变得更加动态化和强大了。多亏有JavaScript,我们已经把很多传统的服务端代码放到了浏览器中,这样就产生了成千上万行的JavaScript代码。它们连接了各式各样的HTML和CSS文件,但缺乏正规的组织形式。这也就是为什么越来越多的开发者使用JavaScript框架诸如Angular、React或Vue这样的。Vue是一款友好的、多用途的且高性能的JavaScript框架。它能够帮助你创建可维护性和可测试性更强的代码库。Vue是渐进式的JavaScript框架,也就是说,如果你已经有一个现成的服务端应用,你可以将Vue作为该应用的一部分嵌入其中,带来更加丰富的交互体验。或者如果你希望将更多的业务逻辑放到前端来实现,那么Vue的核心库及其生态系统也可以满足你的各式需求。和其它前端框架一样,Vue允许将一个网页分割成可复用的组件,每个组件都包含属于自己的HTML、CSS、JavaScript,以用来渲染网页中相应的地方。
如果我们构建一个大型的应用,在这一点上,我们可能需要将东西分割成为各自的组件和文件。Vue甚至有一个命令行工具,使快速初始化一个真实的工程变得非常简单。我们甚至可以使用Vue的单文件组件,它包含了各自的HTML、JavaScript以及带作用域的CSS或SCSS。
1.Vue.js介绍
Vue.js是一款渐进式的JavaScript框架。
什么是渐进式?
渐进式就是指我们可以由浅入深地、由简单到复杂的这种方式去使用Vue.js。
Vue.js优点
①体积小
压缩后33K。
②更高的运行效率
基于虚拟dom,一种可以预先通过JavaScript进行各种计算,把最终的DOM操作计算出来并优化的技术,由于这个DOM操作属于预处理操作,并没有真实的操作DOM,所以叫做虚拟DOM。
③双向数据绑定
让开发者不用再去操作dom对象,把更多的精力投入到业务逻辑上。
④生态丰富、学习成本低
市场上拥有大量成熟、稳定的基于Vue.js的ui框架、常用组件!拿来即用实现快速开发!
对初学者友好、入门容易、学习资料多。
总体而言,Vue.js是一款我们值得去学习和使用的JavaScript框架。
Vue.js经过几年的发展的被广泛的应用于Web端开发、移动端开发、跨平台应用开发等等场景的开发。应该说Vue.js是前端人员开发的必修技能。
Vue.js招聘市场需求大、前景较好。
2.安装与部署
Vue.js的使用方式有很多种。
第一种就是直接使用<script>标签的方式去引入Vue.js。
第二种方式大家可以使用Vue官方提供的CLI这样的一个工具,快速地搭建比较复杂的脚手架。作为初学者来讲我们强烈建议大家先不使用命令行的方式去创建Vue.js的应用。
在官方文档上Vue.js为我们提供了两个版本:一个是开发版本,一个是生产版本。顾名思义,开发的时候我们推荐大家使用开发版本,因为它包含完整的警告和调试信息。生产环境下我们推荐大家使用生产版本去替换开发时使用的开发版本,因为生产版本经过了压缩,更小,而且删除了一些警告信息。
除了使用下载的方式,Vue.js还为我们提供了CDN的方式去引用Vue.js。
3.创建第一个Vue应用
Vue.js的核心是允许采用简洁的模板语法来声明式的将数据渲染进DOM的一套系统。Vue.js可以分为两个重要的组成部分,一个是视图,另外的一个是脚本。
在安装是说过,当我们引入Vue.js的时候,会声明一个全局变量,它的名字叫做Vue。
通过new Vue的方式可以获得一个Vue的应用,它会返回一个对象,这个对象被我们称之为应用对象或者是Vue.js的对象。在new Vue的时候需要注意需要传递一个对象作为参数,这个对象有两个非常重要的属性。分别是el(它代表element,就是元素),可利用选择器的方式选中。第二个重要的属性是data。data用于保存数据,我们在视图中声明的哪些变量,就需要在data里面注册这些变量,并且为变量进行初始化的赋值。
<div id="app">
{{ message }}
</div>
<script type="text/javascript">
var app = new Vue({
el: '#app',
data: {
message: 'Hello Vue!',
name: "Vue"
}
});
</script>
4.数据与方法
每一个Vue其实都是通过Vue函数创建一个Vue实例开始的。通常我们会使用一个变量来接收Vue函数被new之后的一个结果,其实它就是Vue的对象。虽然Vue没有完全遵守MVVM的模型,但是Vue的设计也受到了它的启发。所以我们在开发中,经常会使用vm(ViewModel的缩写)来代表一个Vue的实例。
// 我们的数据对象
var data = { a: 1 }
// 该对象被加入到一个 Vue 实例中
var vm = new Vue({
data: data
})
当一个Vue实例被创建时,它将data中所有的属性加入到Vue的响应式系统中。当这些属性的值发生改变时,视图将会产生“响应”。
如果我们想让某一个属性或某一个变量能够响应式的,那么我们需要在new Vue的时候把这个变量提前地进行声明。还有Object.freeze()这样的一个方法它会阻止修改现有的属性就意味着相应系统无法再去进行追踪变化。我们再用Vue的时候,大部分的情况下,用它的响应式。如果大家想让某一个对象不再进行响应式,我们可以使用freeze()这样的一个方法。
Vue除了数据属性还暴露了一些有用的实例属性和方法。它们都使用dollar符作前缀,以便与用户定义的属性区分。
watch()是一个非常常用且非常有用的方法。watch它直译的话就是观察,它可以观察一个变量的变化,并且能够为我们获取变化之前和变化之后的结果。
语法格式:Vue对象.$watch('观察的变量',function(newVal, oldVal){…})
5.生命周期
每个 Vue 实例在被创建时都要经过一系列的初始化过程,不如说需要设置数据监听、编译模板、将实例挂载到 DOM 并在数据变化时更新 DOM 等等。同时在这个过程中也会运行一些叫做生命周期钩子的函数,这样子的话给开发者在不同阶段带来了一些添加自己的代码的机会。
生命周期钩子需要写在new Vue的时候传递的这个对象内,以属性的方式进行声明,这个属性的话,它是一个函数。那么在Vue的应用运行的每个阶段,系统会自动调用这样子的一个已声明的生命周期函数。还需要注意的是,生命周期函数不能使用箭头函数。箭头函数是没有this的,而这个this的话在我们的生命周期过程中,我们需要对它频繁进行应用的,所以我们在生命周期的函数内不能够使用箭头函数。
常用的生命周期:
①beforeCreate:实例化之后,数据观测和事件配置之前被调用。可以简单地理解,整个页面创建之前,才调用的一个生命周期。
②created:在实例创建之后被调用,在这一步,实例已经完成以下配置:数据观测,属性和方法的运算,watch/event事件回调。
③beforeMount:在挂载开始之前被调用的一个生命周期函数。它开始于挂载之前,相当于准备挂载的状态。
④mounted:它是指挂载成功,就是整个所有的节点被新的Vue的节点所替换。挂载成功之后调用的一个函数。
⑤beforeupdate:数据变化之前被调用的一个函数。
⑥updated:它是指整个的数据已经更新完毕,DOM结构也已经更新了,会调用这个生命周期函数。
setTimeout(function(){…},3000):3秒钟之后将执行这个函数。然后会去执行一个之前。beforeupdate和updated这样的生命周期函数。
var vm = new Vue({
el: "#app",
data: {
msg: "hi vue"
},
beforeCreate: function(){
console.log('beforeCreate');
},
created: function(){
console.log('created');
},
beforeMount: function(){
console.log('beforeMount');
},
mounted: function(){
console.log('mounted');
},
beforeUpdate: function(){
console.log('beforeUpdate');
},
updated: function(){
console.log('updated');
}
});
setTimeout(function(){
vm.msg = "change";
},3000);
其它的生命周期函数:
①activated:keep-alive组件激活时调用。学到组件的时候会使用到。
②deactivated:keep-alive组件停用时调用。
③beforeDestory:页面或者整个应用被销毁之前。
④destory:页面或者整个应用被销毁之后。
⑤errorCaptured:最近新增的,它是去捕获来自子组件的错误时被调用,去捕获此组件的错误。
6.模板语法
Vue.js使用了基于HTML语法的语法,允许开发者声明式地将DOM绑定至底层Vue实例的数据。所有 Vue.js 的模板都是合法的HTML,所以能被遵循规范的浏览器和HTML解析器所解析。在底层的实现上,Vue 将模板编译成虚拟 DOM 渲染函数。结合响应系统,Vue 能够智能地计算出最少需要重新渲染多少组件,并把 DOM 操作次数减到最少。这也就是说,Vue从2一定层面上提高了整个JS的运行效率。
1)插值
数据绑定最常见的形式就是使用“Mustache”语法左右双大括号的方式包含一个变量的值进行文本插值。那么就是在页面上用左右双大括号的方式包裹一个变量,在data里面声明属性及其取值,就可以完成文本插值的这样的一个动作。
通过使用Vue的v-once指令,还可以执行一次性地插值,当数据改变时,插值处的内容不会更新。
<div id="app" v-once>
{{ msg }}
</div>
<script type="text/javascript">
var app = new Vue({
el: "#app",
data: {
msg: "hi vue",
}
});
</script>
双大括号会将数据解释为普通文本,而非 HTML 代码。为了输出真正的 HTML,你需要使用v-html指令。
<div id="app">
<p v-html="rawHtml"></p>
</div>
<script type="text/javascript">
var app = new Vue({
el: "#app",
data: {
rawHtml: '<span style="color:red">this is should be red.</span>'
}
});
</script>
使用Vue.js如何去为HTML标签绑定属性?
Vue.js为我们提供了bind这样的语法,为HTML标签绑定它所具有的一些属性,使其动态地进行一些变化。
语法:v-bind:属性="值"
<div id="app">
<div v-bind:class="color"></p>
</div>
<script type="text/javascript">
var app = new Vue({
el: "#app",
data: {
color: 'red'
}
});
</script>
<style type="text/css">
.red {
color:red;
font-size:100px;
}
</style>
使用JavaScript表达式
Vue.js完全提供了JavaScript表达式的支持。
例:
{{ number + 1 }}//简单运算
{{ ok ? 'YES' : 'NO' }}//三元运算符
{{ message.split('').reverse().join('') }}//复杂的函数运算
2)指令
指令是带有v-前缀的特殊特性。指令特性的值预期是单个表达式。指令的职责是,当表达式的值改变时,将其产生的连带影响,响应式地作用于 DOM。
<div id="app">
<p v-if="seen">能否看到</p>
</div>
<script type="text/javascript">
var app = new Vue({
el: "#app",
data: {
seen: false;
}
});
</script>
一些指令能够接收一个“参数”,在指令名称之后以冒号表示。例如,v-bind指令可以用于响应式地更新HTML特性。
<div id="app">
<a v-bind:href="url">Vue.js</a>
</div>
<script type="text/javascript">
var app = new Vue({
el: "#app",
data: {
url: "https://cn.vuejs.org/";
}
});
</script>
修饰符是以.指明的特殊后缀,用于指出一个指令应该以特殊方式绑定。
我们还没有学到点击事件,可以先使用@click这样的指令可以为某一个元素绑定对应的点击事件。在初始化Vue对象时,我们使用methods这样的一个属性。在这个属性的内部,使用键值对的方式去声明对应的方法以及方法的函数体。
父子元素均有点击事件,若点击子元素不想让父元素的点击事件触发,加上.stop就可以了。
<div id="app">
<div @click="click1">
<div @click.stop="click2">
click me
</div>
</div>
</div>
<script type="text/javascript">
var app = new Vue({
el: "#app",
data: {
},
methods: {
click1: function() {
console.log('click1');
},
click2: function() {
console.log('click2');
},
}
});
</script>
7.class与style绑定
绑定HTML class
我们可以传给v-bind:class一个对象,以动态地切换class。
你可以在对象中传入更多字段来动态切换多个class。此外,v-bind:class 指令也可以与普通的class特性共存。
<div id="app">
<div
class="test"
v-bind:class="{active: isActive,green: isGreen}"
style="width: 200px; height: 200px; text-align: center; line-height: 200px;">
hi vue
</div>
</div>
<script type="text/javascript">
var app = new Vue({
el: "#app",
data: {
isActive: true;
isGreen: true;
}
});
</script>
<style>
.test{font-size: 30px;}
.green{color: #00FF00;}
.active{background: #FF0000;}
</style>
v-bind:class语法还支持数组形式,可以通过三元运算的方式为某一个样式进行具体的赋值。我们用三元运算进行具体的判断,如果不为真就绑定空样式。
<div id="app">
<div
class="test"
v-bind:class="[isActive ? 'active' : ' ', isGreen ? 'green' : ' ']"
style="width: 200px; height: 200px; text-align: center; line-height: 200px;">
hi vue
</div>
</div>
<script type="text/javascript">
var app = new Vue({
el: "#app",
data: {
isActive: true;
isGreen: true;
}
});
</script>
<style>
.test{font-size: 30px;}
.green{color: #00FF00;}
.active{background: #FF0000;}
</style>
绑定内联样式
通过v-bind:style语法可以为HTML标签动态的绑定style。
在通过v-bind:style指令为元素绑定样式的时候,我们还可以使用三元运算进行动态的样式绑定。
<div id="app">
<div
:style="{color: color, fontSize: size, background: isRed ? '#FF0000' : ' '}">
hi vue
</div>
</div>
<script type="text/javascript">
var app = new Vue({
el: "#app",
data: {
color: "#000000",
size:'50px',
isRed: true
}
});
</script>
8.条件渲染
指令用于条件性地渲染一块内容。这块内容只有在表达式返回真的时候才会被渲染。
Vue.js在2.1.0版本之后,新增了v-else-if,与平时学过的JavaScript语法是一致的。
<div id="app">
<div v-if="type === 'A' ">
A
</div>
<div v-else-if="type === 'B' ">
B
</div>
<div v-else-if="type === 'C' ">
C
</div>
<div v-else>
Not A/B/C
</div>
</div>
<script type="text/javascript">
var app = new Vue({
el: "#app",
data: {
type: "B"
}
});
</script>
Vue.js还提供了v-show指令,这个指令用于根据条件展示某一个元素v-show的元素始终会被渲染并保留在 DOM中。v-show只是简单地切换元素的CSS属性的display。
<div id="app">
<h1 v-show="ok">Hello!</h1>
</div>
<script type="text/javascript">
var app = new Vue({
el: "#app",
data: {
ok: false
}
});
</script>
v-show和v-if的区别是,v-if是“真正”的条件渲染。v-if也是惰性的,如果它的条件不满足,它是不会渲染的。相比之下,v-show就简单很多,不管是什么条件,它都将元素先渲染到页面上,然后通过CSS进行这种隐藏和展示的切换。一般来说,v-if有更高的切换开销,而 v-show 有更高的初始化开销。因此,如果需要非常频繁地切换,则使用v-show比较好;如果在运行条件很少改变时,则使用v-if比较好的。
9.列表渲染
首先来看数组形式的列表渲染,我们可以用v-for指令基于一个数组来渲染一个列表。v-for指令需要使用item in items形式的特殊语法,其中items代表的是源数据数组,而item则是被迭代的数组元素的别名。
在列表渲染的过程中,我们需要注意Vue正在更新使用 v-for 渲染的元素列表时,它默认使用“就地更新”的策略。如果数据项的顺序被改变,Vue将不会移动DOM元素来匹配数据的顺序,这种模式本身是高效的,但它只适用于不依赖子组件状态或者是临时DOM状态。为了给Vue一个提示,以便它能跟踪每个节点的身份,从而重用和重新排序现有元素,你需要为每项提供一个唯一key属性。
<div id="app">
<ul>
<li v-for="item,index in items" :key="index">
{{ index }}{{ item.message }}
</li>
</ul>
<ul>
<li v-for="value,key in object" :key="key">
{{ key }} : {{ value }}
</li>
</ul>
</div>
<script type="text/javascript">
var app = new Vue({
el: "#app",
data: {
items: [
{ message: 'Foo' },
{ message: 'Bar' }
],
object: {
title: 'How to do lists in Vue',
author: 'Jane Doe',
pulishedAt: '2016-04-10'
}
}
});
</script>
10.事件绑定
可以用v-on指令监听DOM事件,并在触发时运行一些JavaScript代码。
然而许多事件处理逻辑会更为复杂,所以直接把JavaScript代码写在v-on指令中是不可行的。因此v-on还可以接收一个需要调用的方法名称。
<div id="app">
<div id="example">
<button v-on:click="counter += 1">数值:{{ counter }}</button><br/>
<button v-on:click="greet('abc',$event)">Greet</button>
</div>
</div>
<script type="text/javascript">
var app = new Vue({
el: "#app",
data: {
counter: 0;
},
methods: {
greet: function(str, e) {
alert(str);
console.log(e);
}
}
});
</script>
v-on指令可以绑定HTML元素拥有的所有的事件。
常见的Vue.js事件修饰符:.stop、.prevent、.capture、.self、.once、.passive
11.表单输入绑定
我们可以使用v-model指令在表单<input>、<textarea>及<select>元素上创建双向数据绑定。它会根据控件类型自动选取正确的方法来更新元素。v-model在内部为不同的输入元素使用不同的属性并抛出不同的事件:
- text和textarea元素使用 value属性和input事件。
- checkbox和radio使用checked属性和change事件。
- select字段将value和change事件。
使用了双向绑定之后,如何对表单元素的默认值进行操作,通过改变data对象的属性来完成表单元素默认值的设置。
完成表单提交的工作:当表单元素的值发生变化的时候,我们在data对象的对应属性内都可以收集到这些表单元素对应的值,我们可以在页面上创建一个提交按钮,为它绑定点击事件。为它绑定好点击事件后,我们可以通过this对象获取到每一个表单元素的值。我们可以声明一个对象形式的变量,将表单所有元素的值收集下来。有了这样的一个变量,我们就可以利用它来进行表单的提交工作了。
<div id="app">
<div id="example">
<input v-model="message" placeholder="edit me">
<p>Message is: {{ message }}</p>
<textarea v-model="message2" placeholder="add multiple lines"></textarea>
<p style="white-space: pre-line;">{{ message2 }}</p>
<br/>
<div style="margin-top: 20px">
<input type="checkbox" id="jack" value="Jack" v-model="checkedNames">
<label for="jack">Jack</label>
<input type="checkbox" id="john" value="John" v-model="checkedNames">
<label for="john">John</label>
<input type="checkbox" id="mike" value="Mike" v-model="checkedNames">
<label for="Mike">Jack</label>
<br>
<span>Checked names: {{ checkedNames }}</span>
</div>
<div style="margin-top: 20px">
<input type="radio" id="one" value="One" v-model="picked">
<label for="one">One</label>
<input type="radio" id="two" value="Two" v-model="picked">
<label for="two">Two</label>
<br>
<span>Picked: {{ picked }}</span>
</div>
</div>
</div>
<script type="text/javascript">
var app = new Vue({
el: "#app",
data: {
message: "test",
message2: "hi",
checkedNames: ['Jack', 'John'],
picked: "Two"
},
methods: {
submit: function() {
var postObj = {
msg1: this.message,
msg2: this.message2,
checkval: this.checkedNames
};
console.log(postObj);
}
}
});
</script>
12.组件基础
组件是可复用的Vue实例,在开发过程中我们把经常重复的功能封装为组件,达到快捷、便捷开发的目的。Vue.js使用Vue.compoment函数去创建一个组件。compoment函数的第一个参数是组件的名称,第二个参数以对象的形式去描述一个组件。因为组件是可复用的Vue实例,所以它们与new Vue接收相同的选项。
可以使用HTML标签的方式对组件进行调用,标签的名称就是组件的名称。组件也是可以复用的,每个组件的数据是封闭在组件内部的,相互并没有影响。还可以通过props为组件定义属性,我们可以在模板内对此属性进行应用和渲染。我们在调用组件可以通过组件的属性为这个属性进行赋值。
创建一个属性我们需要注意一个组件的模板需要一个根节点。
组件的事件监听:可以通过this对象的emit方法去触发一个事件,它的第一个参数是事件名称,第二个参数是可携带的一些参数。在组件父级可以通过事件绑定的方式去接收到emit函数触发的事件。
在模板内我们可以通过slot标签声明一个组件的插槽,通过插槽我们可以插入任意的HTML内容及标签,在组件的内部我们可以插入一些自定义的标签及内容。
<div id="app">
<button-counter title="title1:" @clicknow="clicknow">
<h2>hi</h2>
</button-counter>
<button-counter title="title2:"></button-counter>
</div>
<script type="text/javascript">
Vue.component('button-counter', {
props: ['title'],
data: function() {
return {
count: 0
}
},
template: '<div><h1>hi</hi><button v-on:click="clickfun">{{ title }} You clicked me {{ count }} times.</button><slot></slot></div>',
methods: {
clickfun: function() {
this.count ++;
this.$emit('clicknow', this.count);
}
}
})
var app = new Vue({
el: "#app",
data: {
},
methods: {
clicknow: function(e) {
console.log(e);
}
}
});
</script>
13.组件注册
我们已经知道通过Vue.compoment函数可以在页面上声明并创建一个Vue.js的组件。Vue.compoment函数的第一个参数被称之为组件名,被定义的方式有两种,第一种可以通过短横线的方式分割命名,第二种方式我们可以使用驼峰法对组件进行命名。
我们通过Vue.compoment函数来创建的组件,这些组件都是全局注册的,也就是说,它们在注册之后可以在任何新创建的Vue根实例模板中进行应用。
Vue.js还提供了局部注册机制,因为全局注册往往是不够理想的。全局注册往往是不够理想的。比如,如果你使用一个像webpack这样的构建系统,全局注册所有的组件意味着即便你已经不再使用一个组件了,它仍然会被包含在你最终的构建结果中。这造成了用户下载的JavaScript资源的无谓增加。通过局部注册可以解决这样的问题。
如果想实现局部注册,我们需要在对Vue函数进行初始化的时候,也就是创建Vue对象的时候,在Vue函数的一个参数,这个参数是对象形式的,在这个对象内去声明一个compoments属性。声明好compoments这样的属性之后,我们就可以在它的内部进行组件的局部注册。
<div id="app">
<test></test>
</div>
<script type="text/javascript">
var app = new Vue({
el: "#app",
data: {
},
components: {
test: {
template:"<h2>h2</h2>"
}
}
});
</script>
Vue.js还支持在模块系统中进行组件的局部注册,比如使用webpack这样的模块系统,我们就可以使用import组件名称、from组件位置的方式去引入一个组件。然后在Vue对象内部通过compoments这样的属性进行组件的局部注册。
14.单文件注册
很多Vue项目中,我们使用Vue.component函数来定义全局组件,这种方式在很多中小规模的项目中运作是没有问题的,但是在稍微复杂的项目中会有以下几个比较明显的缺点:
- 全局定义强制要求每个component中的命名不得重复。
- 字符串模板 (String templates) 缺乏语法高亮支持。
- 不支持CSS。
- 没有构建步骤。
而单文件组件为上面所有问题提供了解决方法,还提供了webpack或者Browserify等构建工具。
为了使用Vue.js的单文件组件,我们需要安装以下环境:
①安装 npm
npm全称为Node Package Manager,是一个基于Node.js的包管理器,也是整个Node.js社区最流行、支持的第三方模块最多的包管理器。
npm -v
②由于网络原因,安装 cnpm
npm install -g cnpm --registry=https://registry.npm.taobao.org
③安装 vue-cli
cnpm install -g @vue/cli
④安装 webpack
cnpm install -g webpack
webpack是JavaScript打包器(module bundler)
创建好的项目的目录结构:
①public:打包之后用于部署到生产环境下面的一个目录。
②src:开发的目录。
③scr下的compoments:整个项目的组件目录。
④app.vue:作为整个项目的入口文件去完成了对组件的引入工作。(可以用import的方式去引入,在页面上通过compoments局部注册并使用)
单文件组件的组成:
①template:模板、试图区域
②script:脚本区域
③style:样式区域
完整的描绘了HTML开发必须的三个点:DOM结构、JavaScript脚本、CSS样式。
例:自定义的vue组件
<template>
<h2>test {{ msg }}</h2>
</template>
<script>
export default {
name: 'HelloWorld',
props: {
msg: {
type: String,
default: "test msg"
}
},
methods: {
},
data() {
return {
key:value
}
},
}
</script>
<style>
.red{color: #FF0000;}
</style>
15.免终端开发Vue应用
cli方式
cli是命令行,一个黑色的终端窗体,在里面敲命令行。这要求开发者需要理解终端、node、npm等很多知识,不然在以下方面会困难重重:
①搭建项目环境。
②运行和发布项目。
③配置less/sass/typescript/babel等预编译器。
④安装各种流行的组件库。
使用uni-app+HBuilder x
uni-app和HBuilder都是DCloud公司出品,前者是框架,后者是ide,它们互相搭配,使得基于Vue.js开发项目变得更简单和高效!让开发者把更多精力放在业务逻辑上。
网友评论