组件扩展、ref、监听、计算属性的使用

一、子组件传值父组件

子组件调用父组件的方法:

1. 在父组件中给引用的子组件注册一个事件(这个事件的名字是自定义的)  **相当于给两个组件直接建立联系**
2. 子组件可以触发这个事件$emit('事件名字') 

子组件给父组件传递数据

  1. $emit方法第二个参数可以定义子组件给父组件传递的内容
  2. 在父组件中怎么拿到这内容
    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: {
	属性名() {

	}
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值