render 函数(二)

this.$slots 在 render 函数中的应用

 <div id="app">
        <my-component>
            <p > 灌篮高手</p>
            <p >我是要成为海贼王的男人</p>
            <h1>我是h1</h1>
            <h3 slot="header">《海贼王》</h3> // 用 slot 给 h3起个名字
            <!-- 插值 -->
            <h5 slot="footer">《火影忍者》</h5>
        </my-component>
    </div>

    <script>
        //第三个参数存的就是 VNODE(虚拟节点) createElement('header',header),返回的就是VNODE
        Vue.component('my-component', {
            
            render:function(createElement) {
                var header = this.$slots.header
         //返回的内容就是 含有VNODE数组
         // 使用 this.$slots.header 访问名字是 header 的元素
                var main = this.$slots.default
                var footer = this.$slots.footer  
                return createElement('div',[
                    createElement('header',header),
         // 创建 header 标签以及它里边的内容
                    createElement('main',main),
                    createElement('footer',footer)
                ])              
            },
        })

        var app = new Vue({
            el: '#app',

        })
    </script>

从上例可以看出,在 render 函数中可以不使用 slot 元素,而是直接使用 this.$slots 访问到相应的元素。注意,h3 和 h5 标签中的 slot 是属性,用来给元素“起个名字”的,不是元素!

    console.log(Array.isArray(header))  // true
    console.log(Array.isArray(footer))  // true
    console.log(Array.isArray(main))    // true

由上可得,header、main、footer 都是数组。

这些数组中,存的是 VNode(虚拟节点),也就是 <my-component></my-component> 中的节点。
console.log(header)


createElement 的第三个参数,存的就是 VNode(虚拟节点)。

在 render 函数中使用 props 传递数据

在 render 函数中,父组件给子组件传递数据的步骤:
在父组件绑定数据;
在子组件使用 props 接收数据;
在子组件使用接收到的数据。

    <div id="app">
        <button @click="switchshow">点击切换</button> {{show}}
        <my-component :show="show">  </my-component>
    </div>

    <script>
        //需求:点击按钮切换图片
        //通过点击按钮改变 父组件show 的 true false,改变之后把show 传递给子组件,
        //子组件在 prpps 中接收,接收完以后通过 render函数 构建一个 img 标签,通过this.show来改变src 路径,srcl路径在 attrs中进行设置
        Vue.component('my-component', {
            props: ['show'],
            render: function (createElememt) {
                var imgsrc
                if (this.show) {
                    imgsrc = 'img/1.jpg'
                } else {
                    imgsrc = 'img/2.jpg'
                }
                return createElememt('img', {
                    attrs: {
                        src: imgsrc
                    },
                    style: {
                        width: '300px',
                        height: '300px'
                    }
                })
            },
        })

        var app = new Vue({
            el: '#app',
            data: {
                show: true
            },
            methods: {
                switchshow: function () {
                    this.show = !this.show
                }
            },
        })
    </script>

点击切换

在 render 函数中使用 v-­model

在 render 函数中使用 v-model 绑定父组件中的数据;

  • 在父组件中使用 v-model 绑定父组件中的数据;
  • 在子组件中使用 $emit() 触发 input 事件,并传递子组件中的数据。
    <div id="app">
        <!-- 将name传递过来 -->
        <!-- 在input里面输入值的时候,就会将输入的值传递给父组件,在页面上显示。子组件给父组件传递数据 -->
        <!-- @input 接收数据 showname事件名-->
        <!-- input 事件执行showname方法接收一个数据,把数据赋值给你想要的内容 -->
        <!-- <my-component :name="name"  @input="showName"></my-component>   -->
        <my-component :name="name" v-model="name"></my-component>
        <!-- v-model 绑定name,做了两步操作:
        1.self.$emit('input',event.target.value) 接收子组件传递的数据
        2.赋值给绑定的name -->
        <br> {{name}}
    </div>

    <script>
        Vue.component('my-component', {
            render: function (createElement) { //render渲染组件
                var self = this;//在createElememt里面调用this, 指的就是当前的vue实例
                return createElement('input', {
                    domProps: {
                        value: self.name//将接收的name赋值给input框
                    },
                    //在render函数里面写事件方法的时候需要将 this 赋值给一个变量,用到vue中的方法使用声明的变量来调用
                    on: {//input事件
                        input: function (event) {//默认会把原生的event事件给传递进来
     
                            //此处的this指的是什么?
        //此处的this是window,所以不能直接用this.$emit,需要用 Vue 实例中的this来调用,所以声明var self = this.
                            self.$emit('input', event.target.value)//event.target.value传递input输入的内容;子组件要向父组件传递信息,在父组件上接收;输入内容的时候,触发input事件
                        }
                    }
                })
            },
            props: ['name']//props接收name
        })

        var app = new Vue({
            el: '#app',
            data: {
                name: '你好'
            },
            // methods: {
            //     showName:function(value){//showname方法自动加一个参数(自定义),这里的value就是触发input事件之后传递的值
            //         this.name = value//把value值赋值给this.name
            //     }
            // },
        })
    </script>

在render函数中使用作用域插槽

作用域插槽使得父组件可以从子组件中获取数据。

<div id="app">
   <child-component>
     <template slot-scope="data"> 
<!-- 在父组件中使用 slot-scope 定义变量,data 就是子组件传过来的对象-->
       {{ data.text }}
     </template>
   </child-component>
</div>

Vue.component('child-component', {
 render: function (createElement) {
   return createElement('div', this.$scopedSlots.default({  
// 使用 this.$scopedSlots.default 定义子组件中的数据
     text: '我是子组件中的内容'
   }))
 }
})

var app = new Vue({
 el: '#app',
 data: {
 },
})`

函数化组件

函数化组件在实际开发中并不常用。

    <div id="app">
        <my-component ></my-component>
    </div>
    <script>
        Vue.component('my-component', {
            functional: true,    //表示当前vue实例无状态,无实例   
            //无实例表示没有this这个概念  
            //context 上下文模块
            render: function (createElement, context) {
                return createElement('button',{
                    on:{
                        click:function(){
                            console.log(context)
     
                        }
                    }
                },'点击我学习context')
            }
        })
        var app = new Vue({
            el: '#app',
            data: {

            }
        })
    </script>

可以从中找到需要的 API 。如:打印出父组件 data 中的数据:

    render: function (createElement, context) {
        return createElement('button', {
            on: {
                click: function () {

                    var a = this
                    console.log(context)
                    console.log(context.parent)
                    // alert(context.parent.msg)
                    // console.log(context.props.value)
                    alert(this.value) //undefined
                }
            }
        }, '点击我学习context')
    }

        var app = new Vue({
            el: '#app',
            data: {
                msg: '父组件内容'
            }
        })

上面代码中的 context.parent 可以访问到父组件。

发布了66 篇原创文章 · 获赞 222 · 访问量 119万+

猜你喜欢

转载自blog.csdn.net/Liuqz2009/article/details/103864653