注册方式
1.全局注册
Vue.component
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title>Examples</title>
<meta name="description" content="">
<meta name="keywords" content="">
<link href="" rel="stylesheet">
<style>
.navbar{
background: red;
}
</style>
<script type="text/javascript" src="lib/vue.js"></script>
</head>
<body>
<div id="box">
<navbar></navbar>
<sidebar></sidebar>
<navbar></navbar>
<!-- <app-child></app-child> -->
</div>
<script type="text/javascript">
//1. 全局定义组件 (作用域隔离)
Vue.component("app-child",{
template: `
<div>child</div>
`
})
Vue.component("navbar",{
template: `<nav style="background:red">
<button @click="handleClick()">返回-{{text}}</button>
<span>导航栏</span>
<app-child></app-child>
<navbarchild></navbarchild>
</nav>`,
data(){
return {
text:"111111"
}
// 组件与组件 的状态需要相互隔离, 要设计成函数。
},
methods:{
handleClick(){
console.log("click--navbar");
this.text="222222";
}
},
components:{
navbarchild:{
template:`<div>navbarchild--{{title}}</div>`,
data(){
return {
title:"111111111"
}
}
}
}
})
Vue.component("sidebar",{
template: `<div style="background:blue">
<ul @click="handleClick">
<li>1111</li>
<li>2222</li>
<li>3333</li>
</ul>
<app-child></app-child>
<navbarchild></navbarchild>
</div>`,
methods:{
handleClick(){
console.log("click--sidebar");
}
}
})
var vm = new Vue({
el:"#box"
}) //根组件(root )
</script>
</body>
</html>
2.局部组件
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title>Examples</title>
<meta name="description" content="">
<meta name="keywords" content="">
<link href="" rel="stylesheet">
<style>
.navbar{
background: red;
}
</style>
<script type="text/javascript" src="lib/vue.js"></script>
</head>
<body>
<div id="box">
{{title}}
<!-- <img :src="title"/> -->
<navbar myword="home" :myshow="false"></navbar>
<navbar myword="list" :myshow="true"></navbar>
<navbar myword="shopcar" :myshow="true"></navbar>
<navbar :myword="title" :myshow="true"></navbar>
<!-- <app-child></app-child> -->
</div>
<script type="text/javascript">
//1. 全局定义组件 (作用域隔离)
Vue.component("navbar",{
template: `<nav style="background:red">
<button @click="handleClick()" v-show="myshow">返回-{{text}}</button>
<span>导航栏--{{myword}}---{{myshow}}</span>
</nav>`,
//接受父组件传来的属性
// props:["myword","myshow"],
//属性验证
props:{
myword:String,
myshow:Boolean
},
data(){
return {
text:"111111"
}
// 组件与组件 的状态需要相互隔离, 要设计成函数。
},
methods:{
handleClick(){
console.log("click--navbar");
this.text="222222";
}
}
})
var vm = new Vue({
el:"#box",
data:{
title:"根组件中定义的title"
}
}) //根组件(root )
</script>
</body>
</html>
以上涉及到父传子,属性验证
type:String, Boolean, Array, Object, Function, Symbol
required 必填
default 默认值
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>lesson 15</title>
<script src="https://unpkg.com/vue@next"></script>
</head>
<body>
<div id="root"></div>
</body>
<script>
const app = Vue.createApp({
data() {
return { num: 1234 }
},
template: `
<div><test :content="num" /></div>
`
});
// type:String, Boolean, Array, Object, Function, Symbol
// required 必填
// default 默认值
app.component('test', {
props: {
content: {
type: Number,
//校验
validator: function(value) {
return value < 1000;
},
default: function() {
return 456;
}
}
},
template: `<div>{{content}}</div>`
});
const vm = app.mount('#root');
</script>
</html>
单项数据流
父组件调用子组件,多个数据项可以使用一个对象进行塞值:
v-bind="params"等于子组件的
:content="params.content" :a="params.a" :b="params.b" :c="params.c"
属性传的时候,使用 content-abc 这种命名,子组件接的时候,使用 contentAbc 命名
// 单项数据流的概念: 子组件可以使用父组件传递过来的数据,但是绝对不能修改传递过来的数据
Non-prop属性
如果父组件传给子组件的参数,子组建并没有prop对应的参数来接,那么该属性将直接由子组件最外层html标签继承,这种情况就叫Non-prop属性,如何让子组件避免这种传递:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>lesson 17</title>
<script src="https://unpkg.com/vue@next"></script>
</head>
<body>
<div id="root"></div>
</body>
<script>
// Non-prop 属性
const app = Vue.createApp({
template: `
<div>
<counter msg="hello"/>
</div>
`
});
app.component('counter', {
inheritAttrs: false,
template: `
<div>Counter</div>
`
});
const vm = app.mount('#root');
</script>
</html>
如果子组件没有最外层html标签。也可以指定某个标签继承。更可以分别继承。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>lesson 17</title>
<script src="https://unpkg.com/vue@next"></script>
</head>
<body>
<div id="root"></div>
</body>
<script>
// Non-prop 属性
const app = Vue.createApp({
template: `
<div>
<counter msg="hello" msg1="hello1" />
</div>
`
});
app.component('counter', {
// inheritAttrs: false,
mounted() {
console.log(this.$attrs.msg);
},
template: `
<div :msg="$attrs.msg">Counter</div>
<div v-bind="$attrs">Counter</div>
<div :msg1="$attrs.msg1">Counter</div>
`
});
const vm = app.mount('#root');
</script>
</html>
子传父
父传子属性往下传,子传父事件向上传。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title>Examples</title>
<meta name="description" content="">
<meta name="keywords" content="">
<link href="" rel="stylesheet">
<script type="text/javascript" src="lib/vue.js"></script>
</head>
<body>
<div id="box">
<child @myevent="handleMyEvent($event)"></child>
</div>
<script type="text/javascript">
//子组件
Vue.component("child",{
template:`<div>
child-<button @click="handleClick">send</button>
</div>`,
data(){
return {
money:1000000
}
},
methods:{
handleClick(){
console.log("把消息传给父组件")
this.$emit("myevent",this.money);// emit 分发
}
}
})
var vm = new Vue({
el:"#box",
data:{
},
methods:{
handleMyEvent(data){
console.log("我收到了钱",data)
}
}
})
</script>
</body>
</html>
子传父案例——卖座
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title>Examples</title>
<meta name="description" content="">
<meta name="keywords" content="">
<link href="" rel="stylesheet">
<script type="text/javascript" src="lib/vue.js"></script>
</head>
<body>
<div id="box">
<navbar @myevent="control"></navbar>
<sidebar v-show="isShow"></sidebar>
</div>
<script type="text/javascript">
//子组件
Vue.component("navbar",{
template:`<div>
navbar--<button @click="handleClick">show/hide</button>
</div>`,
methods:{
handleClick(){
this.$emit("myevent");
}
}
})
Vue.component("sidebar",{
template:`<div>
sidebar
<ul>
<li>1111</li>
<li>1111</li>
<li>1111</li>
<li>1111</li>
<li>1111</li>
<li>1111</li>
<li>1111</li>
</ul>
</div>`
})
var vm = new Vue({
el:"#box",
data:{
isShow:false
},
methods:{
control(){
this.isShow = !this.isShow;
}
}
})
</script>
</body>
</html>
ref通信
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title>Examples</title>
<meta name="description" content="">
<meta name="keywords" content="">
<link href="" rel="stylesheet">
<script type="text/javascript" src="lib/vue.js"></script>
</head>
<body>
<div id="box">
<button @click="handleClick()">get</button>
<child ref="mychild"></child>
<input type="text" ref="mytext"/>
<button @click="handleAdd">add</button>
</div>
<script type="text/javascript">
//子组件
Vue.component("child",{
template:`<div>
child 子组件
</div>`,
data(){
return {
childname:"11111111111111111111"
}
},
methods:{
handleClick(data){
console.log("child-11111",data)
}
}
})
var vm = new Vue({
el:"#box",
data:{
},
methods:{
handleClick(){
console.log(this.$refs.mychild.childname); //获取引用
this.$refs.mychild.handleClick("给你5管麻药");//调用的子组件的方法
},
handleAdd(){
console.log("handleAdd",this.$refs.mytext.value)
}
}
})
</script>
</body>
</html>
bus事件总线(组件非父子通信)
根本不在组件结构之外的对象,该如何通信?
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title>Examples</title>
<meta name="description" content="">
<meta name="keywords" content="">
<link href="" rel="stylesheet">
<script type="text/javascript" src="lib/vue.js"></script>
</head>
<body>
<div id="box">
<child1></child1>
<child2></child2>
</div>
<script type="text/javascript">
// eventEmitter .on .emit
var bus = new Vue()// 空vue实例 中央事件总线
Vue.component("child1",{
template:`<div>
child1---<button @click="handleClick">通信</button>
</div>`,
methods:{
handleClick(){
// 向自己兄弟child1 发送一句
// setInterval(() => {
// bus.$emit("kerwin","兄弟,这是麻药");
// }, 1000)
bus.$emit("kerwin");
}
},
mounted(){
console.log("这个函数会在child1组件创建成功后自动被vue调用")
}
})
Vue.component("child2",{
template:`<div>
child2--一直显示
<ul v-show="isShow">
<li>111111</li>
</ul>
</div>`,
data(){
return {
isShow:true
}
},
mounted(){
console.log("这个函数会在child2组件创建成功后自动被vue调用")
bus.$on("kerwin",(data)=>{
// console.log(data);
this.isShow = !this.isShow
})
}
})
new Vue({
el:"#box",
// template:"<div>hello template</div>"
})
</script>
</body>
</html>
父子组件通过事件进行通信
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>lesson 18</title>
<script src="https://unpkg.com/vue@next"></script>
</head>
<body>
<div id="root"></div>
</body>
<script>
const app = Vue.createApp({
data() {
return {
count: 1
}
},
methods: {
handleAddOne() {
this.count += 1;
}
},
template: `
<counter :count="count" @add-one="handleAddOne"/>
`
});
app.component('counter', {
props: ['count'],
methods: {
handleClick() {
this.$emit('addOne');
}
},
template: `
<div @click="handleClick">{{count}}</div>
`
});
const vm = app.mount('#root');
</script>
</html>
如下表示子组件传递到父组件的参数可以带数值到父组件方法:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>lesson 18</title>
<script src="https://unpkg.com/vue@next"></script>
</head>
<body>
<div id="root"></div>
</body>
<script>
const app = Vue.createApp({
data() {
return {
count: 1
}
},
methods: {
handleAddOne(param) {
this.count += param;
}
},
template: `
<counter :count="count" @add-one="handleAddOne"/>
`
});
app.component('counter', {
props: ['count'],
methods: {
handleClick() {
this.$emit('addOne',2);
}
},
template: `
<div @click="handleClick">{{count}}</div>
`
});
const vm = app.mount('#root');
</script>
</html>
v-model使用:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>lesson 18</title>
<script src="https://unpkg.com/vue@next"></script>
</head>
<body>
<div id="root"></div>
</body>
<script>
const app = Vue.createApp({
data() {
return { count: 1 }
},
template: `
<counter v-model="count" />
`
});
app.component('counter', {
props: ['modelValue'],
methods: {
handleClick() {
this.$emit('update:modelValue', this.modelValue + 3);
}
},
template: `
<div @click="handleClick">{{modelValue}}</div>
`
});
const vm = app.mount('#root');
</script>
</html>
如上使用,props中必须为modelValue
,触发事件也必须叫update:modelValue
,但可以如下写法:
const app = Vue.createApp({
data() {
return { count: 1 }
},
template: `
<counter v-model:app="count" />
`
});
app.component('counter', {
props: ['app'],
methods: {
handleClick() {
this.$emit('update:app', this.app + 3);
}
},
template: `
<div @click="handleClick">{{app}}</div>
`
});
以上可以用于父子组件双向绑定时使用。
更深入扩展,可以多参数像这样简写:
const app = Vue.createApp({
data() {
return { count: 1 ,count1: 1 }
},
template: `
<counter v-model:count="count" v-model:count1="count1" />
`
});
app.component('counter', {
props: ['count','count1'],
methods: {
handleClick() {
this.$emit('update:count', this.count + 3);
},
handleClick1() {
this.$emit('update:count1', this.count1 + 3);
}
},
template: `
<div @click="handleClick">{{count}}</div>
<div @click="handleClick1">{{count1}}</div>
`
});
v-model默认绑定一个固定的参数modelModifiers,可以绑定修饰符:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>lesson 19</title>
<script src="https://unpkg.com/vue@next"></script>
</head>
<body>
<div id="root"></div>
</body>
<script>
const app = Vue.createApp({
data() {
return {
count: 'a',
}
},
template: `
<counter v-model.uppercase="count" />
`
});
app.component('counter', {
props: {
'modelValue': String,
'modelModifiers': {
//不传递的时候,传一个空对象
default: ()=> ({})
}
},
methods: {
handleClick() {
let newValue = this.modelValue + 'b';
if(this.modelModifiers.uppercase) {
newValue = newValue.toUpperCase();
}
this.$emit('update:modelValue', newValue);
},
},
template: `
<div @click="handleClick">{{modelValue}}</div>
`
});
const vm = app.mount('#root');
</script>
</html>
网友评论