Vue 组件小结
自己学习时记录,略混乱,可能有错,不属于教程,慎读!
1. 全局组件/局部组建语法
全局:
<div id="app">
<my-component></my-component>
</div>
<script>
// 注册
Vue.component('my-component', {
template: '<h1>自定义组件!</h1>'
})
// 创建根实例
new Vue({
el: '#app'
})
</script>
局部:
<div id="app">
<my-component></my-component>
</div>
<script>
var Child = {
template: '<h1>自定义组件!</h1>'
}
// 创建根实例
new Vue({
el: '#app',
components: {
'my-component': Child
}
})
</script>
2. 组建的data属性必须是function return形式
其它属性methods compute跟正常一样
Vue.component("my-component",{
template: '<div>模版:{{ Msg }}' +
'</div>',
data: function() {
return {
Msg: "属性"
};
}
});
3. props:父组建给子组建传数据
- props可以是数组也可以是object
- warningGMessage是子组建props中的一个值
- 在父组建里props是一个属性,可以用v-bind动态绑定如下例
- 如果传的是基础类型Number、string这种,只能由父传递向子,父改变,子会变,反之不行,会出warning。这是vue2的一种安全性设计。如下例1,会出warning。
- 解决方法可以复制一份如例2,这样相当于用父给子赋值
- 但如果传的是object,父子共享,无论复制不复制都共享,因为是引用如例3
//例1
//html
<div id="app" >
<input type="text" v-model="parentMessage">
父节点: {{ parentMessage }}
<my-component :warning-g-message="parentMessage"></my-component>
</div>
Vue.component("my-component",{
props: ['warningGMessage'], //因为js代码要用所以用驼峰不用-连接,html里用-在大写字母前warning-g-message
template: '<div>模版:{{ warningGMessage }} <input type="text" v-model="warningGMessage"/> ' +
'</div>',
});
var app = new Vue({
el: '#app',
data: {
parentMessage: "DOM传递"
}
});
//例2
//html
<div id="app" >
<input type="text" v-model="parentMessage">
父节点: {{ parentMessage }}
<my-component :warning-g-message="parentMessage"></my-component>
</div>
Vue.component("my-component",{
props: ['warningGMessage'], //因为js代码要用所以用驼峰不用-连接,html里用-在大写字母前warning-g-message
template: '<div>模版:{{ Msg }} <input type="text" v-model="Msg"/> ' +
'</div>',
data: function() {
return {
Msg: this.warningGMessage
};
}
});
var app = new Vue({
el: '#app',
data: {
parentMessage: "DOM传递"
}
});
//例3
//html
<div id="app" >
<input type="text" v-model="parentMessage">
父节点: {{ parentMessage.msg }}
<my-component :warning-g-message="parentMessage"></my-component>
</div>
// vue
Vue.component("my-component",{
props: ['warningGMessage'], //因为js代码要用所以用驼峰不用-连接,html里用-在大写字母前warning-g-message
template: '<div>模版:{{ Msg.msg }} <input type="text" v-model="Msg.msg"/> ' +
'</div>',
//template: '<div>模版:{{ warningGMessage.msg }} <input type="text" v-model="warningGMessage.msg"/> ' +
'</div>',
data: function() {
return {
Msg: this.warningGMessage
};
}
});
var app = new Vue({
el: '#app',
data: {
parentMessage: {
msg:"DOM传递"
}
}
});
4. 子给父传数据:自定义事件
- 子用$emit("事件名", 参数) //这个事件名要用xxx-xxx的形式,不能驼峰命名
- 父用@事件名相应,然后参数就是传递的数据了,下面给一个比较复杂的例子
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Vue test</title>
</head>
<body>
<div id="app" >
<input type="text" v-model="parentMessage">
父节点: {{ parentMessage.msg }}
<my-component :warning-g-message="parentMessage"></my-component>
</div>
<div id="app2" >
<input type="text" v-model="parentMessage">
<my-component :warning-g-message="parentMessage" @child-clk="handleChildClk"></my-component>
<parrent-component></parrent-component>
</div>
<script src="https://cdn.staticfile.org/vue/2.2.2/vue.min.js"></script>
<script src="components.js"></script>
</body>
</html>
Vue.component("my-component",{
props: ['warningGMessage'], //因为js代码要用所以用驼峰不用-连接,html里用-在大写字母前warning-g-message
template: '<div>模版:{{ warningGMessage.msg }} <input type="text" v-model="warningGMessage.msg"/> ' +
'<button @click="handleClk">click</button>' +
'</div>',
data: function() {
return {
Msg: this.warningGMessage
};
},
methods: {
handleClk: function() {
console.log("child handleClk");
this.$emit('child-clk', "来自子组建的消息"); // 不能用驼峰命名
}
}
});
Vue.component("parrent-component",{ //真正用组件作为父组件
template: '<div>{{parentMessage.msg}}<br />' +
'<my-component :warningGMessage="parentMessage" v-on:child-clk="handleChildClk"></my-component>'+
'</div>',
data: function() {
return {
parentMessage: {
msg: "parrent-component消息"
}
}
},
methods: {
handleChildClk: function(chldmsg) {
console.log(chldmsg);
this.parentMessage.msg += chldmsg;
}
}
});
var app = new Vue({
el: '#app',
data: {
parentMessage: {
msg:"DOM传递"
}
}
});
var app2 = new Vue({
el: '#app2',
data: {
parentMessage: {
msg:"DOM传递app2"
}
},
methods: {
handleChildClk: function(chldmsg) {
console.log(chldmsg);
this.parentMessage.msg += chldmsg;
}
}
});
5. 利用props和自定义事件实现父子数据双向绑定
除了传object引用实现共享之外,还可以用props+自定义事件
- props实现父到子
- 自定义事件实现子到父
- 这种方法可以实现自定义表单的双向绑定
//html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Vue test</title>
</head>
<body>
<div id="app" >
<input type="text" v-model="parentMessage">
父节点: {{ parentMessage }}
<my-component :warning-g-message="parentMessage" v-model="parentMessage"></my-component>
</div>
<script src="https://cdn.staticfile.org/vue/2.2.2/vue.min.js"></script>
<script src="components2.js"></script>
</body>
</html>
//vue
Vue.component("my-component",{
props: ['warningGMessage'],
template: '<div>模版:{{ warningGMessage }} <input type="text" :value="warningGMessage" @input="handleInput"/> ' +
'</div>',
methods: {
handleInput: function(event) {
this.$emit('input',event.target.value);
}
}
});
var app = new Vue({
el: '#app',
data: {
parentMessage:"DOM传递"
}
});
子组件用value + @input 达到类似v-model的功能
当子组件变化时,给父组建发input事件,父组件的v-model(相当于value+@input)就能相应此事件,动态修改绑定的parentMessage值
6.任意组件间的消息传递
- 中央事件总线方法(bus)
//html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Vue test</title>
</head>
<body>
<div id="app1" >
<my-component></my-component>
</div>
<div id="app2">
{{ message }}
</div>
<script src="https://cdn.staticfile.org/vue/2.2.2/vue.min.js"></script>
<script src="bus.js"></script>
</body>
</html>
//vue
var bus = new Vue(); //总线
Vue.component("my-component",{
template: '<button @click="handleEvent">传递事件</button> ' +
'</div>',
methods: {
handleEvent: function(event) {
bus.$emit('on-message',"my-component的内容"); //用总线发事件
}
}
});
var app1 = new Vue({
el: '#app1',
});
var app2 = new Vue({
el: '#app2',
data: {
message: ""
},
mounted: function() { //在mounted钩子函数里启动监听
var _this = this;
bus.$on("on-message",function(msg){ //监听总线事件
_this.message = msg;
})
},
})
- this.$parrent和this.$children能直接访问父子组件,不太推荐用,破坏封装性
7. slot
非命名和命名两种
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Vue test</title>
</head>
<body>
<div id="app" >
<my-component>
<h2 slot="header">标题</h2>
<p>正文</p>
<p>更多的正文</p>
<div slot="footer">底部信息</div>
<p>又正文???咋办</p>
</my-component>
</div>
<script src="https://cdn.staticfile.org/vue/2.2.2/vue.min.js"></script>
<script src="slot.js"></script>
</body>
</html>
Vue.component("my-component",{
template: '
<div class="container">
<div class="header">
<slot name="header"></slot>
</div>
<div class="main">
<slot>父组件没给的话,默认填充</slot>
</div>
<div class="footer">
<slot name="footer"></slot>
</div>
</div>',
});
var app = new Vue({
el: '#app',
});
作用域插槽:实现子向父传递数据
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Vue test</title>
</head>
<body>
<div id="app" >
<my-component>
<template slot-scope="props">
<p>来自父组件的</p>
<p>{{ props.msg }}</p>
</template>
</my-component>
</div>
<script src="https://cdn.staticfile.org/vue/2.2.2/vue.min.js"></script>
<script src="slot.js"></script>
</body>
</html>
//vue
Vue.component("my-component",{
template: ' <div>
<slot msg="子组件内容"></slot>
</div>'
});
var app = new Vue({
el: '#app',
});
8. 注
-
v-model="x" 相当于:value="x"和@input(handleX), 隐式声明了value
-
<input>中的@input和@changed区别在于
- input是只要输入就出发
- changed是文本框失去焦点或按enter后触发
-
watch
Vue.component('input-number', { watch: { currentValue: function(val) { this.$emit('input', val); this.$emit('on-change', val); }, value: function(val) { this.updateValue(val); } }, });
用于监控某个值是否变化,触发事件
9. 部署nginx服务器(linux)
最简单做法
-
/var/www/html 把打好的包扔到这里
-
改/etc/nginx/sites-available/default文件
#index index.html index.htm index.nginx-debian.html; index index_prod.html index_prod.htm;#换成自己的入口页面
-
service nginx restart