渲染函数-深入 data 对象

我们平时在家是很少看电视的,最近看了几期最强大脑,真的被震惊到了,为什么他们的大脑容量那么大呢?并且非常机敏。海量的信息可以在很短的时间内记住,真是最遥远的距离莫过于我还没弄明白题目,别人已经答案出来了。感觉对他们来说,考上清华北大真是太容易了。我就想纵然我不能记住很多的信息,难道我认真些,努力些还不能记住几行代码吗?

言归正传,深入 data 对象在官网上没有完整的例子,可能对初学者真正透传的理解是有些难度的,这里展示data对象的完整例子。

官网原文:

有一件事要注意:正如在模板语法中,v-bind:class 和 v-bind:style ,会被特别对待一样,在 VNode 数据对象中,下列属性名是级别最高的字段。该对象也允许你绑定普通的 HTML 特性,就像 DOM 属性一样,比如 innerHTML (这会取代 v-html 指令)

{
  // 和`v-bind:class`一样的 API
  // 接收一个字符串、对象或字符串和对象组成的数组
  'class': {
    foo: true,
    bar: false
  },
  // 和`v-bind:style`一样的 API
  // 接收一个字符串、对象或对象组成的数组
  style: {
    color: 'red',
    fontSize: '14px'
  },
  // 正常的 HTML 特性
  attrs: {
    id: 'foo'
  },
  // 组件 props
  props: {
    myProp: 'bar'
  },
  // DOM 属性
  domProps: {
    innerHTML: 'baz'
  },
  // 事件监听器基于 `on`
  // 所以不再支持如 `v-on:keyup.enter` 修饰器
  // 需要手动匹配 keyCode。
  on: {
    click: this.clickHandler
  },
  // 仅对于组件,用于监听原生事件,而不是组件内部使用
  // `vm.$emit` 触发的事件。
  nativeOn: {
    click: this.nativeClickHandler
  },
  // 自定义指令。注意,你无法对 `binding` 中的 `oldValue`
  // 赋值,因为 Vue 已经自动为你进行了同步。
  directives: [
    {
      name: 'my-custom-directive',
      value: '2',
      expression: '1 + 1',
      arg: 'foo',
      modifiers: {
        bar: true
      }
    }
  ],
  // 作用域插槽格式
  // { name: props => VNode | Array<VNode> }
  scopedSlots: {
    default: props => createElement('span', props.text)
  },
  // 如果组件是其他组件的子组件,需为插槽指定名称
  slot: 'name-of-slot',
  // 其他特殊顶层属性
  key: 'myKey',
  ref: 'myRef'
}

例1

<body class="">
    <div id="app">
        <anchored-heading :level="2">hello world</anchored-heading>
    </div>
    <script src="js/vue.js"></script>
    <script>
    Vue.component("anchored-heading", {
        render: function(createElement) {
            return createElement("nav" + this.level, {
                    'class': {
                        foo: true,
                        bar: false
                    },
                    style: {
                        color: 'red',
                        fontSize: '14px'
                    },
                    attrs: {
                        id: 'foo'
                    },
                    props: {
                        myProp: 'bar' //可以传给子组件的属性
                    },
                    nativeOn: {
                        click: this.nativeClickHander
                    },
                   /* scopedSlots: {
                        default: props => createElement("span", props.text)
                    }*/

                },

                this.$slots.default)
        },

        //props:["level"] 也可以
        props: {

            level: {
                type: Number,
                required: true,
                myProp: 'bar'
            }
        },
        methods: {
            nativeClickHander: function() {
                alert("you click native Event")
            }
        }
    })
    Vue.component("nav2", {
        props: ["myProp"],
        //template:`<h2>{{myProp}}</h2>`
        render: function(createElement) {
            return createElement("h2", [createElement("div", this.$slots.default), this.myProp])
        }
    })
    var app = new Vue({
        el: "#app"
    })
   
    </script>
</body>

渲染函数最终渲染出来的div元素,其实跟template写出的字符串模板一样的
上例子anchored-heading组件定义了渲染函数(类似模板)和props属性(level),level是接收父级传递过来的的值,其中渲染函数渲染出的也是一个组件(从"nav" + this.level可以看出是nav2元素组件),为nav2组件定义了class与props属性,nav2的props{myProp: 'bar'}是用来传递myProp的值给它的子组件,class属性是可以从父级传给子组件的,所以最终HTML渲染为

<h2 class="foo"><div>hello world</div>bar</h2>

需要知道当你不使用slot属性向组件中传递内容时,这些子元素被存储在组件实例中的$slots.default中,本例中没有使用slot属性像子组件中传递内容,所以父组件的内容被存储在this.$slots.default中

例2:含有scopedSlots的例子

<body class="">
    <div id="app">
        <anchored-heading :level="2">hello world</anchored-heading>
    </div>
    <script src="js/vue-2.5.13.js"></script>
    <script>
    Vue.component("anchored-heading", {
        render: function(createElement) {
            return createElement("nav" + this.level, {
                    scopedSlots:{
                        //default:props => createElement("span",props.text)
                        default:function(props){
                            return createElement("span",props.text)
                        }
                    }
                },
                this.$slots.default)
        },
        //props:["level"] 也可以
        props: {

            level: {
                type: Number,
                required: true,
                myProp: 'bar'
            }
        },
        
    })
    Vue.component("nav2", {
        props: ["myProp"],
        
        render:function(createElement){
            return createElement("h2",[createElement('b',[this.$scopedSlots.default({text:'我是组件'})]),createElement("div",this.$slots.default),this.myProp])
        }
     
    })
    var app = new Vue({
        el: "#app"
    })
</script>
</body>

渲染为:

<body class="">
    <div id="app">
        <h2>
            <b><span>我是组件</span></b>
            <div>hello world</div>
        </h2>
    </div>
</body>

例3:含有on和domProps的例子

<body class="">
    <div id="app">
        <anchored-heading :level="2"><div>hello world</div></anchored-heading>
    </div>
    <script src="js/vue.js"></script>
    <script>
    Vue.component("anchored-heading", {
        render: function(createElement) {
            return createElement("h" + this.level, {
                    'class': {
                        foo: true,
                        bar: false
                    },
                    style:{
                        color:'red',
                        fontSize:'14px'
                    },
                    attrs:{
                        id:'foo'
                    },
                    domProps:{
                        innerHTML:"BAZ"
                    },
                    on:{
                        click:this.clickHander // on 与 nativeOn的区别是,nativeOn是加在组件上,它是父级还有字组件
                    },
                    //slot:"header"

                },

                this.$slots.default)
        },

        //props:["level"] 也可以
        props: {

            level: {
                type: Number,
                required: true,
                myProp: 'bar'
            }
        },
        methods:{
            clickHander:function(){
                alert("you clicked me")
            }
        }
    })
    
    var app = new Vue({
        el: "#app"
    })
    //domProps的优先级高,此时就不再显示this.$slots.default的内容
    </script>
</body>

渲染成:

<div id="app"><h2 id="foo" class="foo" style="color: red; font-size: 14px;">BAZ</h2></div>

例4:含有slot和ref的例子:


<body class="">
    <div id="app">
        <anchored-heading :level="2"><div slot="header">hello world</div></anchored-heading>
    </div>
    <script src="js/vue.js"></script>
    <script>
    Vue.component("anchored-heading", {
        render: function(createElement) {
            return createElement("h" + this.level, {
                    slot:"header",
                    ref:"myRef"
                },

                this.$slots.header)
        },
        //props:["level"] 也可以
        props: {

            level: {
                type: Number,
                required: true,
                myProp: 'bar'
            }
        },
        methods:{
            clickHander:function(){
                console.log(this.$refs.myRef.innerHTML)
            }
        }
    })
    var app = new Vue({
        el: "#app"
    })
    </script>
</body>

 

转载于:https://my.oschina.net/u/2612473/blog/1922517

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值