vue高级语法

Mixin 混入

  • 组件 data,methods 优先级高于 mixin data,methods 优先级

  • 生命周期函数,先执行 mixin 里面的,再执行组件里面的

  • 自定义的属性,组件内的属性优先级高于 mixin 属性的优先级

    【自定义属性可以通过this.$options获取】

    // 处理自定义属性的优先级
    app.config.optionMergeStrategies.number = (mixinVal, appValue, vm) => {
       return mixinVal || appValue
    }
    

自定义指令

  • 新建自定义指令

    // 全局自定义指令
    app.directive('focus', {
        mounted(el) {
            el.focus()
        }
    }
    // 局部自定义指令
    const directives = {
        focus: {
              mounted(el) {
                  el.focus()
              }
        }
    }           
    const app = Vue.createApp({
        directives: directives,
        template: `<div><input v-focus /></div>`
    })          
    
  • 自定义指令传参

    const app = Vue.createApp({
          data() { 
              return { distance: 110 }
          },
          template: `
            <div>
              <div v-pos:bottom="distance" class="header">
                <input />
              </div>
            </div>
          `
    })
    // 全局自定义指令
    // app.directive('pos', {
    //   mounted(el, binding) {
    //     el.style[binding.arg] = `${binding.value}px`
    //   },
    //   updated(el, binding) {
    //     el.style[binding.arg] = `${binding.value}px`
    //   },
    // })
    // 简写版 (条件是初始化跟更新是一样的操作时)
    app.directive('pos', (el, binding) => {
        el.style[binding.arg] = `${binding.value}px`
    })
    

Teleport——任意传送门

Vue2,如果想要实现类似的功能,需要通过第三方库 portal-vue 去实现

为什么我们需要 Teleport

Teleport 是一种能够将我们的模板移动到 DOMVue app 之外的其他位置

场景:像 modals,toast 等这样的元素,很多情况下,我们将它完全的和我们的 Vue 应用的 DOM 完全剥离,管理起来反而会方便容易很多

原因在于如果我们嵌套在 Vue 的某个组件内部,那么处理嵌套组件的定位、z-index 和样式就会变得很困难

Teleport 的使用

// html:
<div id="hello"></div>

// 添加如下,留意 to 属性跟上面的 id 选择器一致
const app = Vue.createApp({
      methods: {
        handleBtnClick() {
          this.show = !this.show
        }
      },
      template: `
        <div>
          <div class="area">
            <button @click="handleBtnClick">按钮</button>
            <teleport to="#hello">
              <div class="mask"></div>
            </teleport>
          </div>
        </div>
      `
})

渲染函数 render

Vue 推荐在绝大多数情况下使用模板来创建你的 HTML。然而在一些场景中,你真的需要 JavaScript 的完全编程的能力。这时你可以用渲染函数,它比模板更接近编译器。

createElement参数

createElement可以是接受多个参数:

第一个参数:{String | Object | Function}

第一个参数对于createElement而言是一个必须的参数,这个参数可以是字符串string、是一个对象object,也可以是一个函数function

<template>
  <div class="dome">
    <div id="app">
    </div>
  </div>
</template>

<script>
  Vue.components('dom', {
    render: function (createElement) {
      return createElement('div');
    }
  });
  new Vue({
    el: '#app'
  });
</script>

上面的示例,给createElement传了一个String参数'div',即传了一个HTML标签字符

第二个参数:{Object}

createElement是一个可选参数,这个参数是一个Object。来看一个小示例:

Vue.components('dom', {
    render: function (createElement) {
      return createElement('div', {
        'class': {
          container: true
        },
        style: {
          cursor: 'pointer'
        },
        domProps: {
          innHTML: 'baz'
        }
      });
    }
});
new Vue({
   el: '#app'
});

第三个参数:{String | Array}

createElement还有第三个参数,这个参数是可选的,可以给其传一个StringArray。比如下面这个小示例:

Vue.components('dom', {
    render: function (createElement) {
      return createElement('div', [
        createElement('h1', '主标'),
        createElement('h2', '副标')
      ]);
    }
  });
new Vue({
  el: '#app'
});

使用JavaScript代替模板功能

在使用Vue模板的时候,我们可以在模板中灵活的使用v-ifv-forv-modelslot 但在render函数中是没有提供专用的API。如果在render使用这些,需要使用原生的JavaScript来实现

v-ifv-for

render函数中可以使用if/elsemap来实现template中的v-ifv-for

<ul v-if="items.length">
    <li v-for="item in items">{{ item }}</li>
</ul>
<p v-else>No items found.</p>

换成render函数,可以这样写:

Vue.component('item-list',{
    props: ['items'],
    render: function (createElement) {
        if (this.items.length) {
            return createElement('ul', this.items.map((item) => {
                return createElement('item')
            }))
        } else {
            return createElement('p', 'No items found.')
        }
    }
})

<div id="app">
    <item-list :items="items"></item-list>
</div>

let app = new Vue({
    el: '#app',
    data () {
        return {
            items: ['大漠', 'W3cplus', 'blog']
        }
    }
})

v-model

render函数中也没有与v-model相应的API,如果要实现v-model类似的功能,同样需要使用原生JavaScript来实现。

<div id="app">
    <el-input :name="name" @input="val => name = val"></el-input>
</div>

Vue.component('el-input', {
    render: function (createElement) {
        var self = this
        return createElement('input', {
            domProps: {
                value: self.name
            },
            on: {
                input: function (event) {
                    self.$emit('input', event.target.value)
                }
            }
        })
    },
    props: {
        name: String
    }
})

let app = new Vue({
    el: '#app',
    data () {
        return {
            name: '大漠'
        }
    }
})

更多详细可以查看 Vue render函数

plugin 插件

plugin 插件, 也是把通用性的功能封装起来

const myPlugin = {
   install(app, options) {
        // 扩展vue全局变量
        app.provide('name', 'elfecho');
        app.directive('focus', {
          mounted(el) {
            el.focus()
          }
        })
        app.mixin({
          mounted() {
            console.log('mixin') // 这里打印了两次,因为父子组件都执行这个生命周期函数
          },
        })
        // vue底层扩展全局属性
        app.config.globalProperties.$sayHello = 'hello world'
    }
}

const app = Vue.createApp({
      mounted() {
        console.log(this.$sayHello)
      },
      template: `<my-title></my-title>`
    })
// 组件使用全局变量时,需要注册inject
app.component('my-title', {
    inject: ['name'],
    template: `
        <h1>{{name}}</h1>
        <input v-focus/>
    `
})

app.use(myPlugin, {
    name: 'elf'
})
    
const vm = app.mount('#root')

应用

对数据进行校验的插件

// 这个写法,相比前面简写了install
const validatorPlugin = (app, options) => {
  app.mixin({
    created() {
      for (let key in this.$options.rules) {
        const item = this.$options.rules[key]
        this.$watch(key, (value) => {
          const result = item.validate(value)
          if (!result) console.log(item.message)
        })
      }
    },
  })
}

const app = Vue.createApp({
  data () {
    return {
      name: 'jun',
      age: 24
    }
  },
  rules: {
    age: {
      validate: age => age > 25,
      message: 'too young, to simple'
    },
    name: {
      validate: name => name.length > 4,
      message: 'name too short'
    }
  },
  template: `name: {{name}},age: {{age}}`
})
app.use(validatorPlugin)
const vm = app.mount('#root')
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,565评论 6 479
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,021评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,003评论 0 341
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,015评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,020评论 5 370
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,856评论 1 283
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,178评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,824评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,264评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,788评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,913评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,535评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,130评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,102评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,334评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,298评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,622评论 2 343

推荐阅读更多精彩内容

  • 这篇笔记主要包含 Vue 2 不同于 Vue 1 或者特有的内容,还有我对于 Vue 1.0 印象不深的内容。关于...
    云之外阅读 5,044评论 0 29
  • 前几天想学学Vue中怎么编写可复用的组件,提到要对Vue的render函数有所了解。可仔细一想,对于Vue的ren...
    kangaroo_v阅读 116,012评论 13 171
  • 这篇文章是接着我的上部vue学习笔记写的,之所以分开写这两篇文章是因为我意识到不知道什么时候就写了非常多的字了,所...
    看物看雾阅读 824评论 0 1
  • 前言 Vue基本用法很容易上手,但是有很多优化的写法你就不一定知道了,本文从列举了 36 个 vue 开发技巧; ...
    阿_军阅读 1,435评论 0 1
  • Vue是一款高度封装的、开箱即用的、一栈式的前端框架,既可以结合webpack进行编译式前端开发,也适用基于gul...
    Hebborn_hb阅读 1,085评论 0 31