一、子组件传值父组件
子组件调用父组件的方法:
1. 在父组件中给引用的子组件注册一个事件(这个事件的名字是自定义的) **相当于给两个组件直接建立联系**
2. 子组件可以触发这个事件$emit('事件名字')
子组件给父组件传递数据:
- $emit方法第二个参数可以定义子组件给父组件传递的内容
- 在父组件中怎么拿到这内容
2.1 父组件这个方法没有自定参数,在父组件的方法直接加这个参数就可以拿到 ⭐ 易错点
2.2 父组件有自定义参数,可以传入 e v e n t 也可以拿到子组件传递的数据。通过 event也可以拿到子组件传递的数据。通过 event也可以拿到子组件传递的数据。通过event只能传递第一个参数。
具体步骤:
子传父,需要写两个组件,一个为子组件,一个为父组件,然后把子组件的调用放到父组件中,
给父组件加一个自定义事件,通过自定义事件,在子组件里面通过this.$emit实现子组件给父组件传参,然后通过给子组件的模板中加一个点击事件,然后通过点击事件实现子组件给父组件传参的目的
body区域
<div id='app'>
<father></father>
</div>
<template id="fatherFn">
<div>
<son @getson="getson1($event)"></son>
<!-- 给父组件中的子组件注册事件,相当于给两个组件直接建立联系 -->
<!-- 2.1 父组件这个方法没有自定参数,在父组件的方法直接加这个参数就可以拿到 ⭐ 易错点 -->
<!-- 2.2 父组件有自定义参数,可以传入$event也可以拿到子组件传递的数据。通过$event只能传递第一个参数。⭐ -->
</div>
</template>
<template id="sonFn">
<div>
<button @click="getFather">点击我</button>
</div>
</template>
script区域:
<script>
// 父组件
Vue.component('father', {
template: '#fatherFn',
data(){
},
methods: {
getson1(data,text) {
console.log(data); //1111
console.log(text); //undefined
}
},
})
// 子组件
Vue.component('son', {
template: '#sonFn',
methods: {
getFather() {
this.$emit('getson', '12345', '上山打老虎')
}
}
})
const vm = new Vue({
el: '#app',
data: {
},
methods: {
}
})
</script>
二、子传父传值后把值渲染在视图层
// 父组件
Vue.component('father', {
template: '#fatherFn',
data() {
return{
getson:'',
}
},
methods: {
// 自定义形参名字,叫什么都可以
// 父组件接受参数(形参)
getFather(msg,text1){
console.log(msg); //12345
console.log(text1); //上山打老虎
// 把值渲染到视图层
this.getson = msg +','+ text1 //12345,上山打老虎
}
},
})
// 子组件
Vue.component('son', {
template: '#sonFn',
data() {
return {
message:'12345',
text:'上山打老虎'
}
},
methods: {
getBtn(){
// 子组件给父组件传递参数(实参)
this.$emit('getfather1',this.message,this.text)
}
}
})
const vm = new Vue({
el: '#app',
data: {
},
methods: {
}
})
三、评论案例巩固
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<!-- <script src="https://unpkg.com/vue-router@3.0.0/dist/vue-router.js"></script> -->
<!-- <script src="https://unpkg.com/axios/dist/axios.min.js"></script> -->
<link rel="stylesheet" href="./bootstrap/css/bootstrap.min.css">
</head>
<body>
<div id='app'>
<div class="container">
<child @getson="getSonData"></child>
<ul class="list-group">
<li class="list-group-item" v-for="(item,index) in list" :key="index">
{{item.content}}
<span class="badge">评论人:{{item.person}}</span>
</li>
</ul>
</div>
</div>
<!-- 子组件 -->
<template id="childFn">
<div>
<div class="form-group">
<label for="">评论人:</label>
<input type="text" class="form-control" id="" placeholder="" v-model="person">
</div>
<div class="form-group">
<label for="">评论内容:</label>
<input type="text" class="form-control" id="" placeholder="" v-model="content">
</div>
<button type="submit" class="btn btn-info" @click="btn">提交评论</button>
</div>
</template>
<script>
// 子组件
Vue.component('child', {
template: '#childFn',
data() {
return {
person: '',
content: '',
}
},
methods: {
btn() {
// 通过对象的形式传递参数
let obj = {
person: this.person,
content: this.content,
}
this.$emit('getson', obj)
}
},
})
// 父组件
const vm = new Vue({
el: '#app',
data: {
// 数组接受值
list: [],
},
methods: {
getSonData(data) {
// 通过push方法,把传递过来的参数放到list数组中
this.list.push(data)
}
}
})
四、ref的使用
ref 被用来给元素或子组件注册引用信息。引用信息将会注册在父组件的 $refs 对象上。
如果在普通的 DOM 元素上使用,引用指向的就是 DOM 元素;
如果用在子组件上,引用就指向组件实例
body区域:
<div id='app'>
<!-- 如果在普通的 DOM 元素上使用,引用指向的就是 DOM 元素; -->
<div ref="text">我是DOM元素</div>
<son ref="son"></son>
</div>
<template id="sonFn">
<div>
{{msg}}
<button @click="log()">点击log</button>
<p>{{msg}}</p>
<div>{{msg}}</div>
</div>
</template>
script区域:
<script>
// 子组件
Vue.component('son',{
template:'#sonFn',
data(){
return {
msg:'我是子组件',
}
},
methods:{
log(){
// console.log(111);
return 1
}
},
mounted(){
}
})
const vm = new Vue({
el: '#app',
data: {
},
methods: {
},
created(){
// console.log(this.$refs); //能获取到但是是一个空对象,空对象里面有dom元素
// console.log(this.$refs.text); //undefined
},
// 初始化已经完成,第一个可以操作data,methods的生命周期
mounted(){
// 引用指向DOM元素
this.$refs.text.style.color='red'
console.log(this.$refs.text); //获取DOM元素
// 如果用在子组件上,引用就指向组件实例
console.log(this.$refs.son) //VueComponent实例
console.log(this.$refs.son.$el); //获取子组件元素
console.log(this.$refs.son.msg); //我是子组件 获取子组件文本节点
this.$refs.son.$el.style.color='green'
}
})
</script>
五、wacth监听以及computed计算属性的使用
1、wacth监听属性
一个对象,键是需要观察的表达式,值是对应回调函数。值也可以是方法名,或者包含选项的对象。Vue 实例将会在实例化时调用 watch,遍历 watch 对象的每一个 属性。
//watch写法
watch: {
侦听的属性名: {
//用handler方法监听 把需要监听的值(first)看作对象 然后利用handler方法监听
handler (newName, oldName) { //第一个参数newName是最新的值;第二个参数oldName是输入之前的值
console.log(newName)
},
//下面都是配置属性
immediate: true, //是否初始化
deep: true //深度监听:监听对象或数组的时候需要添加deep:true属性
}
}
body区域:
<div id='app'>
<input type="text" v-model="first">
+
<input type="text" v-model="last">
<button @click="add()">=</button>
<input type="text" v-model="name">
</div>
script区域:
<script>
const vm = new Vue({
el: '#app',
data: {
first: '',
last: '',
name: '',
// obj: {
// name: '123'
// }
},
methods: {
add() {
// this.name = Number(this.first) + Number(this.last)
// this.name = this.first + this.last
// return this.name
}
},
// 监听
// 一个对象,键是需要观察的表达式,值是对应回调函数。
// 值也可以是方法名,或者包含选项的对象。Vue 实例将会在实例化时调用 watch,遍历 watch 对象的每一个 属性。
watch: {
// 常规方法监听
first: function (val) {
// console.log(val);
},
last: function (val) {
// console.log(val);
},
// name:function(val){
// val = this.first + this.last
// console.log(val);
// },
// oldVal参数保存上一个newVal的数字
name: function (newVal, oldVal) {
// console.log('newVal',newVal); //1
// console.log('oldVal',oldVal); //1111
},
// 用handler方法监听 把需要监听的值(first)看作对象 然后利用handler方法监听
first: {
handler(newVal, oldVal) {
// console.log(newVal); //新值
// console.log(oldVal); //旧值
},
immediate: true
},
// 以上两种写法是watch监听器的普通用法,这种用法有一个特点,就是当值第一次绑定的时候,不会执行监听函数,只有当值发生改变时才会执行。
// 如果我们需要在最初绑定值的时侯,也执行监听函数,则就需要用到immediate属性。
// 比如,当父组件向子组件动态传值时,子组件props首次获取到父组件传来的默认值时,也需要执行函数,此时就需要将immediate属性设置为true,结合handler方法使用。
// 当设置immediate属性为true时,无论值是否发生改变,时刻都会监听;
// 当设置immediate属性为false时,常规用法,只有值发生改变才会监听。
//第三种:超高级用法(deep 深度监听)
//监听普通变量的变化可以使用以上两种方法,但是要监听变量值是某对象的时候,则不起作用。
//例如,我们监听form对象内部属性的变化,是监听不到的。
// obj:{
// handler(newVal,oldVal){
// console.log('newVal',newVal);
// console.log('oldVal',oldVal);
// },
// deep:true,
// },
},
2、计算属性
计算属性
computed计算属性:只能对最终结果进行运算功能,只计算一次,具有缓存功能,能实现计算属性与普通属性之间的双向绑定。
computed的作用:
1.减少模板中的计算逻辑
2.能够进行数据缓存
3.响应式数据依赖固定的数据类型
script区域:
//computed的完整写法
computed: {
"属性名": {
//修改时触发的函数
set(值){
},
//读取时触发的函数
get() {
return "值"
}
}
}
//computed简写 当只使用get函数的使用简写形式
computed: {
属性名() {
}
}