目录
- 一、组件间通信
- 1. 使用 props 和 $emit 进行父子组件通信
- 2. 使用 $attrs 和 $listeners 进行多层组件间通信
- 3. 使用 中央事件总线 bus 进行组件间通信
- 4. 使用 $parent 和 $children 实现父子组件之间的通信
- 5. 使用 provide 和 inject 实现父组件向子组件的单向通信
- 二、过滤器
- 1. 局部过滤器
- 2. 全局过滤器
- 3. 过滤器中还可以传入参数
- 三、插槽
- 四、watch 监听
- 五、计算属性
- 六、生命周期
- 七、keep-alive 内置组件
- 八、其他补充
- 九、RESTful 规范
一、组件间通信
以下5种组件间通信,数据传递的方法中,第1~3中是比较常用的。
1. 使用 props 和 $emit 进行父子组件通信
1) 父==>子组件传值
- Step1:先通过
v-bind
给父组件中绑定自定义的属性; - Step2: 在子组件中使用
props
接收父组件传递的数据; - Step3: 在子组件中使用接收的数据。
2) 子==>父组件传值
- Step1: 在父组件绑定自定义的事件;
- Step2: 在子组件中触发原生的事件,在事件函数中使用
$emit
触发父组件自定义的事件; - Step3:
$emit
的参数是回传给父组件的数据。
Vue.component("Child", {
template: `
`,
props: ['childData'],
methods: {
changeValue(val){
// 父组件自定义的事件一定是通过this.$emit()去触发
// $emit(自定义的事件名, 消息)
this.$emit('childHandler', val)
}
}
});
Vue.component("Parent", {
data: {
msg: "我是父组件"
},
template: `
我是父组件
,
`,
methods: {
getDataHandler(val){
console.log(val)
}
}
})
2. 使用 $attrs 和 $listeners 进行多层组件间通信
第一种方式处理组件之间的数据传输有一个问题:多层组件之间的数据传递只能一层一层传递。Vue2.4开始提供了$attrs
和$listeners
来解决这个问题。
组件通信二
3. 使用 中央事件总线 bus 进行组件间通信
上面两种方式处理的都是父子组件之间的数据传递,如果两个组件不是父子关系呢?这种情况下可以使用中央事件总线的方式:
新建一个Vue
对象bus
,然后通过bus.$emit
触发事件传递数据,通过bus.$on
监听触发的事件接收数据。
// 中央事件总线
var bus = new Vue();
Vue.component("brother1", {
data() {
return {
brother2Msg: ''
}
},
template: `
我是同级组件A
同级组件B传递过来的数据:{{brother2Msg}}
`,
mounted() {
// 绑定自定义的全局事件globalEvent
bus.$on('globalEvent', (val)=>{
this.brother2Msg = val;
})
}
});
Vue.component("brother2", {
data() {
return {
msg: ""
}
},
template: `
我是同级组价B
`,
methods: {
passData(val){
// 触发自定义的全局事件globalEvent
bus.$emit('globalEvent', val)
}
}
});
var App = { // 父组件
template: `
`
};
new Vue({
el: "#app",
components: {App},
template: " "
})
4. 使用 $parent 和 $children 实现父子组件之间的通信
在父组件中通过this.$children[
可以向子组件传递数据;在子组件中通过this.parent.
可以向父组件传递数据。
Vue.component("Child", {
props: {
value: String, //v-model会自动传递一个属性名为value的prop属性
},
data() {
return {
myMessage: this.value
}
},
methods: {
changeValue() {
// 通过如此调用,可以向父组件传递数据,改变父组件的值
this.$parent.message = this.myMessage;
}
},
template: `
{{myMessage}}
`
});
Vue.component('Parent', {
data() {
return {message: 'Hi, child'}
},
template: `
我是父组件
{{message}}
`,
methods: {
changeChildValue() {
// 通过如此调用,可以向子组件传递数据,改变子组件的值
this.$children[0].myMessage = this.message;
}
},
});
var App = {
template: `
我是入口组件
`
};
new Vue({
el: "#app",
components: {App},
template: " "
})
5. 使用 provide 和 inject 实现父组件向子组件的单向通信
父组件中通过provide
来提供变量,然后子组件中通过inject
来注入变量。不论子组件有多深,只要调用了inject
那么就可以注入provide
中的数据,而不是局限于只能从当前父组件的props
属性来获取数据。只要在父组件的生命周期内,子组件都可以调用。
Vue.component("Child", {
data() {
return {msg: ""}
},
template: "我是子组件: {{msg}}",
inject: ['for'],
created() {
this.msg = this.for;
}
});
Vue.component("Parent", {
template: `
我是父组件
`
});
var App = {
provide: {
for: "从祖先组件跨代传递到子孙组件的数据"
},
template: `
我是入口组件,也是祖先组件
`
};
new Vue({
el: "#app",
components: {
App
},
template: " "
})
二、过滤器
- 过滤器的作用:为页面中的数据进行添油加醋。
- 过滤器的种类:局部过滤器、全局过滤器。
1. 局部过滤器
- 声明过滤器: 在组件的
filters
选项中定义函数。 - 使用过滤器:{{data|myFilter}}
2. 全局过滤器
使用Vue.filter(
创建全局过滤器。
Vue.filter("moneyFormat", function(value) {
return "¥" + value;
})
3. 过滤器中还可以传入参数
Vue.filter("myFilter", function(value, arg) {
return arg + value.split('').reverse().join('');
})
三、插槽
插槽slot
是Vue
内置的组件,它的作用是作为承载内容分发的出口。
具名插槽
为slot
添加name
属性的插槽叫做具名插槽,在使用时,将根据name
去分别替换内容。
Vue.component("myLi", {
template: `
第一个插槽
第二个插槽
`
});
new Vue({
el: "#app",
template: `
插入第二插槽
插入第一插槽
`
})
四、watch 监听
watch
监听的是单个属性,当监听基本数据类型时,使用简单监视;当监听复杂数据类型(引用数据类型),使用深度监视。
- 定义
watch
监听时,watch
对象的属性名称必须与被监听的data
对象中数据属性的名称相同。
示例代码:
new Vue({
el: "#app",
data: {
msg: "",
arr_obj: [
{
name: "Jack",
age: 18,
sex: male
}
]
},
watch: {
// 基本数据类型,简单监视
msg: function(newValue, oldValue) {
console.log(newValue, oldValue);
},
// 复杂数据类型,深度监视
arr_obj: {
deep: true,
handler: function(newValue, oldValue) {
console.log(newValue);
}
}
}
})
五、计算属性
计算属性可以同时监听多个数据属性。
Vue-computed
-
{{item.name}}
--{{item.author}}
六、生命周期
生命周期钩子函数:
- beforeCreate: 组件创建之前,此时组件对象实例已经创建,但实例的属性还没有初始化。
- created: 组件创建之后,在这个方法中通常会请求后端,获取数据。
- beforeMount: 挂载数据到
DOM
之前会调用。 - mounted: 挂载数据到
DOM
之后会调用,应用:操作DOM
。 - beforeUpdate: 在更新
DOM
之前会调用,应用:可以获取原始的DOM
。 - updated: 在更新
DOM
之后会调用,应用:可以获取最新的DOM
。 - activated: 当
keep-alive
组件激活时调用。 - deactivated: 当
keep-alive
组件停用时调用。 - beforeDestroy: 在组件销毁之前调用。
- destroyed: 在组件销毁之后调用。
- errorCaptured:
七、keep-alive 内置组件
Vue 内置组件keep-alive
能在组件的切换过程中将组件的状态保留在内存中,即缓存组件,防止重复渲染DOM
。
var App = {
data() {
return {
isShow: true
}
},
template: `
`
}
new Vue({
el: "#app",
components: {App}
})
八、其他补充
- 如果给HTML标签绑定
ref="xxx"
属性,使用this.$refs.xxx
获取原生的JS-DOM
对象。 - 如果给组件绑定
ref=“xxx”
属性,那么this.$refs.xxx
获取的是这个组件对象。 $nextTick()
会在DOM
更新循环结束之后自动触发,执行它的回调函数。在修改数据之后必须使用此方法,在其回调函数中获取更新之后的DOM
。- 获取更新后的
DOM
,除了使用$nextTick()
外,还可以在生命周期钩子函数updated
中获取。
let App = {
data() {
return {
isShow: false
}
},
template: `
`,
mounted() {
this.isShow = true;
/*this.$nextTick(function() { // 通过$nextTick的回调函数获取DOM,并获取焦点
this.$refs.input.focus();
});*/
this.$nextTick(()=>{ // 通过$nextTick定义回调函数为箭头函数,获取DOM,并获取焦点
this.$refs.input.focus();
})
}
};
new Vue({
el: "#app",
template: " ",
components: {App}
})
九、RESTful 规范
RESTful规范是一种软件的架构风格、设计风格,而不是标准,为客户端和服务端的交互提供一组设计原则和约束条件。
前后端分离:
- 后端提供接口(API)
- 前端写页面和Ajax技术
1. 面向资源变成
每个URL代表一种资源,URL中尽量不要使用动词,要用名词,往往名词跟数据库表格相对应。一般来说,数据库中的表都是同种记录的集合,所有API中的名词也应该使用复数。
例如:一个提供动物园信息的API,包括各种动物和雇员的信息,它的路径应该设计成:
https://api.example.com/v1/zoos
https://api.example.com/v1/animals
https://api.example.com/v1/employees
RESTful规范参考
2. 在URL中的过滤条件
如果记录数量很多,服务器不可能将所有的数据都返回给用户。API应该提供参数,用于过滤返回结果。
?limit=10: 指定返回记录的数量
?offset=10: 指定返回记录的开始位置
?page=2&per_page=100: 指定第几页,以及每页的记录数
?sortby=name&order=asc: 指定返回结果按照哪个属性排序,以及排序顺序
?item_id=1: 指定筛选条件
3. 尽量使用HTTPS
4. 相应时设置状态码
5. 返回错误信息
如果状态码是4XX,应该向用户返回错误信息。一般来说,返回的信息中将error
作为键名,错误信息作为键值即可。
6. Hypermedia API
如果遇到需要跳转的情况,那么就要携带跳转接口的URL。
Hypermedia API 的设计,比如github的API就是这种设计。访问api.github.com就会得到一个所有可用的API的网址列表。
7. 其他
- API的身份认证应该使用OAuth 2.0框架
- 服务器返回的数据格式,应该尽量使用JSON,避免使用XML