主要内容:vue中的组件及传参
- 事件类型-通过@click=来绑定对应的方法
- 注册组件(全局组件及局部组件)
- 通过template来进行模块优化
- 传参方法
- 使用自定义属性向组件传参
- 使用data()向组件传参
- 混合传参
- 传参方向
- 父组件向子组件传参
- 子组件验证从父组件接收的参数
- 子组件向父组件传递消息($emit)
1. 事件类型
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>事件</title>
<script src="../lib/vue.js"></script>
</head>
<body>
<div class="app">
<!-- v-on:事件类型 -->
<p>
<!-- <button v-on:click="num++">点赞</button>已被点赞<span style="color:red"> {{num}} </span> 次</span> -->
<button @click="num++">点赞</button>已被点赞<span style="color:red"> {{num}} </span> 次</span>
</p>
<p>
<button @click="liked">点赞</button>已被点赞<span style="color:red"> {{num}} </span> 次</span>
</p>
<p>
<button @click="whoami('朱老师')">我是谁? </button><span>{{name}}</span>
</p>
<!-- 如果要访问原生的事件对象Event, 第一使用固定的参数名$event, 而且必须是最后一个参数(多个参数时) -->
<ul @click="show($event)">
<li v-for="item of animal">{{item}}</li>
</ul>
</div>
<script>
const vm = new Vue({
el: ".app",
data: {
num: 3456,
name:null,
animal: ['小猪', '小狗', '小猫'],
},
//事件方法
methods: {
liked() {
this.num++;
},
whoami(name){
this.name = name;
},
show(event) {
// 这个地方传参event不用加$,但前面的时候需要加。
// console.log(event.target);
// console.log(event.currentTarget);
alert(`您喜欢的小动物是: ${event.target.innerHTML}`);
}
},
});
</script>
</body>
</html>
2. 注册组件
- 全局组件:在所有的vue实例中都可以用
- 局部组件:只限于在当前实例中使用
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<script src="../lib/vue.js"></script>
<title>注册组件</title>
</head>
<body>
<div class="app">
<!-- 加载到页面中的挂载点中 -->
<global-component></global-component>
<!-- 局部组件 -->
<local-component1></local-component1>
<local-component2></local-component2>
</div>
<hr />
<div class="app2">
<!-- 加载到页面中的挂载点中 -->
<global-component></global-component>
<!-- <local-component1></local-component1> -->
</div>
<script>
// 1. 全局组件:在所有的vue实例中都可以用
// Vue.component(组件标签, 组件的模板内容)
Vue.component("global-component", {
// template: 用户自定义的组件模板的内容
template: "<p>我是一个全局组件</p>",
});
const vm = new Vue({
el: ".app",
// 局部组件: 只限于在当前实例中使用
components: {
"local-component1": {
template: "<p>我是一个局部组件1</p>",
},
"local-component2": {
template: "<p>我是一个局部组件2</p>",
},
},
});
const vm2 = new Vue({
el: ".app2",
});
</script>
</body>
</html>
3. 组件模块的优化
- 通过<template></template>中的 id 在vue.component中进行对应绑定
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<script src="../lib/vue.js"></script>
<title>组件模板的优化</title>
</head>
<body>
<div class="app">
<global-component></global-component>
<local-component></local-component>
</div>
<!-- <script type="x-template" id="g-com1">
<div class="cart">
<h3>购物车</h3>
<ul>
<li>汽车</li>
<li>裤子</li>
<li>苹果</li>
</ul>
</div>
</script> -->
<template id="g-com1">
<div class="cart">
<h3>购物车</h3>
<ul>
<li>火车</li>
<li>裤子</li>
<li>苹果</li>
</ul>
</div>
</template>
<!-- 局部组件 -->
<template id="l-com1">
<p>Hello 我是局部组件对应的模板内容</p>
</template>
<script>
// 全局组件
Vue.component("global-component", {
// template: `
// <div class="cart">
// <h3>购物车</h3>
// <ul>
// <li>汽车</li>
// <li>裤子</li>
// <li>苹果</li>
// </ul>
// </div>
// `,
// 这里要有一个标识和上面的script type="x-template"进行绑定
template: "#g-com1",
});
const vm = new Vue({
el: ".app",
// 局部组件
components: {
"local-component": {
template: "#l-com1",
},
},
});
</script>
</body>
</html>
4. 使用自定义属性向组件传参
- <template></template>来设置
- 通过id在vue.component中进行绑定
- 并通过props: [‘’, ‘’, ‘’]来传参数
- 最后在dom中通过具体变量名来渲染
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>使用自定义属性向组件传参</title>
<script src="../lib/vue.js"></script>
</head>
<body>
<div class="app">
<!-- 通过属性向组件传参 -->
<my-component id="1" name="peter" email="peter@php.cn"></my-component>
</div>
<template id="user">
<ul>
<li>ID: {{id}}</li>
<li>姓名: {{name}}</li>
<li>邮箱: {{email}}</li>
</ul>
</template>
<script>
// 注册组件
Vue.component("my-component", {
template: "#user",
// 在组件中使用props属性来接收通过组件标签的属性传递过来的参数
props: ["id", "name", "email"],
});
const vm = new Vue({
el: ".app",
});
</script>
</body>
</html>
5. 使用data()向组件传参
- 与前面不同的是props为空[]
- 增加了一个data()function,在其中返回具体的赋值,并且将data:{}在vue实例中体现
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>使用data()向组件传参</title>
<script src="../lib/vue.js"></script>
</head>
<body>
<div class="app">
<!-- 通过属性向组件传参 -->
<my-component></my-component>
</div>
<template id="user">
<ul>
<li>ID: {{id}}</li>
<li>姓名: {{name}}</li>
<li>邮箱: {{email}}</li>
</ul>
</template>
<script>
// 注册组件
Vue.component("my-component", {
template: "#user",
// 在组件中使用props属性来接收通过组件标签的属性传递过来的参数
props: [],
data() {
return {
id: 2,
name: "朱老师",
email: "peter@php.cn",
};
},
});
const vm = new Vue({
el: ".app",
data: {},
});
</script>
</body>
</html>
6. 使用data()和属性向组件传参
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>使用data()和属性向组件传参</title>
<script src="../lib/vue.js"></script>
</head>
<body>
<div class="app">
<!-- 通过属性向组件传参 -->
<my-component blog="https://php.cn/hello.html"></my-component>
</div>
<template id="user">
<ul>
<li>ID: {{id}}</li>
<li>姓名: {{name}}</li>
<li>邮箱: {{email}}</li>
<!-- <li>博客:<a v-bind:href="blog">{{blog}}</a></li> ,下面为简化,去掉了v-bind-->
<li>博客:<a :href="blog">{{blog}}</a></li>
</ul>
</template>
<script>
// 注册组件
Vue.component("my-component", {
template: "#user",
// 自定义属性与data()方法共同向组件传参
props: ["blog"],
data() {
return {
id: 2,
name: "朱老师",
email: "peter@php.cn",
};
},
});
const vm = new Vue({
el: ".app",
data: {},
});
</script>
</body>
</html>
7. 父组件向子组件传参
- 在vue实例中通过data:{user:{}}对象来赋值
- 通过<template></template>,vue.component来创建子组建并绑定
- 跟上面在vue.component中的data()function来赋值还是不同的。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>父组件向子组件传参</title>
<script src="../lib/vue.js"></script>
</head>
<body>
<!-- 父组件:唯一的 -->
<div class="app">
<!-- 子组件: 可以有多个,可以由全局组件或局部组件充当 -->
<!-- 用自定义属性来实现父组件向子组件传参 -->
<my-component :user="user"></my-component>
</div>
<template id="user">
<ul>
<li>ID: {{user.id}}</li>
<li>姓名: {{user.name}}</li>
<li>邮箱: {{user.email}}</li>
</ul>
</template>
<script>
// 注册: 全局组件
Vue.component("my-component", {
template: "#user",
// 子组件中接收一个父组件传递过来的user对象
props: ["user"], // 这个地方也需要有
});
const vm = new Vue({
el: ".app",
data: {
user: {
id: 3,
name: "王文军",
email: "wwj@php.cn",
},
},
});
</script>
</body>
</html>
8. 子组件验证从父组件接收的参数
- 也就是在props:[]中进行一些基本的限定,例如类型,如果不对就返回false
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>子组件验证从父组件接收的参数</title>
<script src="../lib/vue.js"></script>
</head>
<body>
<!-- 父组件:唯一的 -->
<div class="app">
<!-- 子组件: 可以有多个,可以由全局组件或局部组件充当 -->
<!-- 用自定义属性来实现父组件向子组件传参 -->
<my-component :user="user" :blog="blog"></my-component>
</div>
<template id="user">
<ul>
<li>ID: {{user.id}}</li>
<li>姓名: {{user.name}}</li>
<li>邮箱: {{user.email}}</li>
<li>博客: <a :href="blog">{{blog}}</a></li>
</ul>
</template>
<script>
// 注册: 全局组件
Vue.component("my-component", {
template: "#user",
// 下面这个地方就相当于在做验证,跟前面就有区别了。
props: {
user: Object,
blog: {
type: String,
default: "https://www.php.cn/default.html",
},
},
});
const vm = new Vue({
el: ".app",
data: {
user: {
id: 3,
name: "王文军",
email: "wwj@php.cn",
},
blog: "https://www.php.cn/hello.html",
},
});
</script>
</body>
</html>
9. 子组件向父组件传递消息
- 子组件向父组件传递消息(全是通过事件,呼叫父组件来响应 $emit)
- 仍是通过自定义属性进行交互
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>子组件向父组件传递消息</title>
<script src="../lib/vue.js"></script>
</head>
<body>
<div class="app">
<my-component
:product="product"
@count="total"
<!-- count是一个方法,而非一个属性,因此绑定用@,而非:冒号 -->
<!-- total是一个表达式,然后下一面一行中的total再和父组件中的方法进行绑定-->
:total="total"
></my-component>
<span style="float: right; margin-right: 50px;"
>总计: {{totalPrice}} 元</span
>
</div>
<template id="cart">
<table
border="1"
width="80%"
align="center"
cellspacing="0"
cellpadding="5"
>
<caption>
购物车
</caption>
<tr bgcolor="lightblue">
<th>ID</th>
<th>品名</th>
<th>单价</th>
<th>数量</th>
</tr>
<tr v-for="item of product"> //这个地方用of或in都可以
<td>{{item.id}}</td>
<td>{{item.name}}</td>
<td>{{item.price}}</td>
<td><input type="number" v-model="item.num" @change="count" /></td>
<!-- 这块主要是为了可以修改 -->
</tr>
</table>
</template>
<script>
Vue.component("my-component", {
template: "#cart",
props: ["product"],
methods: {
count() {
// 向父组件发送消息,调用父组件的total()
this.$emit("count");
},
},
});
const vm = new Vue({
el: ".app",
data: {
product: [
{ id: 1, name: "电脑", price: 5000, num: 1 },
{ id: 2, name: "手机", price: 3000, num: 1 },
],
totalPrice: 0,
},
mounted() {
this.total();
},
methods: {
total() {
this.totalPrice = 0;
this.forEach((item) => {
this.totalPrice += item.num * item.price;
});
},
},
});
// 子组件向父组件传递消息(全是通过事件,呼叫父组件来响应)
// 仍是通过自定义属性进行交互
</script>
</body>
</html>