文章目录
前言
一、vue component组件?
1.引入库全局组件和私有组件
的基本定义 ?
有几个注意的事情 :
1)全局组件 component 建立在 vue 实例前
2)私有组件 componnets写在 全局 或者 vue实例内部
3)都可以在容器中使用 展示
4)需要特别注意 写法和格式
4)实现代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<style>
</style>
<body>
<div id="box">
<vue-header></vue-header>
<vue-footer></vue-footer>
</div>
</body>
</html>
<script>
// 这里定义的是全局组件
Vue.component('vue-header', {
template: '<h2>我是全局组件</h2>'
})
// 下面vue实例 定义的是 私有组件
var vm = new Vue({
el: '#box',
components: {
'vue-footer': {
template: '<h2>我是私有组件 </h2>'
}
},
})
</script>
页面展示效果
5) 再加了 一个 将 私有组件的template写在 上面 单独写出来 也是可以的
但是私有组件 不能互相访问 私有组件也不能访问全局组件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<style>
</style>
<body>
<div id="box">
<vue-header> </vue-header>
<vue-footer> </vue-footer>
<other></other>
</div>
<template id="other">
<h3>我是另外一个子组件</h3>
<!-- 下面这两个在这里无法使用 -->
<!-- <vue-footer></vue-footer>
<vue-footer></vue-footer> -->
</template>
</body>
</html>
<script>
// 这里定义的是全局组件
Vue.component(
'vue-header', {
template: '<h2>我是全局组件</h2>'
})
// 下面vue实例 定义的是 私有组件
var vm = new Vue({
el: '#box',
components: {
'vue-footer': {
template: '<h3>我是一个私有组件 </h3>'
},
// 这个定义的私有组件 它的template写在了上面
'other': {
template: "#other"
}
},
})
</script>
2. vue 动态组件
我们想简单实现一下 这个效果
我们怎么拆解一下?
1)先写右边两部分 我们把它写到一个里面
首先定义三个组件模板
<template id="writeback">
<div>
<div>回复我的</div>
<div>这是回复我的界面</div>
</div>
</template>
<template id="aite">
<div>
<div>@我的</div>
<div>这是@我的界面</div>
</div>
</template>
<template id="zan">
<div>
<div>收到的赞</div>
<div>这是收到赞的界面</div>
</div>
</template>
2)注册为私有组件
components: {
'writeback': {
template: '#writeback'
},
'aite': {
template: '#aite'
},
'zan': {
template: '#zan'
},
3)左边的部分就做好啦
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<style>
* {
margin: 0;
padding: 0;
}
body {
background-color: #67a3e1;
}
/* CSS属性 flex 规定了弹性元素如何伸长或缩短以适应flex容器中的可用空间 */
.bili-content {
display: flex;
}
.bili-content .bili-leftnav {
width: 200px;
background-color: #dee9f7;
}
.bili-content .bili-leftnav li {
padding: 10px 20px;
height: 50px;
line-height: 50px;
}
.bili-content .bili-leftnav li:hover {
cursor: pointer;
}
.bili-content .bili-leftnav .active {
color: #5faee3;
}
.bili-content .bili-rightcontent {
flex: 1;
margin-left: 20px;
}
.bili-content .bili-rightcontent div:nth-child(1) div {
margin-top: 10px;
background: #ffffff;
padding: 10px 10px;
}
</style>
<body>
<div id="box">
<div class="bili-content">
<div class="bili-leftnav">
<ul>
<!-- 点击之后将对应的内容赋给它 -->
<!-- 如果 showName被赋给对应的东西 就会触发 active -->
<li :class="{active:showName=='writeback'}" @click="showName='writeback'">回复我的</li>
<li :class="{active:showName=='aite'}" @click="showName='aite'">@我的</li>
<li :class="{active:showName=='zan'}" @click="showName='zan'">赞我的</li>
</ul>
</div>
// 右边的部分
<div class="bili-rightcontent">
<!-- 使用 动态组件 -->
<component :is="showName"></component>
</div>
</div>
</div>
<template id="writeback">
<div>
<div>回复我的</div>
<div>这里是回复我详细页面</div>
</div>
</template>
<template id="aite">
<div>
<div>@我的</div>
<div>这里是@我详细页面</div>
</div>
</template>
<template id="zan">
<div>
<div>赞我的</div>
<div>这里是赞我详细页面</div>
</div>
</template>
</body>
</html>
<script>
var vm = new Vue({
el: '#box',
data() {
return {
// 展示当前定义的组件 初始值设置为 writeback
showName: 'writeback'
}
},
// 定义组件
components: {
'writeback': {
template: '#writeback'
},
'aite': {
template: '#aite'
},
'zan': {
template: '#zan'
}
}
})
</script>
4)注意右边的部分
3. 我们来加一点 组件的动画
使用 <transition></transition>
来加
1.
<link href="https://cdn.jsdelivr.net/npm/animate.css@3.5.1" rel="stylesheet" type="text/css">
二、组件通信
1.组件通信 父组件传子组件
1)我们先来注册一个组件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<body>
<div id="box">
<!-- 在 根组件中使用 这个 定义的组件 -->
<userlistcom></userlistcom>
</div>
<!-- 写一个组件模版 -->
<template id="userlistcom">
<div>
<ul>
<li>测试一下这个组件是否注册成功了</li>
</ul>
</div>
</template>
</body>
</html>
<script>
var vm = new Vue({
el: '#box',
// 私有化 组册 组件
components: {
'userlistcom': {
template: '#userlistcom'
}
}
})
</script>
2) 我们现在没有后台 模拟一点假数据
3) 我们想使用 父组件的 数据 怎么弄?
我们先理清楚 这个逻辑
父传子 怎么传递 ?
1、 父组件在页面的created 生命周期调用了一个 loadData()函数 方法
2、里面将拿到的数据 赋给 父组件data 里面的userlist 属性
3、拿到值之后 怎么给子组件 ? ``绑一个名将这个值赋给 :getuserlist 这个 getuserlist 在子组件的props上
4、然后在 组件的props 里面 设置 type 类型 和 required 是否必须
5、然后 就可以在子组件的模版中 渲染出来了
6、页面渲染完成
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<style>
img {
width: 100px;
height: 100px;
}
</style>
<body>
<div id="box">
<!-- 在 根组件中使用 这个 定义的组件 -->
<!-- 给这个组件绑定了一个名字叫 getuserlist 值取得是下面的父组件的props里的userlist -->
<userlistcom :getuserlist="userlist"></userlistcom>
</div>
<!-- 写一个组件模版 -->
<template id="userlistcom">
<div>
<ul>
<li v-for="data in getuserlist">
<img :src="data.pic" alt="">
{{data.name}}
</li>
</ul>
</div>
</template>
</body>
</html>
<script>
var vm = new Vue({
el: '#box',
data() {
return {
userlist: [],
}
},
// 私有化 注册 组件
components: {
'userlistcom': {
template: '#userlistcom',
props: {
'getuserlist': {
// 传递的类型
type: Array,
// 是否必要
required: false
}
}
},
// 接受父组件传值
},
created() {
// 加载数据
this.loadData();
},
methods: {
// 初始化数据
loadData() {
console.log('数据正加载');
const res = [{
name: 'fu',
age: 18,
pic: './img/1.png'
},
{
name: 'wu',
age: 17,
pic: './img/2.png'
}
];
console.log('加载已经完成 ');
this.userlist = res;
}
}
})
</script>
2.组件通信 子组件传父组件
子组件 通过 $emit 将事件传递给父组件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<style>
img {
width: 100px;
height: 100px;
}
</style>
<body>
<div id="box">
<!-- 在 根组件中使用 这个 定义的组件 -->
<!-- 给这个组件绑定了一个名字叫 getuserlist 值取得是下面的父组件的props里的userlist -->
<userlistcom :getuserlist="userlist"></userlistcom>
<userformcom @submit="saveSubmit"></userformcom>
</div>
<!-- 写第一个组件模版 -->
<template id="userlistcom">
<div>
<ul>
<li v-for="data in getuserlist">
<img :src="data.pic" alt="">
{{data.name}}
</li>
</ul>
</div>
</template>
<!-- 写另外一个组件模版 -->
<template id="userformcom">
<div>
<form action="">
<input type="text" v-model="user.name">
<input type="text" v-model="user.age">
<input type="text" v-model="user.pic">
<select v-model="user.sex">
<option :value="sex.count" v-for="sex in sexlist">{{sex.name}}</option>
</select>
<button @click.prevent="submit">存储</button>
</form>
</div>
</template>
</body>
</html>
<script>
var vm = new Vue({
el: '#box',
data() {
return {
userlist: [],
}
},
// 私有化 注册 组件 这里面装的便是 子组件的内容
components: {
// 第一个子组件 userlistcom 里面包含的是它的相关的东西
'userlistcom': {
template: '#userlistcom',
props: {
'getuserlist': {
// 传递的类型
type: Array,
// 是否必要
required: false
}
},
},
// 第二个子组件 userformcom 里面包含的是它的东西
'userformcom': {
template: '#userformcom',
data() {
return {
user: {
name: 'lookroot',
age: 12,
sex: 2,
pic: ''
},
sexlist: [{
count: 1,
name: '男'
},
{
count: 2,
name: '女'
},
]
}
},
// userformcom子组件 methods 里面放它的 函数方法
methods: {
submit() {
// 利用 emit将事件传递给父组件 并且传递了 一个值为 user
this.$emit('submit', this.user)
}
}
}
},
// created 是父组件的方法 和components 是同等级的
created() {
// 加载数据
this.loadData();
},
// methods 是父组件的方法 和components created 是同等级的
methods: {
// 初始化数据
loadData() {
console.log('数据正加载');
const res = [{
name: 'fu',
age: 18,
pic: './img/1.png'
},
{
name: 'wu',
age: 17,
pic: './img/2.png'
}
];
console.log('加载已经完成 ');
this.userlist = res;
},
// 这个在父组件里面 接受子组件submit里面的emit 的传值 并合并数组
saveSubmit(user) {
// 浅拷贝
user = Object.assign({}, user);
// 把新的 user 放进 userlist 结果是实现数组合并的效果
this.userlist.push(user);
}
}
})
</script>
3.父组件触发子组件事件
1) 比如希望有个清空按钮 点击之后 会将表单内的数据清除掉
怎么操作?
2)
把完整的代码打出来
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<style>
img {
width: 100px;
height: 100px;
}
</style>
<body>
<div id="box">
<!-- 在 根组件中使用 这个 定义的组件 -->
<!-- 给这个组件绑定了一个名字叫 getuserlist 值取得是下面的父组件的props里的userlist -->
<userlistcom :getuserlist="userlist"></userlistcom>
<!-- ref 相当于组件的id 方便找到并且控制这个组件 -->
<userformcom @submit="saveSubmit" ref="userFormCom"></userformcom>
<button @click="clear"> 清空表单</button>
</div>
<!-- 写第一个组件模版 -->
<template id="userlistcom">
<div>
<ul>
<li v-for="data in getuserlist">
<img :src="data.pic" alt="">
{{data.name}}
</li>
</ul>
</div>
</template>
<!-- 写另外一个组件模版 -->
<template id="userformcom">
<div>
<form action="">
<input type="text" v-model="user.name">
<input type="text" v-model="user.age">
<input type="text" v-model="user.pic">
<select v-model="user.sex">
<option :value="sex.count" v-for="sex in sexlist">{{sex.name}}</option>
</select>
<button @click.prevent="submit">存储</button>
</form>
</div>
</template>
</body>
</html>
<script>
var vm = new Vue({
el: '#box',
data() {
return {
userlist: [],
}
},
// 私有化 注册 组件 这里面装的便是 子组件的内容
components: {
// 第一个子组件 userlistcom 里面包含的是它的相关的东西
'userlistcom': {
template: '#userlistcom',
props: {
'getuserlist': {
// 传递的类型
type: Array,
// 是否必要
required: false
}
},
},
// 第二个子组件 userformcom 里面包含的是它的东西
'userformcom': {
template: '#userformcom',
data() {
return {
user: {
name: 'lookroot',
age: 12,
sex: 2,
pic: ''
},
sexlist: [{
count: 1,
name: '男'
},
{
count: 2,
name: '女'
},
]
}
},
// userformcom子组件 methods 里面放它的 函数方法
methods: {
submit() {
// 利用 emit将事件传递给父组件 并且传递了 一个值为 user
this.$emit('submit', this.user)
},
// 初始化表单事件
clearForm() {
this.user = {}
}
},
}
},
// created 是父组件的方法 和components 是同等级的
created() {
// 加载数据
this.loadData();
},
// methods 是父组件的方法 和components created 是同等级的
methods: {
// 初始化数据
loadData() {
console.log('数据正加载');
const res = [{
name: 'fu',
age: 18,
pic: './img/1.png'
},
{
name: 'wu',
age: 17,
pic: './img/2.png'
}
];
console.log('加载已经完成 ');
this.userlist = res;
},
// 这个在父组件里面 接受子组件submit里面的emit 的传值 并合并数组
saveSubmit(user) {
// 浅拷贝
user = Object.assign({}, user);
// 把新的 user 放进 userlist 结果是实现数组合并的效果
this.userlist.push(user);
},
// 触发子组件事件
clear() {
// console.log(this.$refs.userFormCom.user)
this.$refs.userFormCom.clearForm();
}
}
})
</script>
4、vue 过滤和 自定义组件
1、先来一个全局的过滤
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<body>
<div id="app">
// 在数据 后面使用竖线 + 过滤器的名字 就可以使用
{{title | msgFormat}}
</div>
</body>
</html>
<script>
// 全局过滤 msgFormat 是过滤器的名字
Vue.filter('msgFormat', function (str) {
// 过滤方法 将前面的字符串替换掉
return str.replace('卧槽', '**')
})
var vm = new Vue({
el: '#app',
data() {
return {
// 这是一条数据
title: '卧槽真的好棒啊'
}
}
})
</script>
实现的结果
2、私有 过滤器的写法
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<body>
<div id="app">
{{title | msgFormat}} <br><br>
<!-- 注意这个地方过滤的是对象 所以需要使用.name .sex -->
{{user.name}}--{{user.sex | sexFormat}}
</div>
</body>
</html>
<script>
// 全局过滤
Vue.filter('msgFormat', function (str) {
return str.replace('卧槽', '**')
})
var vm = new Vue({
el: '#app',
data() {
return {
// 这里写的是数据
title: '卧槽真的好棒啊',
user: {
name: 'fhj',
sex: 1,
}
}
},
// 这个里面写的是私有的过滤
filters: {
sexFormat(sex) {
return sex == 1 ? '男' : '女';
}
}
})
</script>
5、vue 自定义指令
我将 全局和自定义指令写在一起 应该很容易理解
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<body>
<div id="app">
<h2 v-color="color">这里做全局自定义test</h2>
<h2 v-fontsize='fontsize'>这里定义的是私有的指令test</h2>
</div>
</body>
</html>
<script>
//全局自定义指令
Vue.directive('color', {
// 指令绑定的时候触发 el => dom val => 值
bind(el, val) {
el.style.color = val.value;
},
// 元素插入到页面的时候触发
inserted() {
console.log('元素插入到页面了')
},
// 元素更新的时候触发
updated() {},
})
// vue 实例化
var vm = new Vue({
el: '#app',
data() {
return {
color: '#f00',
fontsize: '60px'
}
},
// 定义私有自定义指令
directives: {
'fontsize': {
bind(el, val) {
// 注意这个 fontSize 需要使用驼峰命名法
// 因为它本来就是 dom里面的属性
el.style.fontSize = val.value;
}
}
}
})
</script>