美文网首页
Vue 基础 - 自定义指令和 render 函数

Vue 基础 - 自定义指令和 render 函数

作者: 千反田爱瑠爱好者 | 来源:发表于2018-08-25 23:18 被阅读4次
https://cn.vuejs.org/

自定义指令

类似组件可以全局注册和局部注册,使用derective注册。

钩子函数

指令定义函数提供了几个钩子函数(可选):

  1. bind:只调用一次,指令第一次绑定到元素时调用,可以定义一个在绑定时执行一次的初始化动作;
  2. inserted:被绑定元素插入父节点时调用(父节点存在即可调用,不必存在于 document中);
  3. update:被绑定元素所在的模板更新时调用,而不论绑定值是否变化;通过比较更新前后的绑定值,可以忽略不必要的模板更新;
  4. componentUpdated:被绑定元素所在模板完成一次更新周期时调用;
  5. unbind:只调用一次, 指令与元素解绑时调用。

钩子函数有以下参数:

  1. el:指令所绑定的元素,可以用来直接操作 DOM 。
  2. binding:一个对象,包含以下属性:
    1. name:指令名,不包括“v”前缀;
    2. value:指令的绑定值,例如` v­my­directive="1 + 1",value 的值是2;
    3. oldValue:指令绑定的前一个值,仅在update和componentUpdated钩子中可用,无论值是否改变都可用;
    4. expression:绑定值的字符串形式,例如v­my­directive="1 + 1" ,expression的值是“1 + 1”;
    5. arg:传给指令的参数。例如 v­my­directive:foo, arg 的值是 “foo”。
    6. modifiers:一个包含修饰符的对象, 例如v­my­directive.foo.bar,修饰符对
      象modifiers的值是{ foo: true, bar: true }
  3. vnode:Vue编译生成的虚拟节点。
  4. oldVnode:上一个虚拟节点,仅在update和componentUpdated 钩子中可用。
<div id="app">
    <input type="text" v-focus>获取焦点
    <br>
    <input type="text">
    <hr>
    <div v-command:expression.a.b.c="value"></div>
</div>
<script>
    // 自定义指令
    Vue.directive('focus', {
        inserted: function (el) {       // inserted选项:插入父节点时调用
            el.focus()
        }
    })

    Vue.directive('command', {
        bind: function (el, binding, vnode) {
            let keys = []
            for (let key in vnode) {
                keys.push(key)
            }
            console.log(keys)
            el.innerHTML =
                // '<div v-command:expression=.a.b.c="value"></div>' + "<br>" +
                "name: " + binding.name + "<br>" +
                "name: " + binding.value + "<br>" +
                "expression: " + binding.expression + "<br>" +
                "argument: " + binding.arg + "<br>" +
                "modifiers: " + JSON.stringify(binding.modifiers) + "<br>" +
                "vnode keys: " + keys.join(", ") + "<br>"
        }
    })
    let app = new Vue({
        el: "#app",
        data: {
            value: "自定义指令所绑定的值"
        }
    })
</script>

render函数

在render函数中使用this.$slotsprops传递数据:

<div id="app">
    <child :level="level">
        标题
    </child>
    <button v-on:click="add1()">+1</button>
    <button v-on:click="minus1()">-1</button>
</div>
<script>
    Vue.component('child', {
        // 如使用template则只允许有一个子节点
        render: function (createElement) {  // 注意,参数createElement不可修改

            // createElement函数的使用:
            return createElement(
                // 第一个参数(必须,用于创建DOM元素,可以是String/ Object/ Function)
                'h' + this.level,                       // String(HTML标签)
                // {template: '<div>haha</div>>'},         // Object(含有数据选项的对象)
                // function () {                           // Function(返回含有数据选项的对象)
                //     return {template: '<div>haha</div>>'}
                // },

                // 第二个参数(可选,数据对象,只能是Object)
                this.$slots.default     // 含有VNode的数组
                // {
                //     class: {active: true},  // 创建的DOM元素的属性
                //     style: {color: red, fontSize: '16px'},
                //     attrs: {id: 1, src: ""},
                //     domProps: {innerHTML: '<span style="color: red">红色</span>'},
                //     on: {input: functiopn(){//...}}
                // }

                // 第三个参数(可选,动态的VNode虚拟节点,可以是String或Array)
                // [createElement("h1", "标题"), createElement("h2", "二级标题")]
            );
        },
        props: ['level']        // 使用props在render函数中传递数据
    })

    let app = new Vue({
        el: "#app",
        data: {
            level: 1
        },
        methods: {
            add1: function () {
                if (this.level < 6)
                    this.level += 1;
            },
            minus1: function () {
                if (this.level > 1)
                    this.level -= 1;
            }
        }
    })
</script>

在render函数中使用v-model

<div id="app">
    <!-- 方法1:子组件使用$emit向父组件传递事件 -->
    <!--<my-component :name="name" @input="showName"></my-component>-->

    <!-- 方法2:使用v-model绑定属性,且自动接收input事件从子组件传递给父组件的值 -->
    <my-component :name="name" v-model="name"></my-component>
    <br> {{name}}
</div>
<script>
    Vue.component("my-component", {
        render: function (createElement) {
            let self = this     // 临时保存this,此处的this为当前Vue实例
            return createElement("input", {
                domProps: {
                    value: self.name
                },
                on: {
                    input: function (event) {
                        console.log(this)       // 此处的this为window
                        self.$emit("input", event.target.value)     // 输入内容传递给父组件
                    }
                }
            })
        }
    })

    let app = new Vue({
        el: "#app",
        data: {
            name: "ywh"

        },
        // methods: {
        //     showName: function(value) {
        //         this.name = value
        //     }
        //
        // }
    })
</script>

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

<div id="app">
    <my-component>
        <!-- 作用域插槽写在template中 -->
        <template scope="prop">     <!-- prop获取传递过来的数据 -->
            {{prop.text}}
        </template>
    </my-component>
</div>
<script>
    Vue.component('my-component', {
        render: function (createElement) {

            // 相当于在template中创建一个<div><slot :text="text"></slot></div>
            return createElement(
                'div',
                this.$scopedSlots.default({     // 使用作用域插槽
                    text: '子组件传递过来的数据',
                })
            )
        }
    })
    let app = new Vue({
        el: "#app"
    })
</script>

函数化组件

<div id="app">
    <my-component value="子组件信息"></my-component>
</div>
<script>
    Vue.component('my-component', {
        functional: true,       // 表示当前Vue实例无状态,无实例(没有this)
        render: function(createElement, context) {
            // context中存放父组件、子组件中的内容
            // this.text === context.props.text
            // this.$slots.default === context.children
            return createElement("button", {
                on: {
                    click: function() {
                        console.log(context)
                        console.log(context.parent)         // 表示父组件
                        alert(context.parent.parentMsg)     // 父组件内容(msg)
                        console.log(context.props.value)    // 子组件内容
                    }
                }
            }, "click")
        },
        prope: ["value"]
    })
    let app = new Vue({
        el: "#app",
        data: {
            parentMsg: "父组件信息"
        }
    })
</script>

相关文章

  • Vue 基础 - 自定义指令和 render 函数

    自定义指令 类似组件可以全局注册和局部注册,使用derective注册。 钩子函数 指令定义函数提供了几个钩子函数...

  • 说说如何利用 Render 函数来实现 Vue.js 的内置指令

    因为在 Render 函数中无法使用 Vue 内置指令,比如 v-if 等,但我们可以在 Render 函数中,利...

  • Vue指令钩子函数

    Vue指令上篇文章有讲过了,现在分析Vue指令钩子函数。 自定义指令 全局定义:Vue.directive( ' ...

  • Vue 自定义指令

    Vue自定义指令 定义 通过directive方法,配合钩子函数及参数定义指令 定义全局自定义指令 定义局部自定义...

  • vue自定义指令,包装函数节流。

    自定义指令的钩子函数 Vue 提供了自定义指令的5个钩子函数: bind:指令第一次绑定到元素时调用,只执行一次。...

  • season2-全局API

    第1节:Vue.directive 自定义指令 Vue.directive自定义指令 自定义的指令:changec...

  • Vue 基础回顾

    Vue 基础结构 h函数:创建虚拟dom render:把h函数创建的虚拟dom返回 $mount:把虚拟dom转...

  • Vue中的render渲染函数

    Vue中的render渲染函数 render函数只支持jsx写法创建虚拟Dom节点。vue组件中的template...

  • vue知识集锦(三)

    自定义指令 除了核心功能默认内置的指令 (v-model和v-show),Vue 也允许注册自定义指令。尽管Vue...

  • vue中的render函数式组件

    问题:1、render函数是什么2、render函数怎么用 1. render函数是什么 简单的说,在vue中我们...

网友评论

      本文标题:Vue 基础 - 自定义指令和 render 函数

      本文链接:https://www.haomeiwen.com/subject/mzkniftx.html