Vue|Vue 学习归纳
一、简介
Vue (读音 /vju?/,类似于 view) 是一套用于构建用户界面的渐进式框架。与其它大型框架不同的是,Vue 被设计为可以自底向上逐层应用。Vue 的核心库只关注视图层,易于上手。
Vue 有个特点是响应式,当数据发生变化时,视图会自动响应,元素会匹配新的数据。
在 JS 中,需要text = "hello world";
document.getElementById("id").innerHTML = text;
才能改变元素的值;
而 Vue 中,只需要text = "hello world"
,元素的值就会自动改变。
参考了Vue教程和Vue API。
二、使用 Vue
- 使用html
需要先使用引入Vue,再在之后的
中使用
new Vue()
创建 Vue。
el: "#div"
表示将 Vue 挂载到id = "div"
的元素上。- 使用 main.js
先使用npm install vue
下载 Vue,在 main.js 中使用new Vue()
初始化。
import Vue from 'vue'
import App from './App.vue'new Vue({
el: "#app",
render: h => h(App)
})
App.vue
是主页面,render: h => h(App)
表示用主页面来渲染 Vue,el: "#app"
表示将该 Vue 挂载到id="app"
的元素上,该元素一般在 index.html 里。注:通常使用第二种方式创建 Vue,界面代码写在
.vue
文件中,通过 Vue Router 跳转界面。- 使用.vue文件
.vue
文件叫做单文件组件,
中为 html 语句。要在 div 中写界面代码,不然会报错,因为每个组件必须只有一个根元素。
中为 JS 语句,export default { }
中为 Vue 语句。
中为 CSS 语句,通常添加scoped="scoped"
,表示样式只在当前组件中生效。注:后面的介绍语法都是在单文件组件使用的,而不是官方教程那样在 html 中使用。
三、模板语法
1、修改文本
使用
{{ }}
为一个元素添加动态的内容。里面是一个变量,变量为data
选项中的key。{{ name }}
- 表达式
{{ }}
里面可以使用变量,也可以使用表达式。实际上,变量也是表达式。
算术表达式,如{{ name + "lisi" }}
。
三元表达式,如{{ isOk ? "zhangsan" : "lisi" }}
,isOk
是一个值为布尔的变量。
函数表达式,如{{ name.toUpperCase() }}
。 - v-text
可使用v-text
指令来代替{{ }}
插值的功能,如相当于
{{ name }}
。 - v-once
因为 Vue 的响应式,当变量name
的值发生改变时,div 的内容会自动改变;
若不想自动改变,可使用v-once
指令,如{{ name }}
。
使用v-once
指令后元素/组件及其子元素/组件只会渲染一次。 - v-html
变量的值通常是字符串、数字等,若想使用 html 语句,可使用v-html
指令。
b {
color: red;
}
修改了 DOM 中的
element.innerHTML
。此时相当于20
。注:scoped的样式不能应用于
v-html
指令中的元素。如上面的 b 元素字体不会变为红色。- 响应式数据
写在data
选项中的数据就是响应式数据,选项是一个对象或返回对象的函数,可通过this.$data
获取该对象。
因为使用的是单文件组件,所以选项必须使用函数。
插值时必须使用响应式数据,其它全局变量无效。
使用this.$data.age
获取数据,因为 Vue 实例代理了data
选项中的所有变量,所以可使用this.age
获取数据。
有前缀_
和$
的变量不会被 Vue 实例代理,所以只能使用this.$data._age
获取数据。- 新增响应式数据
若有一个响应式数据info: { title: "hello" }
,当使用this.info.content = "world"
给对象添加一个新键值对时,该键值对并不是响应式的,{{ info.content }}
是没有效果的。
可使用this.$set()
方法为对象新增响应式的键值对,如this.$set(this.info, "content", "world")
,此时{{ info.content }}
才有效果。
$set()
方法有三个参数:- 参数一为一个对象或数组,必须是响应式的。
- 参数二为对象的键或数组的索引。
- 参数三为数据的值。
- 删除响应式数据
使用this.info.title = null
或this.info.title = undefined
删除一个数据。
也可使用this.$delete()
方法删除数据,能够保证 Vue 知道某数据被删除。
方法有两个参数,与$set()
方法的前两个参数相同。
- 新增响应式数据
- 修改属性
在 html 中,通常元素的属性会赋值为字符串。使用v-bind
指令,可为属性绑定一个表达式。
{{ adress }}
鼠标指着cd时
文章图片
v-bind
指令可简写成
:
,如
{{ adress }}
。
- 指令
指令(Directives)是带有v-
前缀的特殊属性,如v-bind
。
指令的值通常是一个表达式,除了v-for
,如v-bind:title="detailAderss"
后面的detailAderss
。
指令也有参数,在:
后面,如v-bind:title="detailAderss"
后面的title
就是指令的参数。
查看全部指令。
- 动态参数
使用[]
为指令绑定一个变量,变量的值即为指令的参数。
{{ adress }}
此时相当于
{{ adress }}
。指令参数的值通常是一个字符串,值为
null
则可以被显性地用于移除绑定。- 修饰符
使用.
为指令添加一个修饰符,修饰符用于指出指令应该实现某个功能,如v-on:click.prevent=""
。.prevent
修饰符的作用是让事件对象调用event.preventDefault()
。
可同时添加多个修饰符,如v-on:click.prevent.once=""
。
不同的指令有不同的修饰符,查看v-on修饰符。
- 绑定事件
在 html 中,使用来绑定 DOM 事件。
在 Vue 中,使用v-on
指令绑定 DOM 事件,如。
- 要注意的是,要删除原事件前面的
on
,如onclick -> click
。 - 当表达式是一个函数调用时,在 html 中要使用
()
,如onclick="clickAction()"
。 - 而在 Vue 中可以不用,但当需要传入参数时,则必须添加
()
,如v-on:click="clickAction"、v-on:click="clickAction('a', 'b')"
。 - 函数传入的参数可为
$event
,即为事件对象,如v-on:click="clickAction('a', $event)"
。
v-on
指令可简写成@
,如。
- 要注意的是,要删除原事件前面的
{{ funName }}
方法要写在
methods
选项中,它是一个对象,而每个方法则是对象中的一组键值对。函数有两个写法,如
clickAction: function() { }
、clickAction() { }
。若函数有参数,则写成
clickAction: function(a, b) { }
、clickAction(a, b) { }
。- 箭头函数
函数还有一种写法是箭头函数,如clickAction: () => {}
、clickAction: (a, b) => {}
。
若只有一个参数,可省略()
,如clickAction: a => {}
。
若函数里只有一句代码,可省略{}
,如clickAction: a => alert(a)
。
注:在普通函数中,this
指向 Vue 实例;但在箭头函数中,this
不指向任何值。
- 可使用对象
在函数中,event
对象表示函数的事件对象,this
对象则表示当前的 Vue 实例。
当未传入参数时,函数默认有一个传入参数,值为事件对象。
与 JS 一样,函数中也能使用arguments
对象,arguments[0]
表示传入的第一个参数,arguments[1]
表示传入的第二个参数,以至类推。
- 键盘事件
使用@keydown、@keyup、@keypress
绑定键盘事件,分别为按键按下、按键抬起、按键按下并抬起。
在 JS 中,在函数中使用事件对象的key
或keyCode
属性判断按下了哪一个按键;在 Vue 中,使用修饰符判断按键,如,表示在按下回车键时触发。
- 普通按键
修饰符是事件对象的key
属性的值通过kebab-case方式转换而来的,如Enter->enter、ArrowUp->arrow-up
。
修饰符也可以使用数字,即事件对象的keyCode
属性的值,如@keyup.enter=""
相当于@keyup.13=""
。
Vue 内置了一些修饰符:.enter .tab .delete (删除或退格键) .esc .space .up .down .left .right
。
有些旧浏览器的
key
与keyCode
的对应关系可能与新的不一致,可以使用全局属性Vue.config.keyCodes
修改,如Vue.config.keyCodes.f1 = 112
。- 粘滞键
在 JS 中,通过事件对象的ctrlKey、altKey、shiftKey、metaKey
属性判断是否按下了这几种按键。
在 Vue 中,使用修饰符.ctrl .alt .shift .meta
判断是否按下,如@keyup.shift.enter=""
,表示按下shift+enter时触发。
注:在不同系统中,alt、meta键可能不代表的按键不同,需要具体测试。 - 精准按键
使用修饰符.exact
判断是否精确按下了按钮,如@keyup.shift.enter.exact=""
只有在按下shift+enter时触发,按下shitf+alt+enter时不会触发。
- 【Vue|Vue 学习归纳】鼠标事件
在 JS 中,使用事件对象的button
属性判断哪个鼠标按键被按下,012分别表示左键、中键、右键。
在 Vue 中,使用修饰符.left .right .middle
判断哪个鼠标按键被按下,如@click.right=""
。
- 绑定多个方法
v-on
指令的值可以是一个对象,可用于绑定多个方法,如v-on="{ click: clickAction, dblclick: dblclickAction }"
。
但这种方式不支持修饰符,也不支持给函数传入参数。
模板语法插值时,可向里面传入一个表达式,表达式可为一个变量,可为一个方法,也可为一个计算属性。
{{ name }}
,name
是一个变量,值通常是一个简单的值,如{name: "zhangsan"}
。{{ getName() }}
,getName()
是一个方法,可在函数里实现复杂的运算,最后返回一个值。methods: {
getName: function() {
//一系列运算
return "zhangsan"
}
}
{{ getName1 }}
,getName1
是一个计算属性,也可在里面实现复杂的运算,最后返回一个值。computed: {
getName1: function() {
//一系列运算
return "zhangsan"
}
}
- 计算属性与方法
计算属性与方法实际上都是函数,但方法是写在methods
选项中,而计算属性写在computed
选项中,选项是一个对象。
在调用方法时,每调用一次都会执行一次函数。
在调用计算属性时,只会执行一次函数,再次调用时则使用之前的返回值;若函数中使用的响应式变量发生了变化,才会重新调用一次函数。如computed: { getName1: function() { return this.name.toUpperCase() } }
,只有当name
的值变化时才会重新执行函数。
注:响应式变量指的是data
选项中的变量。
- 何时使用计算属性
计算属性可以节约系统资源,当使用了一个大数组时,使用方法则会每次调用都遍历一次数组,而使用计算属性则只会遍历一次。
- 计算属性的setter
computed: {
fullName: {
// getter
get: function () {
return this.firstName + ' ' + this.lastName
},
// setter
set: function (newValue) {
var names = newValue.split(' ')
this.firstName = names[0]
this.lastName = names[1]
}
}
}
执行
fullName = "Sherlock Holmes"
时会调用set方法,使firstName和lastName变量更新;由于这两变量发生了变化,所以下次使用计算属性fullName
时会重新执行一次函数。六、侦听
- 侦听属性
响应式变量改变时计算属性会重新调用一次函数,这实现了变量的被动监听,但这并不好用。
而使用侦听属性可以实现变量的主动监听。
export default {
data() {
return {
watchProperty: ""
};
},
watch: {
watchProperty: function(val, oldval) {
alert("新值为" + val + ",旧值为" + oldval)
}
}
}
侦听属性需要写在
watch
选项中,选项是一个对象。对象键值对的值可以是一个函数,函数会传入两个参数,参数为变量的新值和旧值。
还可以是字符串、数组、对象,详见watch。
- 实例方法
除了写在watch
选项中,还可以使用实例方法this.$watch()
。
$watch()
一般写在mounted
选项中,选项是一个函数,它会在 Vue 实例被挂载后调用。
$watch()
有三个参数:- 参数一是一个表达式或函数。
- 表达式通常是一个变量,会监听变量值是否发生了变化。若要监听对象中的键值对,可使用表达式
a.b.c
。 - 为函数时,会监听函数的返回值是否发生了变化。
- 表达式通常是一个变量,会监听变量值是否发生了变化。若要监听对象中的键值对,可使用表达式
- 参数二是一个回调函数,会在监听的值发生变化时回调。函数有两个参数,分别为新值与旧值。
- 参数三是一个对象,可使用两个键
deep、immediate
,它们都是布尔值。- 若
deep
为true,当监听一个对象时,对象中任意键值对变化,就能触发回调。为数组时不需这样设置。 - 若
immediate
为true,会立即触发一次回调函数。
- 若
-
$watch()
有一个返回值,返回值是一个函数,调用这个函数能取消监听。
如var unwatch = this.$watch("message", function() {}); unwatch();
。
- 侦听事件
通常,在组件上使用$emit()
触发一个自定义事件,在父组件上使用v-on
指令监听这个事件。详见 十一、组件 -- 3. 事件方法。
那么,在本组件中怎么监听由$emit()
触发的自定义事件呢?可以使用实例方法this.$on()
实现。
title
$on()
一般写在mounted
选项中,选项是一个函数,它会在 Vue 实例被挂载后调用。$on()
有两个参数:- 参数一为一个字符串或数组。
- 字符串为
$emit()
触发的事件名。 - 数组为多个事件名组成的数组。
- 字符串为
- 参数二为回调函数,回调函数会接收所有
$emit()
触发函数的参数。
七、class与style的绑定$on(eventName, eventHandler)
侦听一个事件
$once(eventName, eventHandler)
一次性侦听一个事件,事件名不支持数组。
$off(eventName, eventHandler)
停止侦听一个事件
在 html 中,通过
来绑定元素的 CSS 类名和样式。在 Vue 中,则使用
v-bind
指令动态地绑定类名或样式。- 对象语法
v-bind
指令可为属性绑定一个变量,当属性为class
或style
时,这个变量可以是一个对象。
- 变量写法
- class
,变量classObject为
classObject: { class1: true, class2: true , class3: flase }
。此时相当于。
- style
,变量styleObject为
styleObject: { color: 'red', fontSize: '16px' }
。此时相当于。
在对象中,font-size
要写成驼峰式fontSize
,也可以写成'font-size'
。
- class
- 内联写法
- class
,变量为
enable1: true, enable2: true, enable3: false
。此时也相当于。
- style
,变量为
color: 'red', size: '16px'
。此时也相当于。
font-size
要写成驼峰式fontSize
,也可以写成'font-size'
。
- class
- 使用计算属性
变量不仅可以是一个对象,也可以是计算属性。
变量为计算属性时,可以通过一系列判断后再返回对象。上面的作用是根据
pageIndex
来使用不同的类名。当然,style也可以像上面一样使用计算属性。
- 数组语法
v-bind
指令可为属性绑定一个变量,当属性为class
或style
时,这个变量可以是一个数组。
- 变量写法
,变量classArray为
classArray: ['class1', 'class2']
。此时相当于。
与对象语法一样,变量也可以是一个计算属性,不同点在于返回值是一个数组。 - 内联写法
- class
。
,变量为
className1: "class1", className2: "class2"
。
,变量为
isok1: true, isok2: true
。
上面三种都相当于。
- style
,变量为
colorstyle: { color: 'red' }, fontstyle: { fontSize: '16px' }
,相当于。
font-size
要写成驼峰式fontSize
,也可以写成'font-size'
。
- class
v-bind
指令时,Vue 会在 CSS 属性前自动添加上各种浏览器的前缀。八、条件渲染
- v-if
与 JS 中的if、else if、else
一样,在 Vue 中也能通过指令v-if、v-else-if、v-else
来条件渲染不同的元素。
三个指令的值都是一个表达式,且表达式的结果应该是一个布尔值。
必须按顺序书写,在一组元素中,带有v-else-if
指令的元素可存在零个或多个,带有v-else
指令的元素可存在至多一个。
if
else if
else
当show1为true,渲染第一个div;当show1为false,show2为true,渲染第二个div;当都为false,渲染最后一个div。
- template
当需要条件渲染多个元素时,可以使用 template。
如12
,当 show1 改变时,实际上是切换最外层带有v-if
指令的这个 div,只不过是该div中有两个子div。
若想同时切换多个元素,可将最外层改成 template,如12
,此时实际上是在切换里面的两个div。 - 元素的复用
Vue 会尽可能高效地渲染元素,通常会复用已有元素而不是从头开始渲染。
上面例子的 label 元素和 input 元素在切换时,实际上是修改 label 元素的内容和 input 元素的占位符。
若在输入框中输入了字符串,你会发现在切换时字符串并不会变化。
但这种情况有时并不符合要求。给需要重新渲染的元素设置不同的
key
值,就能解决这个问题。
此时 laebl 元素会复用,input 元素会重新渲染。
- v-show
使用v-show
指令也可以实现条件渲染,如show
。
v-show
指令的值也是一个表达式,表达式的结果是一个布尔值。
结果为true则显示,为false则不显示,实际上是将元素的CSS切换成display: none
。
九、循环渲染v-if
在初始渲染时条件为假时什么也不做;直到条件第一次变为真时,才会开始渲染。v-show
不管初始条件是什么,元素都会被渲染。
v-if
有更高的切换开销,而v-show
有更高的初始渲染开销。因此,如果要频繁地切换,则使用v-show
较好。
v-if
支持 template 元素,而v-show
则不支持。
在 JS 中,使用
for
来循环执行代码;在 Vue 中,可以使用v-for
指令来循环渲染元素。通常,指令的值都是一个表达式,而
v-for
指令的值为alias in expression
。其中expression的值可为数组、对象、数字、字符串、Iterable(详见迭代协议)。
- 在v-for中使用数组
v-for
指令的值为item in items
,items
为data
选项中的变量,是一个数组;item
则是数组的元素,通常是一个对象。
{{item.content}}
v-for
指令的值还可以为"item,index in items"
,index
为元素的索引。in
可以替换成of
,如item of items
、"item,index of items"
- 在v-for中使用对象
v-for
指令的值为value in object
,object
为data
选项中的变量,是一个对象,value
为对象的键值对的值。
v-for
指令的值还可以为value,key in object
和value,key,index in object
,key
为对象的键值对的键,index
为索引。
in
也可以替换成of
。
注:遍历对象时,会按Object.keys()
的结果遍历。 - 在v-for中使用数字
v-for
指令的值为num in 10
,则会重复对应次数。 - 在v-for中使用字符串
v-for
指令的值为charStr in 'string'
,则会重复字符串长度的次数,charStr
为每一个字符。
v-for
指令的值了也可为charStr,index in 'string'
,index为索引值。 - 使用key
当更新使用v-for
指令渲染的元素列表时,它默认使用 就地更新 的策略。如果数据项的顺序被改变,Vue 不会移动 DOM 元素来匹配数据项的顺序,而是就地更新每个元素,并且确保它们在每个索引位置正确渲染。
为了重用和重新排序现有元素,可以给每项提供一个key
属性,如{{item.content}}
。
注:
key
的值应该是一个字符串或数字,并且值不能够重复。
在组件上使用v-for
指令时,key
是必须的。如
。 - 使用template
v-for
指令可以用在 template 元素上,如{{ item.id }}{{ item.content }}
。
同v-if
指令一样,当需要循环渲染多个元素,可以使用 template。 - v-for与v-if
当两个指令同时使用时,如{{item.content}}
。
v-for
指令的优先级比v-if
指令高,即先遍历再判断。
注:Vue 不推荐这两个指令组合使用。
在 html 中,给一个输入框设定初始值,如
。当在输入框修改值后,实际上
value
的值并没有改变。可以监听oninput
事件,在函数使用element.setAttribute()
来改变value
的值。在 Vue 中,使用
v-model
指令来实现双向绑定,实际上也是通过监听输入事件以更新数据。v-model
指令针对不同类型的 input 元素使用不同的值与事件。
text 和 textarea 使用 value 属性和 input 事件;
checkbox 和 radio 使用 checked 属性和 change 事件;
select 使用 value 属性和 input 事件。
- 使用v-model
inputValue
是data
选项中的一个变量,必须设置初始值,即使是一个""
。
checkbox 绑定的值是一个数组或布尔,radio 绑定的值是一个布尔,其他类型绑定的值则是一个字符串。 - 修饰符
text 和 textarea 绑定的值默认在input
事件中更新,使用.lazy
修饰符,使其在change
事件中更新,如。
text 和 textarea 绑定的值默认是字符串,使用.number
修饰符,可以让绑定的值变为数字,如。
使用.trim
修饰符,可以自动去除字符串前后的空格,如。
组件是可复用的 Vue 实例,
.vue
文件就是一个单文件组件。- 使用组件
可使用
import
引入其他的.vue
文件,如组件CustomComponent;也可以在当前文件中直接创建组件,如组件CustomComponent1。组件要写在
components
选项中,选项是一个对象。当对象的键值对的键值相同时,可以省略值,如{ CustomComponent }
相当于{ CustomComponent: CustomComponent }
。使用组件时,可以使用大驼峰
CustomComponent
,也可以使用分隔式Custom-Component
,也可以使用小写分隔式custom-component
,建议使用小写分隔式,如
。若注册组件时就使用的小写分隔式(此时两端要加引号),如
'custom-component2'
,使用时也就只能使用小写分隔式。- 全局组件
上面的组件只能在当前文件中使用,可使用Vue.component('name', {})
注册全局组件。要注意的是,必须写在new Vue({})
之前。
- 组件属性
每个元素都有属性,自定义的组件在props
选项中声明自定义属性,可使用this.$props
获取选项的值。
props
选项中声明的属性可以像data
选项中的变量一样,直接在组件中使用。
{{ title }}{{ content }}
组件的
data
选项必须为一个函数,它返回一个对象。这样可以保证每个组件实例有只属于自己的数据。- 使用属性
通过
使用自定义的属性,当然也可以使用:content=""
为属性绑定一个表达式。
若
,表示content
的值为true。
- v-bind
当组件中声明的属性很多时,如果都使用的话代码就会很长,如
。
使用v-bind
指令可将所有属性集中在一个对象中,如
,变量为datas: { name: "", age: "", adress: "", phone: "" }
。
- sync
上面不管是:content=""
还是v-bind=""
绑定变量时,都是单向的。当组件内的属性值改变时,不会改变父组件变量的值。
若要进行双向绑定,可使用.sync
修饰符,如:content.sync=""
、v-bind.sync=""
。
注:.sync
修饰符只支持变量,不支持表达式。
- 属性命名
自定义的属性通常使用小驼峰命名,在使用时,可使用小驼峰或分隔式,如
、
。
- prop选项的类型
prop
选项可为数组或对象。
- 为数组时,如
props: ['title', 'likes', 'isPublished']
。 - 为对象时,如
props: { title: String, likes: Number, isPublished: Boolean}
。- 对象键值对的值为数据类型,可使用
String、Number、Boolean、Array、Object、Date、Function、Symbol
。 - 也支持构造函数,如
function Person (firstName, lastName) { this.firstName = firstName; this.lastName = lastName }
,通过props: { person: Person}
来使用。
- 对象键值对的值为数据类型,可使用
- 为数组时,如
- props类型验证
当props
选项为对象时:
- 可让一个属性支持一种数据类型,如
title: String
。 - 也可支持多种数据类型,如
title: [String, Number]
。 - 键值对的值也可以是一个对象,如
title: { type: String }
,相当于title: String
这个对象有多种键:-
type
表示属性的数据类型,如title: { type: String }
。 -
required
表示属性是否必填,如title: { type: String, required: true }
。 -
default
表示默认值,如title: { type: String, default: "标题" }
;
若数据类型为数组或对象,必须使用函数,如title: { type: Array, default: function() { return [] } }
。 -
validator
表示验证函数,如title: {type: String, validator: function(value) { return value.length > 6 } }
,表示title的值的字符长度必须大于6。
-
props
选项中的属性会在组件实例创建之前进行验证,所以实例this
在default
或validator
的函数中是不可用的。
- 可让一个属性支持一种数据类型,如
- 使用非props的属性
若组件中并没有声明title属性,使用时,Vue 会将title自动添加到组件的根元素上。若根元素上已经设定了该属性,会被覆盖。但style、class
会发生合并。
若想让未声明的属性不自动添加到组件的根元素上,需要设置inheritAttrs
选项为false。
该选项并不会影响class、style
的合并。
使用
$attrs
属性可获取所有已使用且未在props
中声明的属性,它是一个对象,里面不包括class、style
。{{ $attrs["val1"] }}
使用
设置未声明的属性,在组件中也可使用$attrs
属性来实现props
的功能,但不推荐。- 事件方法
每个元素都有事件方法,自定义组件中使用实例方法$emit()
来声明自定义方法。
{{ title }}{{ content }}
{{ title }}
的功能是,当点击 h1 元素时,触发一个名为 tap 的事件,并为事件提供了两个参数1和2;$emit
中事件名必须的。当然,也可以将
$emit()
写在@click="clickAction"
绑定的函数中。父组件通过
来监听 tap 事件,并通过tapAction: function(val1, val2) { }
使用这两个参数,或在函数中通过arguments[0]、arguments[1]
使用这两参数。- native
在组件上监听原生事件时,如
,会发现点击时并不会调用 clickAction 函数,因为只能监听$emit()
触发的事件。
为了能顺利调用函数,需要使用.native
修饰符,如@click.native="clickAction"
。 - listeners
.native
修饰符可以监听根元素上的原生事件,若根元素是一个div,监听的事件是input,这当然不会有作用。
可以使用$listeners
属性获取所有v-on
指令绑定的事件(不包括.native
修饰符的事件)。
这样就能将父组件要监听的input
事件绑定到子组件的 input 元素上,如。
也可以将所有事件都绑定到 input 元素上,如。
- 组件使用v-model
使用v-model
指令时,text 和 textarea 绑定的是 value 属性 和 input 事件,相当于。
组件也能使用v-model
指令,也默认绑定 value 属性与 input 事件,相当于
。
在 input 元素中,$event
表示事件对象;而在组件中,$event
表示$emit()
的第二个参数。
- 更改默认
组件使用v-model
指令时默认绑定value
与input
事件,可使用model
选项更改默认值。
选项是一个对象,对象有两个键prop、event
,分别为要绑定的属性和事件。
此时变更为绑定content属性与change事件。
- 插槽
html 元素大都可以通过message
在开始和结束标签中添加内容。
而对于组件,
标签中的内容是没有任何效果的。message
为了使添加的内容生效,可以使用 slot 元素。
{{ title }}{{ content }}
此时,
message
标签中的message就会替换到
的位置。- 默认值
在中添加默认值,如
hello
,那么当
时,就相当于
。hello - 具名插槽
有时候,我们可能需要添加多个插槽,它们在组件的不同位置。
这时需要使用插槽的name
属性。
是一个默认插槽,name
默认为default,相当于
。
default
aaa
bbb
使用时具名插槽的内容必须写在 template 元素中,通过
v-slot
指令的参数来匹配插槽的名字。若为默认插槽,可省略
。文章图片
内容显示的顺序只与组件中各插槽的顺序有关。
- 简写
同v-bind、v-on
指令可以简写成: @
一样,v-slot
指令可以简写成#
,如简写成
。
- 作用域插槽
通常,给插槽添加内容时,都是使用当前文件中的数据。如
。{{ value }}
但组件内部也提供了许多数据给外面的插槽使用,使用v-slot
指令来获取组件提供的数据。
在插槽 slot 上添加属性 age 和 adress,也可使用
v-bind
指令为属性绑定一个表达式。
{{ value }}
v-slot:default="value"
表示给name="default"
的插槽(即默认插槽)提供一个变量 value。插槽就能够使用变量 value 的数据,而 value 的值为
{ "age": "20", "adress": "cd" }
,即在 slot 上添加的属性与属性值。若只有默认插槽,有另一种写法,如
{{ value }}
- 使用部分数据
上面 value 的值是一个对象{ "age": "20", "adress": "cd" }
,若想只返回对应属性的值,可写成v-slot:default="{age: a, adress: b}"
,这时a为20,b为cd。
因为当对象中的键值相同时可以省略值,所以可以写成v-slot:default="{age, adress}"
,相当于v-slot:default="{age: age, adress: adress}"
,这时age为20,adress为cd。 - 动态插槽名
和其他指令一样,可以使用[]
为指令设定动态的参数,而v-slot
的参数即表示插槽名。如v-slot:[name]="value"
,{ name: 'default' }
时相当于v-slot:default="value"
。
- 动态组件
使用 component 元素和is
属性来使用动态组件。
相当于
,通常使用v-bind:is=""
绑定一个变量,就可以改变变量的值来切换不同的组件。
除了使用组件,也可以用在普通的 html 元素上,如
。
- 保活组件
动态组件通常用于多标签栏切换界面。你会发现,切换不同界面时界面都会重置;这是因为在切换时,Vue 都会创建一个新的组件实例。
但有时候,我们希望创建的组件能缓存下来,可以使用 keep-alive 元素,如
。
在不同组件同切换时,组件中的activated
和deactivated
这两个生命周期钩子函数会执行,组件的子组件中的这两个钩子函数也会执行。
keep-alive 元素有三个属性:
-
include
字符串或正则表达式,名称匹配的组件会被缓存。
名称为组件name
选项的值或父组件components
选项的键值对的键。 -
exclude
字符串或正则表达式。名称匹配的组件不会被缓存。 -
max
数字。最多可以缓存多少组件实例,数字达到了,会释放最久没有访问的实例。
v-for
,keep-alive 元素也没有效果。
-
- 异步组件
通常,我们都是在本地创建组件,然后在本地直接使用组件。
有时候,组件的代码在服务器端,则需要先从服务器获取组件代码,这时就要使用异步组件。
components: {
ServiceComponent: function(resolve, reject) {
var http = new XMLHttpRequest()
http.onreadystatechange = function() {
if (http.readyState == 4&&http.status == 200) {
const component = {
template: http.responseText
}
resolve(component)
} else {
reject("组件获取失败")
}
}
http.open("GET", "http_url", true)
http.send()
}
}
Vue 允许你以一个函数的方式定义你的组件,这个函数会异步解析你的组件。
Vue 只有在这个组件需要被渲染的时候才会触发该函数,且会把结果缓存起来供以后再次渲染。
函数有两个回调参数,调用
resolve()
表示组件加载成功,调用reject()
表示组件加载失败,- 访问子组件
使用ref
属性为元素或子组件注册引用信息,如
。
再使用$refs
引用就会指向子组件的实例,如this.$ref.custom
。
若用在 html 元素上,引用就会指向 DOM 元素。
注:$refs
只会在组件渲染完成之后生效,并且它不是响应式的。应该避免在 template 或计算属性中访问它。
- 访问父组件
使用$parent
可访问父组件的实例,如this.$parent
。
- 依赖注入
子组件不应该主动访问父组件的实例,可以使用provide、inject
选项来依赖注入,让子组件能访问父组件提供的数据或方法。
在父组件中使用provide
选项提供数据,它是一个对象或返回对象的函数,如provide: {age: this.age};
在子组件中使用inject
选项接收数据,它是一个对象或数组,如inject: ['age']
。
这样就能在子组件中通过age来使用父组件中的this.age。
相比十二、过渡$parent
来说,依赖注入可以让我们在任意后代组件中访问数据,而不需要暴露整个父组件实例。
后代组件不需要知道被注入的数据来自哪里。
父组件不需要知道哪些后代组件使用了它提供的数据。
注入的数据是非响应式的。
使用 transition 元素,给其他元素或组件添加进入、离开过渡/动画效果。
将要过渡/动画的元素放在 transition 中,如
然后在CSS类名中添加过渡/动画效果。
- 类名
在进入/离开的过渡中,会有6个类名切换。
v-enter
定义进入过渡/动画的开始状态。在元素插入之前生效,在元素插入之后的下一帧移除。为动画时会在animationend
事件触发时移除。
v-enter-active
定义进入过渡/动画生效时的状态。在这里设定进入过渡/动画的过程时间、延迟和曲线函数。
v-enter-to
定义进入过渡/动画的结束状态。在元素插入之后下一帧生效 (v-enter
移除之时),在过渡/动画完成之后移除。
v-leave
定义离开过渡/动画的开始状态。在元素删除之前生效,在元素删除之后的下一帧移除。为动画时会在animationend
事件触发时移除。
v-leave-active
定义离开过渡/动画生效时的状态。被用来定义离开过渡/动画的过程时间、延迟和曲线函数。
v-leave-to
定义离开过渡/动画的结束状态。在元素删除之后的下一帧生效 (v-leave
移除之时),在过渡/动画完成之后移除。
前面的v表示 transition 元素的name
的值,如
时使用div-enter-active
。
当没有设置name
时,默认使用v。
文章图片
v-enter-active
表示元素插入、执行过渡/动画、过渡/动画结束这三个阶段。
v-enter-active = v-enter + v-enter-to
,大概相当于v-enter
占v-enter-active
的前1%,v-enter-to
占后面99%。
v-leave-active
与v-enter-active
类同。
animation
transtion
/* 过渡 */
.div1-enter-active, .div1-leave-active {
transition: all 1s ease;
}
/* 设置进入过渡执行前或离开过渡执行后的CSS,通常这两个时间点CSS相同 */
.div1-enter, .div1-leave-to{
opacity: 0;
transform: translateX(60px);
}/* 动画 */
.div-enter-active {
animation: framename 2s;
}
/* 通常离开动画是进入动画的反向 */
.div-leave-active {
animation: framename 2s reverse;
}
/* from中设置动画的初始状态CSS to中设置结束状态CSS */
@keyframes framename{
from{
transform: translate(0px, 0px);
}
25% {
transform: translate(50px, 0px)
}
50% {
transform: translate(50px, 50px)
}
75% {
transform: translate(0px, 50px)
}
to{
transform: translate(0px, 0px);
}
}
文章图片
- 自定义类名
transtion
.aaa, .bbb {
transition: all 1s ease;
}
使用属性
enter-class、enter-active-class、enter-to-class、leave-class、leave-active-class、leave-to-class
自定义过渡/动画的类名。如上,
aaa、bbb
相当于div1-enter-active、div1-leave-active
类名。- 监听类型
Vue 会监听transitionend
或animationend
事件来确定过渡/动画的结束。若为一个元素同时设定过渡和动画,Vue 并不知道监听哪一个事件来确定过渡/动画的结束。
可以将type
属性设为animation、transition
来确定监听哪一个事件,如
。
- 持续时间
过渡/动画的持续时间通常是在CSS属性中设置,也可以使用duration
属性设定持续时间,如
。
可以分别设定进入和离开的持续时间,如
。
duration
属性设定的持续时间优先度更高。当到了设定的持续时间,即使过渡或动画还在执行,也会立即结束过渡或动画。
- 事件
transition 元素有before-enter、enter、after-enter、enter-cancelled、before-leave、leave、after-leave、leave-cancelled
这几种事件,会在过渡前、过渡时、过渡后、过渡取消时触发,如
。
事件可以与 CSS 类名一起使用,建议单独使用。使用
可屏蔽 CSS。
- 事件会给绑定的函数提供一个参数,参数值为执行过渡/动画的元素。
- 若为
enter、leave
事件,还会多提供一个参数,参数为一个回调函数。
需要在过渡/动画完成时执行回调函数,如enter: function(el, done) { done() }
。
若不执行回调,过渡/动画就不会结束,就不会触发after-enter
事件;执行回调函数后,过渡/动画会立即结束。
- 初始渲染过渡
当元素初次渲染到界面时,也可以执行过渡。使用appear
属性来实现初始渲染过渡。
transtion init1
.div-enter-active, .div-leave-active {
transition: all 1s ease;
}
.div-enter, .div-leave-to{
opacity: 0;
transform: translateX(60px);
}.div-appearname{
opacity: 0;
transform: translateX(60px);
}
.div-appearname-active {
transition: all 1s ease;
}
.div-appearname-to {}
初始渲染过渡有三个类名,默认为
v-appear、v-appear-active、v-appear-to
,表示初始渲染过渡前、初始渲染过渡中、初始渲染过渡完成。根据
name
属性和appear
属性的值决定类名,若
,那么类名为div-appearname、div-appearname-active、div-appearname-to
。初始渲染过渡也可以通过
appear-class、appear-active-class、appear-to-class
使用自定义类名,如
。初始渲染过渡也可以使用事件
before-appear、appear、after-appear、appear-cancelled
。表示初始渲染过渡前、初始渲染过渡时、初始渲染过渡后、初始渲染过渡取消。- 元素切换的过渡
上面介绍的都是单个元素的进入与离开过渡,若想使用多个元素间切换时的过渡,可使用v-if、v-else-if、v-else
。
transtion init1
transtion init2
文章图片
此时就会在两个 div 中切换。
必须给每个元素的
key
属性设置不同的值,否则 Vue 会直接改变元素的内容,就不会产生过渡效果。
若两个元素是不同的元素,也可以不设置
key
属性,但建议设置。
- 过渡模式
你会发现两个元素它们会同时过渡,即离开与进入过渡同时进行。可以使用mode
属性修改过渡模式。
-
in-out
新元素先进行过渡,完成之后当前元素过渡。 -
out-in
当前元素先进行过渡,完成之后新元素过渡。(经常使用)
mode
时,两者会同时过渡。
设置
后
文章图片
-
- 组件切换的过渡
通过动态组件实现组件切换的过渡,动态组件详见 十一、组件 -- 6. 动态组件。
这里因为是不同的组件,所以可以不设置key
属性。
.div-enter-active, .div-leave-active {
transition: all 1s ease;
}
.div-enter, .div-leave-to{
opacity: 0;
transform: translateX(60px);
}
- 列表元素的过渡
上面我们过渡的,实际上都是单一元素或组件的过渡;若同时要过渡多个元素,需要使用 transition-group 元素,且多个元素必须设置不同的key
。
不同于 transition 元素,transition-group 会以一个真实元素呈现,默认为一个 span,使用tag
属性更换为其他元素。
{{ item }}
.v-enter-active, .v-leave-active {
transition: all 1s ease;
}
.v-enter, .v-leave-to{
opacity: 0;
transform: translateY(30px);
}
文章图片
- 平滑过渡
可以看出,当添加一个元素时,周围的元素会瞬间移动到他们的新布局的位置。
为了让周围元素能平滑的移动到新位置,可以使用v-move
类名。
像其他类名一样,可以使用name
属性改变类名,也可以使用move-class
属性自定义类名。
上面的例子添加.v-move { transition: all 1s ease; }
后
文章图片
注:要使用平滑过渡,元素不能为display: inline
。
- 状态过渡
上面都是元素的进入或离开过渡,若想让数据元素本身产生动效,可以使用状态过渡。如数字从0变到100的渐增式效果。
详见状态过渡。
混入 (mixin) 提供了一种非常灵活的方式,来分发 Vue 组件中的可复用功能,一个混入对象包含任意的组件选项。
export default {
data: function() {
return {
b: 22,
c: 33
}
},
created: function() {
console.log('hello!11')
this.action()
},
methods: {
action: function() {
console.log('action11')
}
}
}
在
.js
文件中添加要混入的选项。{{ a }}
{{ b }}
{{ c }}
在单文件组件中通过
import
引入.js
文件,混入的对象写在mixins
选项中,选项是一个数组。- 选项合并
当组件和混入对象含有同名选项时,这些选项会进行合并。
-
data
选项里的数据对象会递归合并,若遇到同名冲突,以组件的数据优先。 - 值为对象的选项(
methods、components、directives
等),将被合并为同一个对象。若遇到同名冲突,以组件的数据优先。 - 生命周期钩子函数(
created、beforeCreate、mounted
等),若遇到同名冲突,两个函数会合并为一个数组,它们都会调用,但混入对象中的函数优先调用。
- 全局混入
使用Vue.mixin({})
来注册全局混入,需要写在new Vue()
前面。
- 自定义合并
混入数据与组件数据合并时,有一个默认的合并策略。使用Vue.config.optionMergeStrategies
可修改合并策略,详见自定义选项合并策略。
- 扩展
扩展(extend)和混入功能差不多,都是给组件添加其他的选项功能。
混入使用mixins
选项,它是一个数组;而扩展使用extend
选项,它是一个对象或函数。
扩展与混入的选项合并策略相同,不同点在于mixins可同时混入多组对象,而extend只能扩展一组对象。
扩展的优先级比混入高,但都低于组件本身。
- 全局扩展
使用Vue.extend({})
来注册全局扩展,需要写在new Vue()
前面。
Vue 有自带的指令,但也可以使用
directives
选项来自定义指令,选项是一个对象。
文章图片
- 全局指令
使用Vue.directive('name', {})
注册全局指令,必须写在new Vue()
前面。
- 钩子函数
自定义指令有几个钩子函数:-
bind
只调用一次,指令第一次绑定到元素时调用。在这里可以进行一次性的初始化设置。 -
inserted
元素插入父节点时调用 (仅保证父节点存在,但不一定已插入到文档中)。 -
update
元素的 VNode 更新时调用,可能发生在其子 VNode 更新之前。指令的值可能发生了改变,也可能没有。 -
componentUpdated
元素的 VNode 及其子 VNode 全部更新后调用。 -
unbind
只调用一次,指令与元素解绑时调用。
-
- 钩子函数参数
钩子函数有4个参数,其中el
是可读写的,其他都是只读的。-
el
指令绑定的元素,可以用来直接操作 DOM。 -
binding
一个对象,包含以下的键。-
name
指令名,不包括v-
前缀。 -
value
指令的绑定值,如v-directive="1 + 1"
中的2。 -
oldValue
指令绑定的前一个值,仅在update、componentUpdated
钩子中可用。无论值是否改变都可用。 -
expression
指令的表达式。如v-directive="1 + 1"
中的1 + 1。 -
arg
指令的参数,可选。如v-directive:arg
中的arg。 -
modifiers
一个包含修饰符的对象。如v-directive.mod1.mod2
,修饰符对象为{ mod1: true, mod2: true }
。
-
-
vnode
Vue 编译生成的虚拟节点。详见 VNode。 -
oldVnode
上一个虚拟节点,仅在update、componentUpdated
钩子中可用。
-
- 动态参数
指令可使用[]
设置动态参数,如v-on:[dynamic]=""
。
自定义的指令也可以使用动态参数,如v-redtext:[dynamic]
,在钩子函数中通过binding.arg
获取参数。
通常使用模板来创建组件,也可以使用
render
选项来创建组件。
上面例子相当于
title
。使用
render
选项来创建组件时需要删除最上面的
,也会忽略template
选项的值。-
render
选项是一个函数,函数需要返回一个 VNode。函数有一个参数,参数是一个回调函数,可通过这个回调函数来创建 VNode。 -
render
选项可以使用箭头函数,如render: createElement => createElement()
。
回调函数通常使用字母h,即render: h => h()
,可看到 main.js 中就是这种写法。
- VNode
每个元素都是一个节点,每段文字也是一个节点,注释和属性也都是节点。一个节点就是页面的一个部分,每个节点都可以有子节点 。
Vue 通过建立一个虚拟 DOM 来追踪自己要如何改变真实 DOM,虚拟 DOM 由虚拟节点(virtual node)组成,即VNode。
回调函数createElement()
可以创建一个虚拟节点 。它包含的信息会告诉 Vue 需要渲染什么样的节点,包括节点及其子节点的描述信息。
VNode 必须是唯一的,下面是错误的。
render: function (createElement) {
var myParagraphVNode = createElement('p', 'hi')
return createElement('div', [
// 错误 - 重复的 VNode
myParagraphVNode, myParagraphVNode
])
}
但可以写成:
render: function (createElement) {
return createElement('div', [
createElement('p', 'hi'), createElement('p', 'hi')
])
}
- 参数
createElement()
需要传三个参数,如createElement("h1", {}, "title")
。- 参数一是必填项,可为一个 HTML 标签名、组件选项对象,或者 resolve 了上述任何一种的
async
函数。 - 参数二是一个对象,为元素的各种属性,如
props、class、id
等。 - 参数三是一个由子 VNode 组成的数组,如
createElement("div", {}, [createElement("h1", "title"), createElement("p", "content")])
。
或为一个字符串,内容为元素的innerHTML
。
- 参数一是必填项,可为一个 HTML 标签名、组件选项对象,或者 resolve 了上述任何一种的
- 参数二
{
// 与 `v-bind:class` 的 API 相同,
// 接受一个字符串、对象或字符串和对象组成的数组
'class': {
foo: true,
bar: false
},
// 与 `v-bind:style` 的 API 相同,
// 接受一个字符串、对象,或对象组成的数组
style: {
color: 'red',
fontSize: '14px'
},
// 普通的 HTML attribute
attrs: {
id: 'foo'
},
// 组件 prop
props: {
myProp: 'bar'
},
// DOM property
domProps: {
innerHTML: 'baz'
},
// 事件监听器在 `on` 内,
// 但不再支持如 `v-on:keyup.enter` 这样的修饰器。
// 需要在处理函数中手动检查 keyCode。
on: {
click: this.clickHandler
},
// 仅用于组件,用于监听原生事件,而不是组件内部使用
// `vm.$emit` 触发的事件。
nativeOn: {
click: this.nativeClickHandler
},
// 自定义指令。注意,你无法对 `binding` 中的 `oldValue`
// 赋值,因为 Vue 已经自动为你进行了同步。
directives: [
{
name: 'my-custom-directive',
value: '2',
expression: '1 + 1',
arg: 'foo',
modifiers: {
bar: true
}
}
],
// 作用域插槽的格式为
// { name: props => VNode | Array }
scopedSlots: {
default: props => createElement('span', props.text)
},
// 如果组件是其它组件的子组件,需为插槽指定名称
slot: 'name-of-slot',
// 其它特殊顶层 property
key: 'myKey',
ref: 'myRef',
// 如果你在渲染函数中给多个元素都应用了相同的 ref 名,
// 那么 `$refs.myRef` 会变成一个数组。
refInFor: true
}
- 事件修饰符
在参数二的 on 中可设置事件监听,但事件名后是不能添加修饰符的,如on { click.once: this.clickAction }
是错误的。为了解决这个问题,Vue 提供了一些前缀。
-
&
表示.passive
修饰符。 -
!
表示.capture
修饰符。 -
~
表示.once
修饰符。 -
~!
表示.capture.once、.once.capture
修饰符。
on { !click: this.clickAction }
相当于@click.capture="clickAction"
。
而其他修饰符,可以在函数中实现相同的功能。
-
event.stopPropagation()
相当于.stop
修饰符。 -
event.preventDefault()
相当于.prevent
修饰符。 -
if (event.target !== event.currentTarget) return
相当于.self
修饰符。 -
if (event.keyCode !== 13) return
相当于.enter、.13
修饰符。 -
if (!event.ctrlKey) return
相当于.ctrl
修饰符。
-
- 插槽
- 使用
this.$slots
访问插槽,每个插槽都是一个 VNode 组成的数组。
如render: function (h) { return h('div', this.$slots.default) }
相当于。
如render: function (h) { return h('div', [this.$slots.header, this.$slots.default]) }
相当于。
注:使用插槽时不能用箭头函数,因为不能访问this。 - 使用
this.$scopedSlots
访问作用域插槽。
data: function() {
return {
title: "标题",
content: "内容"
}
},
render: function (h) {
return h('div', [this.$scopedSlots.header({
title: this.title
}), this.$scopedSlots.default({
content: this.content
})])
}
相当于
。- JSX
JSX是一个插件,可使用模板来代替渲染函数。详见JSX。
如render: h =>h("div", [h("h1", "title"), h("div", "contnet")])
可写成redder: h=> (titlecontent)
。
- 函数式组件
组件比较简单时,即没有管理任何状态,没有监听任何传递给它的状态,也没有生命周期方法,它相当于一个接受一些props
的函数。
在这样的场景下,我们可以将组件的functional
选项设为true,这意味它无状态,没有响应式数据(即没有data
选项),也没有实例 (即没有this
)。
functional: true,
props: {},
render: function(createElement, context) {
createElement("div", context.data, context.children)
}
因为函数式组件只是函数,所以渲染开销也低很多。
- context
因为在函数式组件中this
不可用,所以所有属性都保存在参数context
中。
它是一个对象,包含下列字段:-
props
提供所有自定义属性的对象。 -
children
子虚拟节点的数组,通常作为createElement()
的第三个参数传入组件。 -
slots
一个函数,返回了包含所有插槽的对象。 -
scopedSlots
一个包含的作用域插槽的对象。 -
data
传递给组件的数据对象,通常作为createElement()
的第二个参数传入组件。 -
parent
对父组件的引用。 -
listeners
一个包含了所有父组件为当前组件注册的事件监听器的对象。data.on
的别名。 -
injections
如果使用了inject
选项,则该对象包含了被注入的属性。注入详见 十一、组件 -- 9. 访问父组件 。
-
过滤器用于一些常见的文本格式化。过滤器可以用在两个地方:
{{ }}
插值和 v-bind
指令的值,如{{ mesage | filter }}、
。过滤器写在
filters
选项中,选项是一个对象。{{ message | lowercase | uppercase }}
过滤器使用
|
与表达式相连,过滤器对象的键值对的值是一个函数,且表达式为函数的第一个参数。可多个过滤器串联使用,如
{{ message | lowercase | uppercase }}
,前面过滤器得出的结果变为后面过滤器的第一个参数。过滤器可传入其他参数,如
{{ message | lowercase(arg1, arg2) }}
,第一个参数为message,参数二三为arg1、arg2。- 全局过滤器
使用Vue.filter('name', function (value) {})
注册全局过滤器,必须写在new Vue()
前面。
当全局过滤器与局部过滤器重名时,优先使用局部过滤器。
整个 Vue 实例初始化到销毁会经历如下过程。
文章图片
生命周期分为多个阶段,每个阶段都会触发相应的钩子。
钩子有
beforeCreate、created、beforeMount、mounted、beforeUpdate、updated、beforeDestroy、destroyed
这几种,详见生命周期钩子。它们都是函数,使用时不要用箭头函数,因为箭头函数中
this
不指向 Vue 实例。推荐阅读
- 由浅入深理解AOP
- vue-cli|vue-cli 3.x vue.config.js 配置
- 2020-04-07vue中Axios的封装和API接口的管理
- 继续努力,自主学习家庭Day135(20181015)
- python学习之|python学习之 实现QQ自动发送消息
- 小学英语必考的10个知识点归纳,复习必备!
- 一起来学习C语言的字符串转换函数
- 定制一套英文学习方案
- 漫画初学者如何学习漫画背景的透视画法(这篇教程请收藏好了!)
- 《深度倾听》第5天──「RIA学习力」便签输出第16期