Vue听课笔记(Vue2~Vue3)
一、初始Vue
1.1、声明式渲染
Vue.js 的核心是一个允许采用简洁的模板语法来声明式地将数据渲染进 DOM 的系统:
<div id="app">
{{ message }}
</div>
var app = new Vue({//此时app相当于一个对象
el: '#app',
data: {
message: 'Hello Vue!'//状态
}
})
- 想要使用Vue,首先要引入Vue文件
- 再在
script
标签中声明标签属到Vue
中进行new
- 需要使用
data
来定义变量
1.2、Vue的拦截原理
当你把一个普通的 JavaScript 对象传入 Vue 实例作为 data 选项,Vue 将遍历此对象所有的 property
,并使用 Object.defineProperty
把这些 property
全部转为 getter/setter
。Object.defineProperty
是 ES5 中一个无法 shim 的特性,这也就是 Vue 不支持 IE8 以及更低版本浏览器的原因。
<div id="box"></div>
<script>
var obj = {
}
var obox = document.getElementById("box")
Object.defineProperty(obj,"myname",{
get(){
console.log("get")
return obox.innerHTML
}
set(value){
console.log("set",value)
obox.innerHTML = value
}
})
</script>
- 缺陷
- 无法监听es6的Set,Map变化
- 无法监听Class类型的数据
- 属性的新加或者删除也无法监听
- 数组元素的增加和删除也无法监听
1.3、vue模板语法
- 用
@
(相当于v-on:
)标记的事件,即为Vue中的事件
<button @click="handleChange()">change</button>
再JavaScript中需要使用methods
来承接
methods:{
handleChange(){
console.log("handleChange")
}
}
- 类名属性使用
:
(相当于v-bind
)进行标记
<div :class="whichcolor"></div>
<img :src="imgpath"/>
再JavaScript中需要使用data
来承接
data:{
whichcolor:'colorname'
imgpath=''
}
- 标签内部的东西使用
{{}}
进行标记
<div id="box">
{{10+10}}
{{10>20>'aaa':'bbb'}}
</div>
再JavaScript中需要使用el
来承接
el:"box"
- 动态属性
<div id='box'>
<div :class="isColor?'red':'yellow'"></div>
<div :class="whichcolor"></div>
<button @click="handleChange()">change</button>
</div>
<script>
new Vue({
el:"#box",
data:{
isColor:true
}
methods:{
handleChange(){
this.isColor = !this.isColor
}
}
})
</script>
指令:是带有
v-
前缀的特殊属性
v-model
:双向绑定表单v-show
:动态显示与隐藏v-if
:动态创建与删除v-for
:列表渲染
<ul>
<li v-for="(item,index) in list">//括号里第一个参数是内容,第二个参数是索引
{{item}}-{{index}}
</li>
</ul>
data:{
list:["aaa","bbb","ccc"]
}
1.4、todolist案例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="https://cdn.jsdelivr.net/npm/vue@2.7.14/dist/vue.js"></script>
</head>
<body>
<div id="box">
<input type="text" v-model=" mytext"/>
<!-- {{mytext}} -->
<button @click="handleAdd()">add</button>
<ul v-show="datalist.length">
<li v-for="(data,index) in datalist">
{{data}}
<button @click="handleDel(index)">del</button>
</li>
</ul>
<div v-show="!datalist.length">待办事项空空如也</div>
</div>
<script>
var vm = new Vue({
el: "#box",
data: {
datalist: ["1111", "2222", "3333"],
mytext: "aaaaa"
},
methods: {
handleAdd() {
this.datalist.push(this.mytext)
this.mytext = ""
},
handleDel(index) {
console.log("del", index)
this.datalist.splice(index, 1)
}
}
})
</script>
</body>
</html>
1.5、-v-html
指令
在默认情况下,直接将带有标签的字符串,通过Vue解析到页面上,标签不会发生解析
如果加上-v-html
指令则可以使标签发生解析
<div id="box">
{{mytext}}//不会解析
<div v-html="mytext"></div>//会发生解析
</div>
<script>
new Vue({
el: "#box",
data:{
mytext: "<b>加粗的</b>"
}
})
1.6、点击变色
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="https://cdn.jsdelivr.net/npm/vue@2.7.14/dist/vue.js"></script>
<style>
* {
margin: 0;
padding: 0;
}
ul {
list-style: none;
display: flex;
}
li {
fLex: 1;
height: 50px;
line-height: 50px;
text-align: center;
}
.active {
background-color: aquamarine;
}
</style>
</head>
<body>
<div id="box">
<ul>
<li v-for="(data,index) in datalist" :class="current===index?
'active':''" @click="handleclick(index)">
{{data}}
</li>
</ul>
</div>
<script>
new Vue({
el: "#box",
data: {
datalist: ["首页", "列表", "我的"],
current: 0
},
methods: {
handleclick(index) {
console.log(index)
this.current = index
}
}
})
</script>
</body>
</html>
1.7、vue2-class&style
- 对象方法动态切换class值
<style>
.red{
background-color: red;
}
.yellow{
background-color: yellow;
}
.aa{}
.bb{}
.cc{}
</style>
<div id="box">
<div :class="whichClass">动态切换class-对象</div>
</div>
<script>
var vm = new Vue({
el: "#box",
data: {
classobj: {
aa: true,
bb: true,
cc: false
}
}
})
</script>
-
此时通过控制台控制对象
classobj
中key值的true
或者false
就可以控制代码块的颜色 -
问题:当通过控制台给标签添加一个对象中没有的
Class属性
无法加载到标签中- vue的特性 过期不候 ,在本身的对象中没有就无法加载进标签
-
解决方案(vue2):
- 使用
Vue.set
方法 Vue.set(对象,属性,true)
- 使用
Vue.set(vm.classobj,"dd",true)
- Vue3不用解决,自带的就好用
- 支持动态增加属性的拦截
- 数组方法动态切换class值
<style>
.red{
background-color: red;
}
.yellow{
background-color: yellow;
}
.aa{}
.bb{}
.cc{}
</style>
<div id="box">
<div :class="whicharr">动态切换class-数组</div>
</div>
<script>
var vm = new Vue({
el: "#box",
data: {
arr:['aa','bb']
}
})
</script>
- 与对象方法有同样的问题
- 通过使用数组的
增删改查
既可以改变class值
- 对象方法动态切换style值
<style>
.red{
background-color: red;
}
.yellow{
background-color: yellow;
}
.aa{}
.bb{}
.cc{}
</style>
<div id="box">
<div :style="styleobj">动态切换style-对象</div>
</div>
<script>
var vm = new Vue({
el: "#box",
data: {
styleobj:{
backgroundColor:'red'
}
}
})
</script>
- 可以通过控制台修改
backgroundColor
以的值来改变这个标签的属性 - 不能通过控制台给对象添加属性来添加标签的属性,同样需要使用
Vue.set(对象,属性,true)
的方法
- 数组方法动态切换style值
<style>
.red{
background-color: red;
}
.yellow{
background-color: yellow;
}
.aa{}
.bb{}
.cc{}
</style>
<div id="box">
<div :style="stylearr">动态切换style-数组</div>
</div>
<script>
var vm = new Vue({
el: "#box",
data: {
stylearr:[
{backgroundColor:'red'}
]
}
})
</script>
1.8、vue3-class&style
- 在Vue3中声明Vue的方式发生了改变,如果使用原来的方式会发生报错
Vue.creatApp(obj).mount('#box')
- 原来的声明式渲染也发生了改变
data(){
return {
myname:"asds",
mytext:''
}
}
- 在Vue3中,动态添加原来没有的属性可以直接通过在控制台上修改对象或者数组值即可
1.9、条件渲染
v-if
拥有条件分支v-else
起作用和正常的if...else
语句相同
案例:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="https://cdn.jsdelivr.net/npm/vue@2.7.14/dist/vue.js"></script>
</head>
<body>
<div id="box">
<h2>所有订单</h2>
<ul>
<li v-for='item in datalist'>
{{item.title}}---
<span v-if="item.state===0">未付款</span>
<span v-else-if="item.state===1">待发货</span>
<span v-else-if="item.state===2">已发货</span>
<span v-else>已签收</span>
</li>
</ul>
</div>
<script>
var vm = new Vue({
el: "#box", data: {
iscreated: false, datalist: [
{
title: "11111",
state: 0
},
{
title: "22222",
state: 1
},
{
title: "33333",
state: 2
},
{
title: "4444",
state: 3
}
]
}
})
</script>
</body>
</html>
- Vue提供了一个标签
template
- 就是一个包装元素,不会真正创建在页面上
- 可以用来隐藏一些元素而不破坏原来的dom结构
1.10、列表渲染
v-for
有两种表达方式v-for="变量 in 数组名 "
和v-for="变量 of 数组名 "
- 没有什么区别
- 在Vue中用这种方法也可以遍历对象
变量
处,第一个参数为value
值,第二个参数为key
值 v-for="变量 in 10 "
相当于遍历1~10
1.11、key设置
key
值- 在Vue中可以通过
key
值来智慧的判断删除的位置,元素或者是添加的位置 - key可以跟踪节点的身份,从而重用和重新排序现有的元素
- 理想中的key值是每一项都有唯一的id,data.id
- 在Vue中可以通过
1.12、检测数组变动
- 以下数组方法可以操作数组,可以检测变动
push()
pop()
shift()
unshift()
splice()
sort()
reverse()
- 以下方法不会对原数组产生影响
filter()
concat()
slice()
map()
新数组替换旧数组
- 不能检测一下变动的数组
vm.item[indexOfltem] = newValue
- 解决:
Vue.set
(example.items
,indexOfltem
,newValue
)splice
1.13、模糊查询
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="https://cdn.jsdelivr.net/npm/vue@2.7.14/dist/vue.js"></script>
</head>
<body>
<div id="box">
<input type="text" @input="handleInput" v-model="mytext">
<ul>
<li v-for="data in datalist" :key="data">
{{data}}
</li>
</ul>
</div>
<script>
var vm = new Vue({
el:"#box",
data:{
mytext:"",
datalist:["aaa","aac","acc","bbb","bbc","ccc"],
originlist:["aaa","aac","acc","bbb","bbc","ccc"],
},
methods:{
handleInput(){
this.datalist = this.originlist.filter(item=>item.includes(this.mytext))
}
}
})
</script>
</body>
</html>
第二种方法
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="https://cdn.jsdelivr.net/npm/vue@2.7.14/dist/vue.js"></script>
</head>
<body>
<div id="box">
<input type="text" v-model="mytext">
<ul>
<li v-for="data in test()" :key="data">
{{data}}
</li>
</ul>
</div>
<script>
var vm = new Vue({
el:"#box",
data:{
mytext:"",
datalist:["aaa","aac","acc","bbb","bbc","ccc"],
},
methods:{
test(){
return this.datalist.filter(item=>item.includes(this.mytext))
}
}
})
</script>
</body>
</html>
二、Vue相关修饰符
2.1、事件处理器
- 在Vue中,事件中使用函数不写(),也会默认传入一个参数,这个参数就相当于函数本身,可以拿到事件对象
<button @click="handleAddd1">add-函数名</button>
- 如果想要获取事件对象,还要求自己传参,就在第一个参数传
$event
即可
<button @click="handleAddd2($event,1,2)">add-函数表达式</button>
- 也可以直接在事件中写表达式,事件本身也可以启用
<button @click="count++">add-表达式</button>
2.2、事件修饰符
.stop
事件触发之后阻止冒泡
.self
只有点击自己才会触发事件,点击子辈标签没用
.once
只能点击一次
.prevent
阻止默认行为
模态框示例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="https://cdn.jsdelivr.net/npm/vue@2.7.14/dist/vue.js"></script>
<style>
#overlay {
background: rgba(0, 0, 0, 0.6);
width: 100%;
margin: auto;
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
}
#center {
background: #ffff;
border-radius: 5px;
/*边框圆角*/
padding-top: 15px;
padding-left: 30px;
padding-bottom: 15px;
width: 290px;
height: 160px;
position: fixed;
margin: auto;
left: 50%;
bottom: 50%;
}
</style>
</head>
<div id="box">
<button @click="isshow=true">登录</button>
<div id="overlay" v-show="isshow" @click.self="isshow=false">
<div id="center">
<div>用户名:<input type="text" /></div>
<div>密码:<input type="password" /></div>
<div>
<button>登录</button>
</div>
</div>
</div>
<body>
<script>
var vm =new Vue({
el:"#box",
data:{
isshow:false,
}
})
</script>
</body>
</html>
2.3、按键修饰符
.enter
当按下回车键时才会触发,用于按键标签
常见按键修饰符:
.esc
.up
.down
.left
.right
.space
.ctrl
.shift
.delete
这写修饰符可以组合起来用
使用方法:
- 可以直接在按钮后面加上修饰符
- 可以直接在按钮事件后面加上
.相关按键的key值
2.4、表单控件绑定
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="https://cdn.jsdelivr.net/npm/vue@2.7.14/dist/vue.js"></script>
</head>
<body>
<div id="box">
{{mytext}}
<textarea v-model="mytext"></textarea>
<div>
<div>用户名:<input v-model="mytext" /></div>
<input type="checkbox" v-model="isRemember" />记住用户名
<button @click="handleLogin">登录</button>
</div>
<div>
<h2>注册页面-兴趣爱好</h2>
<input type="checkbox" v-model="checkList" value="vue" /> vue
<input type="checkbox" v-model="checkList" value="react" />react
<input type="checkbox" v-model="checkList" value="wx" /> 小程序
</div>
{{checkList}}
<div>
<h2>性别选择</h2>
<input type="radio" v-model="select" value="a" />男
<input type="radio" v-model="select" value="b" />女
</div>
</div>
<script>
var vm = new Vue({
el: "#box",
data: {
mytext: localStorage.getItem("username"),
isRemember: true,
checkList: [],
select: "a"
},
methods: {
handleLogin() {
if (this.isRemember) {
localStorage.setItem("username", this.mytext)
}
console.log(this.mytext,this.checkList,this.select)
}
}
})
</script>
</body>
</html>
- 单选框
- 单选框可以给选项添加一个
v-model
双向指令,并且给每个选项赋上独特的value
值 - 通过选择value值来改变
v-model
双向指令中的值,从而改变选项
- 单选框可以给选项添加一个
- 多选框
- 多选框需要添加一个
v-model
双向指令,这个指令中需要是一个数组,并且给每个选项赋上独特的value
值 - 通过选择value值来添加或移除
v-model
双向指令中的值,从而添加或者移出选项
- 多选框需要添加一个
- 记住用户名
- 同样需要加上
v-model
双向指令给checkbox
框 - 这个双向指令需要是一个布尔类型的值,通过点击来判断布尔值
- 并且给登录框一个函数,通过操作真假来判断是否记住用户名
- 同样需要加上
- Vue的架构模式是mvvm(双向数据绑定)类型
2.5、购物车
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="https://cdn.jsdelivr.net/npm/vue@2.7.14/dist/vue.js"></script>
</head>
<style>
li {
dispLay: flex;
justify-content: space-around;
padding: 10px;
}
li img {
width: 100px;
}
</style>
<body>
<div id="box">
<input type="checkbox" v-model="isAll" @change="handleAllChecked">全选/全不选
<ul>
<li v-for="(item,index) in datalist" :key="item.id">
<input type="checkbox" v-model="checkList" :value="item"
@change="handleItemChecked"/>
<img :src="item.pic" />
<div>
<div>{{item.name}}</div>
<div style="color: red;">¥{{item.price}}</div>
</div>
<div>
<button @click="item.number--" :disabled="item.number===1">-</button>
<span>{{item.number}}</span>
<button @click="item.number++" :disabled="item.number===item.limit">+</button>
</div>
<div>
<button @click=handleDeleteClick(index,item.id)>删除</button>
</div>
</li>
</ul>
<div>总金额:{{sum()}}</div>
</div>
</body>
<script>
var vm = new Vue({
el: "#box",
isAll: false,
data: {
checkList: [],
datalist: [{
name: "商品1",
price: 10,
number: 1,
id: 1,
limit: 5,
pic: "#"
},
{
name: "商品2",
price: 20,
number: 2,
id: 2,
limit: 5,
pic: "#"
},
{
name: "商品3",
price: 30,
number: 3,
id: 3,
limit: 5,
pic: "#"
}]
},
methods: {
sum() {
var total = 0
this.checkList.forEach(item => {
total += item.number * item.price
})
return total
},
handleDeleteClick(index, id) {
this.datalist.splice(index, 1)
this.checkList = this.checkList.filter(item => item.id !== id)
this.handleItemChecked()
},
handleAllChecked() {
if(this.isAll){
this.checkList = this.datalist
}else{
this.checkList = []
}
},
handleItemChecked(){
if(this.checkList.length===this.datalist.length){
this.isAll = false
}else{
this.isAll = true
}
}
}
})
</script>
</html>
2.6、表单修饰符
.lazy
一般用于v-model
这个作用是当输入框失去焦点再进行同步数据
.number
输入框输出的值都是字符串,通过这个修饰符可转换为数值
.trim
可以去除输入内容首尾的空格
2.7、计算属性
- 计算属性(防止模板过重,难以维护),负责逻辑放在计算机中来写
- 计算属性需要放在一个新的节点中
computed
- 计算属性有缓存,基于依赖的缓存
案例
{{myComputedName}}
computed{
myComputedName(){
return this.myname.substring(0,1).toUpperCase()+myname.substring(1)
}
}
2.8、watch监听
- 主要用于处理异步的事件,比如使用定时器,可以是其异步进行
watch
也是一个新的节点,需要在Vue属性中写一个新节点- 监听一个值的改变,没有返回值,同步异步都可以,重视过程
三、前后端交互
3.1、fetch-get
<div id="box">
<button @click="handleFetch"></button>
</div>
<script>
new Vue=({
el:"#box",
methods:{
fetch("#")
.then(res=>res.json())
.then(res=>{
console.log(res)
})
.catch(err=>{
console.log(err)
})
}
})
</script>
3.2、fetch-post
- post-1
fetch("##",{
method : ' post ',
headers: {
"Content-Type": "application/x-www-form-urlencoded"
},
body : "name=kerwin&age=100",
}).then(res=>res.json()).then(res=>{console.log(res)
});
- post-2
fetch("##",{
method : ' post ',
headers: {
"Content-Type": "application/json"
},
body : JSON.stringify({
name:"kerwin",
age:100
}),
}).then(res=>res.json()).then(res=>{console.log(res)
});
3.3、axios
- Axios 是一个基于 promise 的网络请求库,可以用于浏览器和 node.js
- 需要引入
axios
文件
axios.get
<div id="box">
<button @click="handleFetch"></button>
</div>
<script>
new Vue=({
el:"#box",
methods:{
axios.get("##").then(res=>{
console.log(res.data)//axios里面自带一个data属性,并且json文件都这个data属性中
})
}
})
axios.post
<div id="box">
<button @click="handleFetch"></button>
</div>
// post-1
<script>
new Vue=({
el:"#box",
methods:{
axios.post("##","name=kerwin&age=100")
})
}
})
// post-2
<script>
new Vue=({
el:"#box",
methods:{
axios.post("##",{name=“kerwin",age=100})
})
}
})
3.4、猫眼数据
- 从后台引入数据以后有时还需要自行进行修改一下,可以通过函数的方式进行修改
3.5、过滤器
将原始数据通过过滤器进行相应的修饰
语法:原始数据|过滤器1名称|过滤器2名称
过滤器可以链式的写很多个
<img: src="item.img" | imgFilter|imgFilter2/>
<script>
Vue.filter("imgFilter",(url)=>{
return url.replace('xxx/','XXX')
})
Vue.filter("imgFilter2",(url)=>{
return url+'xxx'
})
</script>
注:过滤器Vue3 不支持
四、组件
4.1、组件定义
- 扩展HTML元素,封装可重用的代码
- 起名字: 驼峰写法,在HTML文件中驼峰处必须使用
-
链接 - dom片段没有代码提示没有高亮显示-vue单文件组件解决
- CSS只能写成行内。- vue单文件组件解决
template
只能包含由一个根节点- 组件是孤岛,无法【直接】访问外面的组件的状态或者方法。–间接的组件通信来交流。
- 自定义的组件data必须是一个函数,
- 所有的组件都在一起,太乱了 — vue单文件组件解决
全局组件
<div id="box">
<navbar></navbar>
</div>
<script>
//定义了一个全局组件
Vue.component("navbar",{
//dom,js,css
template:`dom`
methods:{},//方法
data(){},
watch:{},
})
</script>
4.2、全局&局部组件
- 在组件之内的
template
如果还包含有组件,那么这个包含的组件为外部组件的子组件 - 定义第一个组件的
component
模板里在此进行一次component
定义组件,这个组件就是局部组件 - 在内部定义的组件只能在父组件中使用,而外部定义的组件可以全局使用
- 在局部定义的组件中里面的方法等定义方式与组件定义方式一模一样
4.3、父传子
- 给要调用的组件加上一个自定义的属性,如果调用相同的组件,但是想要不同的值,自定义的属性就赋上不同的值
<div id="box">
<navbar myname="a"></navbar>
<navbar myname="b"></navbar>
</div>
- 在定义组件的
component
中加上props:[]
在这个数组中引入你的自定义属性
Vue.component("navbar",{
prop:["myname"],
})
- 如果想传入布尔值来控制相关标签的出现隐藏,需要使用动态属性的方式给自定义属性
<div id="box">
<navbar myname="a" :myright="false"></navbar>
<navbar myname="b" :myright="true"></navbar>
</div>
<script>
Vue.component("navbar",{
prop:["myname","myright"],
})
</script>
4.4、属性验证&默认属性
属性验证:在传入我们的自定义属性时,可以通过属性验证进行验证,即将原来prop数组改编成prop对象
prop:{
myname=String,
myright=Boolean
},
- 有些情况下,我们希望有个默认属性,即在不给某次调用组件时自定义属性加值时,也可以让其有一个默认行为
prop:{
myname:{
type:String,
default:""
},
myright:{
type:Boolean,
default:true
}
4.5、子传父与父传子
- 父传子的形式:
- 父传子使用属性
- 定义的组件内无法使用根组件的定义的属性,不过可以通过动态属性的方式定义自定义属性给子组件,这时子代就能用了
- 子传父的形式:
- 子传父使用事件
- 现在子组件中定义一个方法,这个方法里面加上
this.$emit("父组件方法名")
这样启动子组件事件时就会触发父组件方法,这样就可以通过方法的启用来影响父组件,子方法中传入参数也能在父方法中出现
4.6、中间人模式
-
现在第一个组件中使用事件与父组件形成交互
-
当父组件收到了信息之后,再通过属性的方式,将数据再出给子组件的兄弟组件,这样就可以使数据再两个兄弟组件之间传播
-
这种模式成为中间人模式
4.7、中央事件总线
-
在发布者的组件中的方法里面添加
bus.$emit("方法名")
-
在外面设置一个
bus
即var bus = new Vue()
-
在订阅者的组件中创建一个生命周期函数
mounted
-
再将从发布者组件中获取的方法以
bus.$on("方法名",()=>{ })
的方法使传到订阅者组件中
4.8、ref组件通信
- ref -绑定dom节点,拿到的就是dom对象
- ref -绑定组件,拿到的就是 组件对象
给dom节点绑定ref="属性名"
属性,就可以使用this.$refs.属性名
的方式获取
- 给组件绑定节点的方式与dom的方式相同
- 需要注意的是,当给组件绑定ref组件以后父组件也可以直接修改到子组件内部定义的状态,在子组件的
data(){}
内部定义的属性可以被父组件通过ref直接获取并修改 - 如果组件状态出现问题,就很难查到问题的出现
- 容易造成数据流的紊乱
- 需要注意的是,当给组件绑定ref组件以后父组件也可以直接修改到子组件内部定义的状态,在子组件的
4.9、组件注意
属性:父组件传给组件的属性,只有父组件可以重新传,但不允许子组件随意修改
- 如果修改了属性,也会在下一次刷新网页时被父组件的原来属性给变回去
- 可能会导致父组件属性和子组件属性的不统一,造成紊乱
状态:组件内部的状态,可以随意修改
- 当出现
v-once
时,修改状态也不会影响页面
4.10、动态组件
选项卡案例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="https://cdn.jsdelivr.net/npm/vue@2.7.14/dist/vue.js"></script>
</head>
<body>
<div id="box">
<keep-alive>
<component :is="which"></component>
</keep-alive>
<footer>
<ul>
<li @click=" which= '' home ' ">
首页
</li>
<li @click=" which=' list' ">
列表
</li>
<li @click=" which='shopcar' ">
购物车
</li>
</ul>
</footer>
</div>
<script>
Vue.component("home", {
template: `
<div>
home
<input type="search"/>
</div>
`
})
Vue.component("list", {
template: `
<div>
list
<input type="search"/>
</div>
`
})
Vue.component("shopcar", {
template: `
<div>
shopcar
<input type="search"/>
</div>
`
})
</script>
</body>
</html>
component
动态组件,Vue自带的一个组件- 可以通过
:is="组件名"
动态的设置组件 - 在动态组件的基础上再加
<keep-alive></keep-alive>
标签,可以使动态组件里的内容得以保存