【笔记】Vue Element+Node.js开发企业通用管理后台系统——Vue进阶(上)

文章目录

  • 一、$emit 和 $on
    • 1.$on
    • 2.$emit
  • 二、directive 用法
  • 三、Vue.component 用法
    • 源码分析
  • 四、Vue.extend 用法
  • 五、Vue.extend 进阶用法
  • 六、Vue.use 用法


http://www.youbaobao.xyz/admin-docs/guide/base/vue.html


一、$emit 和 $on

实例:$emit 和 $on

$emit 和 $on主要负责事件的定义和消费,实现逻辑的解耦

<html>
  <head>
    <title>$emit 和 $ontitle>
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js">script>
  head>
  <body>
    <div id="root">
      <button @click="boost">触发事件button>
    div>
    <script>
      new Vue({
        el: '#root',
        data() {
          return {
            message: 'hello vue'
          }
        },
        created() {
          this.$on('my_events', this.handleEvents)
        },
        methods: {
          handleEvents(e) {
            console.log(this.message, e)
          },
          boost() {
            this.$emit('my_events', 'my params')            
          }
        }
      })
    script>
  body>
html>

1.$on

官方文档:https://cn.vuejs.org/v2/api/#vm-on

通过断点调试分析

  • $on传入两个参数,绑定的事件名称和事件方法。
  • 源码中第一步创建获取vue实例:var vm = this
  • 第二步 判断事件名称是否是数组
    • 是,使用迭代的方式继续调用$on
    • 否,vm._events[event]判空,为空则赋予它一个空数组,然后把需要绑定的事件方法push进去
  • 最后将处理后的vue实例返回

通过第二步可知,可以多个事件绑定一个执行方法,也可以一个事件同时绑定多个执行方法

2.$emit

官方文档:https://cn.vuejs.org/v2/api/#vm-emit

通过断点调试分析

  • $emit传入一个参数,绑定事件方法。
  • 源码中第一步创建获取vue实例:var vm = this
  • 第二步,将事件名称转为小写赋予变量lowerCaseEvent:var lowerCaseEvent = event.toLowerCase()
  • 第三步:做一些检查(略)
  • 第四步:从vm._events[event]中拿出事件方法,判空
  • 第五步:是多个事件方法就转数组
  • 。。。

通过分析可知,$emit中出现error并不会中断执行只是使用try-catch抛出异常

二、directive 用法

官方文档:https://cn.vuejs.org/v2/api/#Vue-directive

实例:directive 用法

<html>
  <head>
    <title>directive 用法title>
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js">script>
  head>
  <body>
    <div id="root">
      <div v-loading="isLoading">{{data}}div>
      <button @click="update">更新button>
    div>
    <script>
      Vue.directive('loading', {
        update(el, binding, vnode) {
          if (binding.value) {
            const div = document.createElement('div')
            div.innerText = '加载中...'
            div.setAttribute('id', 'loading')
            div.style.position = 'absolute'
            div.style.left = 0
            div.style.top = 0
            div.style.width = '100%'
            div.style.height = '100%'
            div.style.display = 'flex'
            div.style.justifyContent = 'center'
            div.style.alignItems = 'center'
            div.style.color = 'white'
            div.style.background = 'rgba(0, 0, 0, .7)'
            document.body.append(div)
          } else {
            document.body.removeChild(document.getElementById('loading'))
          }
        }
      })
      new Vue({
        el: '#root',
        data() {
          return {
            isLoading: false,
            data: ''
          }
        },
        methods: {
          update() {
            this.isLoading = true
            setTimeout(() => {
              this.data = '用户数据'
              this.isLoading = false
            }, 3000)
          }
        }
      })
    script>
  body>
html>
  • update的参数:
    • el:需要进行loading操作的DOM对象
    • binding:更新状态(是否在更新)
    • vnode:转化后的虚拟DOM对象

vue自定义指令VNode详解

VNode虚拟DOM学习

  • 若直接传入function:如下,会直接把指令添加到bind和update生命周期当中
    • Vue.directive(‘loading’, {update(…) {}})
    • Vue.directive(‘loading’, function update(…) {})

需要改造的地方:

else {
    const div = document.getElementById('loading')
    div && document.body.removeChild(div)
}

三、Vue.component 用法

官方文档:https://cn.vuejs.org/v2/api/#Vue-component

实例:Vue.component 用法

<html>
  <head>
    <title>Vue.component 用法title>
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js">script>
  head>
  <body>
    <div id="root">
      <Test :msg="message">Test>
    div>
    <script>
      Vue.component('Test', {
        template: '
{{msg}}
'
, props: { msg: { type: String, default: 'default message' } } }) new Vue({ el: '#root', data() { return { message: "Test Component" } } })
script> body> html>

源码分析

  • 定义组件需要传入组件名称和一个匿名对象
  • vue.js:5216:ASSET_TYPES.forEach(function (type) {
  • type为component
  • vue.js:5216:Vue[type] = function (id,definition) {
  • id为组件名称;definition为传入的匿名对象
  • 使用正则表达式检验名称合法性
  • 接下来判断类型的同时使用isPlainObject函数判断指定参数是否是一个纯粹的对象
    • vue.js:69:function isPlainObject (obj) {return _toString.call(obj) === '[object Object]'}
    • vue.js:59:var _toString = Object.prototype.toString;

为什么用Object.prototype.toString.call(obj)检测对象类型?

  • vue.js:5230:definition = this.options._base.extend(definition);
  • vue.js:5132:Vue.extend = function (extendOptions) {
  • vue.js:5146:var Sub = function VueComponent (options) {this._init(options);};
    • 构造方法进行组件实例化

四、Vue.extend 用法

官方文档:https://cn.vuejs.org/v2/api/#Vue-extend

实例:Vue.extend 用法

<html>
  <head>
    <title>Vue.extend 用法title>
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js">script>
  head>
  <body>
    <div id="root">
      <Test :msg="message">Test>
    div>
    <script>
      const component = Vue.extend({
        template: '
{{msg}}
'
, props: { msg: { type: String, default: 'default message' } }, name: 'Test' }) Vue.component('Test') new Vue({ el: '#root', data() { return { message: "Test Extend Component" } } })
script> body> html>

主要用来生成组件的构造函数VueComponent

  • vue.js:5132:Vue.extend = function (extendOptions) {
  • vue.js:5146:var Sub = function VueComponent (options) {this._init(options);};
    • 构造方法进行组件实例化

其实本实例作用和上一个相同

五、Vue.extend 进阶用法

官方文档:https://cn.vuejs.org/v2/api/#Vue-extend

实例:Vue.extend 进阶用法

<html>
  <head>
    <title>Vue.extend 用法2title>
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js">script>
    <style>
      #loading-wrapper {
        position: fixed;
        top: 0;
        left: 0;
        display: flex;
        justify-content: center;
        align-items: center;
        width: 100%;
        height: 100%;
        background: rgba(0,0,0,.7);
        color: #fff;
      }
    style>
  head>
  <body>
    <div id="root">
      <button @click="showLoading">显示Loadingbutton>
    div>
    <script>
      function Loading(msg) {
        const LoadingComponent = Vue.extend({
          template: '
{{msg}}
'
, props: { msg: { type: String, default: msg } }, name: 'LoadingComponent' }) const div = document.createElement('div') div.setAttribute('id', 'loading-wrapper') document.body.append(div) new LoadingComponent().$mount('#loading-wrapper') return () => { document.body.removeChild(document.getElementById('loading-wrapper')) } } Vue.prototype.$loading = Loading new Vue({ el: '#root', methods: { showLoading() { const hide = this.$loading('正在加载,请稍等...') setTimeout(() => { hide() }, 2000) } } })
script> body> html>

给vue实例添加自定义api,实现$loading

  • 使用Vue.prototype.$loading = Loading绑定方法
  • 将字符串'正在加载,请稍等...'作为参数msg传入Loading方法中
  • Vue.extend的返回值赋值给变量LoadingComponent
  • const div = document.createElement('div') 创建div
  • div.setAttribute('id', 'loading-wrapper')起名为loading-wrapper
  • document.body.append(div)进行挂载
  • new LoadingComponent().$mount('#loading-wrapper')实例化一个LoadingComponent对象,并挂载到前面创建的div上(直接覆盖,因此id必须相同,否则后面移除的时候找不到)
    【笔记】Vue Element+Node.js开发企业通用管理后台系统——Vue进阶(上)_第1张图片
  • const hide = this.$loading('正在加载,请稍等...'),将this.$loading的返回值() => {document.body.removeChild(document.getElementById('loading-wrapper'))赋值给变量hide,并在赋值过程中执行this.$loadingthis.$loading执行过程中return的内容不执行)
  • hide(),延时执行完毕,执行匿名方法() => {document.body.removeChild(document.getElementById('loading-wrapper'))this.$loading执行过程中return的内容),移除挂在的div
  • ``
    【笔记】Vue Element+Node.js开发企业通用管理后台系统——Vue进阶(上)_第2张图片

将一个方法赋值给一个变量的过程中,方法会执行一次,变量获取到的是方法的返回值,而方法的返回值是一个匿名方法(箭头函数),因此变量名即这个匿名函数的方法名,所以这个变量可做方法来用

六、Vue.use 用法

官方文档:https://cn.vuejs.org/v2/api/#Vue-use

实例:Vue.use 用法

<html>
  <head>
    <title>Vue.use 用法title>
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js">script>
    <style>
      #loading-wrapper {
        position: fixed;
        top: 0;
        left: 0;
        display: flex;
        justify-content: center;
        align-items: center;
        width: 100%;
        height: 100%;
        background: rgba(0,0,0,.7);
        color: #fff;
      }
    style>
  head>
  <body>
    <div id="root">
      <button @click="showLoading">显示Loadingbutton>
    div>
    <script>
      const loadingPlugin = {
        install: function(vm) {
          const LoadingComponent = vm.extend({
            template: '
{{msg}}
'
, props: { msg: { type: String, default: 'loading...' } } }, 'LoadingComponent') function Loading(msg) { const div = document.createElement('div') div.setAttribute('id', 'loading-wrapper') document.body.append(div) new LoadingComponent({ props: { msg: { type: String, default: msg } } }).$mount('#loading-wrapper') return () => { document.body.removeChild(document.getElementById('loading-wrapper')) } } vm.prototype.$loading = Loading } } Vue.use(loadingPlugin) new Vue({ el: '#root', methods: { showLoading() { const hide = this.$loading('正在加载,请稍等...') setTimeout(() => { hide() }, 2000) } } })
script> body> html>

将上节的功能做成一个插件,通过Vue.use进行加载
【笔记】Vue Element+Node.js开发企业通用管理后台系统——Vue进阶(上)_第3张图片
【笔记】Vue Element+Node.js开发企业通用管理后台系统——Vue进阶(上)_第4张图片
传送门:Vue.use实现原理 ;Vue.use源码分析


b=null;
var a=(b||(b=[]));
console.log(a);
在这里插入图片描述

你可能感兴趣的:(前端,【笔记】Vue,#,vue)