Vue2使用技巧记录

# Vue2使用技巧记录

以下用法主要适用于vue2项目~

# 小技巧

# Vue中重置data中的数据

Object.assign(this.$data, this.$option.data());

在当前组件实例中$data属性保存了当前组件的data对象,$options是当前组件实例初始化时的一些属性,其中data方法执行后会返回一个初始化的data对象。

# 给对象添加新的 property 也会触发更新

// `Object.assign(this.someObject, { a: 1, b: 2 })` // 不会触发更新
this.someObject = Object.assign({}, this.someObject, { a: 1, b: 2 }) // 会触发更新

使用 Object.assign() 添加到对象上的新 property 不会触发更新;可以用原对象与要混合进去的对象的 property 一起创建一个新的对象。

# 通过hook监听生命周期函数

    // 通过hook监听组件销毁钩子函数,并取消监听事件
    this.$once('hook:beforeDestroy', () => {
      window.removeEventListener('resize', resizeFn)
    })

# 通过@hook监听子组件生命周期

<!-- 父组件 -->
<child-comp @hook:created="watchChildCreated"></child-comp>

可以通过@hook:钩子函数名来监听子组件的所有生命周期钩子,执行顺序会在该子组件生命周期之后执行~

# watch深度监听

 watch: {
    formData: {
      handler(newVal, oldVal) {
        //   处理逻辑
      },
      deep: true, // 深度监听
      immediate: true, // 立即触发
    }

# $attrs$listeners

vue2.4.0新增API (opens new window)

  • $attrs: 当组件在调用时传入的属性没有在props里面定义时,传入的属性将被绑定到$attrs属性内(classstyle除外,他们会挂载到组件最外层元素上)。并可通过v-bind="$attrs"传入到内部组件中
  • $listeners: 当组件被调用时,外部监听的这个组件的所有事件都可以通过$listeners获取到。并可通过v-on="$listeners"传入到内部组件中。
<!---root.vue-->
<template>
   <father name="root" @dispatch="val => dispatchFn(val)"></father>
</template>

<!---father.vue-->
<template>
    <!---使用了v-bind与v-on监听属性与事件-->
    <child v-bind="$attrs" v-on="$listeners">
    <!--其他代码不变-->
    </child>
</template>

<!---child.vue-->
<template>
    <span @click="$emit('dispatch',true)">{{name}}</span>
</template>
<script>
  export default {
      props: {
          name: ''
      }
 }
</script>

# provide/inject

vue2.2.0新增API (opens new window)

  • provide选项应该是一个对象或返回一个对象的函数。该对象包含可注入其子孙的 property。
  • inject选项应该是一个字符串数组

这对选项需要一起使用,以允许一个祖先组件向其所有子孙后代注入一个依赖,不论组件层次有多深,并在其上下游关系成立的时间里始终生效。

// 父级组件提供 'foo'
var Provider = {
  provide: {
    foo: 'bar'
  },
  // ...
}

// 子组件注入 'foo'
var Child = {
  inject: ['foo'],
  created () {
    console.log(this.foo) // => "bar"
  }
  // ...
}

# 自定义组件的v-model

vue2.2.0+新增API (opens new window)

一个组件上的v-model默认会利用名为valueprop和名为input的事件,但是像单选框、复选框等类型的输入控件可能会将value attribute 用于不同的目的。model 选项可以用来避免这样的冲突:

Vue.component('base-checkbox', {
  model: { // 通过model自定义属性名和事件名
    prop: 'checked',
    event: 'change'
  },
  props: {
    checked: Boolean
  },
  template: `
    <input
      type="checkbox"
      v-bind:checked="checked"
      v-on:change="$emit('change', $event.target.checked)"
    >
  `
})

// 使用
<base-checkbox v-model="lovingVue"></base-checkbox>

# .sync实现双向数据绑定

vue2.3.0+新增的修饰符 (opens new window)

Vue中,props属性是单向数据传输的,有时我们需要对prop进行“双向绑定”。v-model实现了双向绑定,但有时候我们希望一个组件可以实现多个数据的“双向绑定”,而v-model一个组件只能有一个(Vue3.0可以有多个),这时候就需要使用到.sync

// 父组件
<text-document :title.sync="title"></text-document>

// text-document 组件
export default {
    // 传入title
    props: {
        title: {
            type: String,
            default: ''
        }
    }

    // 更新title
    this.$emit('update:title', newTitle)
}

注意带有.sync修饰符的v-bind不能和表达式一起使用。

# 全局注入utils中的方法

平常我们习惯把一些方法放在utils里面,需要时先引入,再使用;可通过全局注入的方法直接挂在到vueprototype上,使用的时候直接用就可以~

  1. 创建方法
// utils.js
class Utils {
  // 自定义一个复制文本的方法
  copyToClipboard(text, callback) {
    let copyText = document.createElement('input')
    document.body.appendChild(copyText)
    copyText.value = text
    copyText.select()
    document.execCommand('copy')
    document.body.removeChild(copyText)

    callback && callback(text);
  }
}

export default new Utils()
  1. 全局注入
// 入口 main.js
import Utils from './utils.js'

// Init Global Utils
Vue.prototype.$utils = Utils
  1. 使用
this.$utils.copyToClipboard(text)

# 局部刷新某个组件

虚拟 DOM 在渲染时候通过 key 来对比两个节点是否相同,如果 key 不相同,就会判定组件是一个新节点,从而先销毁组件,然后再重新创建新组件,这样组件内的生命周期会重新触发。

<template>
  <component :key="renderKey" />
</template>
<script>
export default { 
  data() { 
    return { 
      renderKey: 0, 
    }
  }; 
  methods: { 
    forceRerender() { 
      this.renderKey = +new Date(); 
    } 
  } 
}
</script>

同理,路由也可以通过设置key来实现页面切换到同一个路由时页面刷新:<router-view :key="$route.fullpath"></router-view>

# 动态的指令参数

在 Vue 2.6 中提供了这样一个特性:可以动态的将指令参数传递给组件。假设你有一个组件 <my-button>,有时候你需要绑定一个点击事件click,有时候需要绑定一个双击事件 dblclick,这个时候你可以这么写:

<my-button @[someEvent]="handleSomeEvent()"/>

<script>
export default {
  computed: {
    someEvent(){
      return someCondition ? "click" : "dblclick"
    }
  }
}
</script>

# v-cloak 解决页面闪烁问题

有时页面模板的数据需要异步步获取,网络不好时,会出现页面闪烁的效果;v-cloak 指令保持在元素上直到关联实例结束编译,利用它的特性,结合 CSS 的规则[v-cloak] { display: none } 一起可以隐藏掉未编译好的 Mustache 标签,直到实例准备完毕。官方 (opens new window)

[v-cloak] {
  display: none;
}

// 不会显示,直到编译结束。
<div v-cloak>
  {{ message }}
</div>

# v-once 和 v-pre 提升性能

Vue 的性能优化很大部分在编译这一块~

  • Vue 提供了 v-pre 给我们去决定要不要跳过这个元素和它的子元素的编译过程,跳过大量没有指令的节点会加快编译。官方 (opens new window)
<span v-pre>{{ this will not be compiled }}</span>   
<!-- 显示的是{{ this will not be compiled }} -->
<span v-pre>{{msg}}</span>    
<!-- 即使data里面定义了msg这里仍然是显示的{{msg}} -->
  • v-once:只渲染元素和组件一次。随后的重新渲染,元素/组件及其所有的子节点将被视为静态内容并跳过。官方 (opens new window)
<!-- 单个元素 -->
<span v-once>This will never change: {{msg}}</span>
<!-- 有子元素 -->
<div v-once>
  <h1>comment</h1>
  <p>{{msg}}</p>
</div>
<!-- 组件 -->
<my-component v-once :comment="msg"></my-component>
<!-- `v-for` 指令-->
<ul>
  <li v-for="i in list" v-once>{{i}}</li>
</ul>

# errorCaptured

2.5.0+ 新增生命钩子 (opens new window),当捕获一个来自子孙组件的错误时被调用。此钩子会收到三个参数:错误对象、发生错误的组件实例以及一个包含错误来源信息的字符串。此钩子可以返回 false 以阻止该错误继续向上传播。

  • child.vue
<template>
  <!-- 省略一些无关代码 -->
</template>
<script>
  export default {
    mounted () {
      // 故意把 console 写错
      consol.log('这里会报错!')
    }
  }
</script>
  • father.vue
<template>
  <child></child>
</template>
<script>
  import Child from './Child.vue'
  export default {
    components: [ Child ],
    /**
     * 收到三个参数:
     * 错误对象、发生错误的组件实例
     * 以及一个包含错误来源信息的字符串。
     * 此钩子可以返回 false 以阻止该错误继续向上传播。
     */
    errorCaptured (err, vm, info) {
      console.log(err)
      // -> ReferenceError: consle is not defined ...
      console.log(vm)
      // -> {_uid: 1, _isVue: true, $options: {…}, _renderProxy: o, _self: o,…}
      console.log(info)
      // -> `mounted hook`
      // 告诉我们这个错误是在 vm 组件中的 mounted 钩子中发生的
      
      // 阻止该错误继续向上传播
      return false
    }
  }
</script>

# Vue.config.keyCodes

场景:自定义按键修饰符别名,参考 (opens new window)

// 将键码为 113 定义为 f2
Vue.config.keyCodes.f2 = 113;
<input type="text" @keyup.f2="add"/>

# img加载失败

有些时候后台返回图片地址不一定能打开,所以这个时候应该加一张默认图片

<img :src="imgUrl" @error="handleError" alt="">
<script>
export default{
  data(){
    return{
      imgUrl:''
    }
  },
  methods:{
    handleError(e){
      e.target.src=reqiure('图片路径')
    }
  }
}
</script>

# $log 调试 template

遇到 template 模板渲染时 JavaScript 变量出错的问题, 可以在开发环境挂载一个 log 函数来进行调试~

// main.js
Vue.prototype.$log = window.console.log;

// 组件内部
<div>{{$log(info)}}</div>

# scrollBehavior管理路由滚动

SPA项目开发中,可通过vue-routerscrollBehavior来管理组件的滚动行为;vue-router滚动行为 (opens new window)

const router = new VueRouter({
  routes: [...],
  scrollBehavior (to, from, savedPosition) {

    // keep-alive 返回缓存页面后记录浏览位置
    if (savedPosition && to.meta.keepAlive) {
      return savedPosition;
    }

    // 异步滚动操作
    return new Promise((resolve) => {
    setTimeout(() => {
      resolve({ x: 0, y: 0 });
    }, 0);
    });

    // 滚动到锚点
    if (to.hash) {
      return {
        selector: to.hash
      }
    }
  }
})

scrollBehavior 方法接收 to 和 from 路由对象。第三个参数 savedPosition 当且仅当 popstate 导航 (通过浏览器的 前进/后退 按钮触发) 时才可用。

# 子组件绑定原生事件

vue中给子组件自定义一个click事件,需要在子组件通过$emit('click')触发才行。如果想在父组件中触发,那就要用到native修饰符了~

<template>
    <div>
        <Child @click.native="test"></Child>
    </div>
</template>
<script>
    methods:{
        test(){}
    }
</script>

# v-for的解构

<template>
  // 对象解构
  <li v-for="(value, key, index) in {name: 'tom', age: 12, gender: 'boy'}">
    {{index+1}}. {{key}}: {{value}}
  </li>

  // es6解构
  <li v-for="{name, age} in [{name: 'tom', age: 12}, {name: 'rose', age: 24}]">
    {{name}}: {{age}}
  </li>

  // 遍历范围
   <li v-for="n in 5">
    {{n}} // 从1开始,以指定的数字结束
  </li>
</template>

# prop添加validator校验

export default {
  name: 'Image',
  props: {
    src: {
      type: String,
    },
    style: {
      type: String,
      validator: s => ['square', 'rounded'].includes(s)
    }
  }
};

这个验证函数接受一个prop,如果prop有效或无效,则返回true或false。

# 使用一个对象绑定多个 prop

const post = {
  id: 1,
  title: 'My Journey with Vue'
}


<BlogPost v-bind="post" />

// 等价于
<BlogPost :id="post.id" :title="post.title" />

# 进阶技能

# slot插槽

官网参考 (opens new window)

  1. 默认插槽
// 父组件
<link-item url="/profile">
  点击跳转
</link-item>

// link-item组件
<a v-bind:href="url" class="nav-link">
  <slot>默认</slot>
</a>
  1. 具名插槽
<!-- child-comp组件 -->
<div>
    <!-- slot 元素有一个特殊的属性:name -->
    <slot name="header"></slot>
    <!-- 不带 name 的 slot 出口会带有隐含的名字“default”。 -->
    <slot></slot> 
    <!--  -->
    <slot name="footer"></slot>

    <!-- 对于需要用容器包裹的slot, 可用$slots[name]加判断,避免渲染无效div -->
    <div v-if="$slots.btn">
      <slot name="btn"></slot>
    </div>
</div>


<!-- 父组件 -->
<child-comp>
    <!-- header插槽:v-slot 是 vue2.6.0 引入的,替代之前的 slot="header" 写法 -->
  <template v-slot:header>
    <h1>Here might be a page header</h1>
  </template>

  <!-- 默认插槽 等同于 v-slot:default -->
  <template>
    <h1>Here might be a page content</h1>
  </template>

  <!-- footer插槽 -->
  <template v-slot:footer>
    <h1>Here might be a page footer</h1>
  </template>
</child-comp>

现在 <template> 元素中的所有内容都将会被传入相应的插槽。任何没有被包裹在带有 v-slot<template> 中的内容都会被视为默认插槽的内容。

vue2.6.0之后可以用#缩写具名插槽:

<!-- 缩写 v-slot:header -->
<template #header>
    <h1>Here might be a page title</h1>
  </template>
  1. 作用域插槽

作用域插槽是为了让父组件中的插槽能够访问到子组件中的数据。

<!-- child-comp组件 -->
<div>
    <!-- 通过v-bind 可以向外传递参数 -->
    <slot name="header" v-bind:user="{name: 'tom', age: 22}"></slot>
</div>

<!-- 父组件 -->
<child-comp>
    <!-- 通过v-slot="scope"可以获取组件内部通过v-bind传的值 -->
    <!-- 当只有默认插槽时可以直接 v-slot="scope"  -->
    <!-- vue2.6.0之前可以这样写:slot="header" slot-scope="scope" -->
  <template v-slot:header="scope">
    <h1>{{scope.user.name}}</h1>
  </template>
</child-comp>

v-slot:header="scope"可进行解构,如:v-slot="{ user }"

  1. 递归插槽实现v-for组件
  • 常规递归v-for组件写法
<!-- VFor.vue -->
<template>
    <div>
        <!--  渲染第一项 -->
    {{ list[0] }}
        <!-- 如果我们有更多的项目,继续!但是不要使用我们刚刚渲染的项 -->
    <v-for
      v-if="list.length > 1"
            :list="list.slice(1)"
        />
    </div>
</template>


<!-- 使用 -->
<template>
  <v-for :list="list" />
</template>
  • 递归插槽实现
<!-- VFor.vue -->
<template>
  <div>
    <!-- Pass the item into the slot to be rendered -->
    <slot v-bind:item="list[0]">
      <!-- Default -->
      {{ list[0] }}
    </slot>

    <v-for
      v-if="list.length > 1"
      :list="list.slice(1)"
    >
      <!-- Recursively pass down scoped slot -->
      <template v-slot="{ item }">
        <slot v-bind:item="item" />
      </template>
    </v-for>
  </div>
</template>


<!--使用-->
<template >
     <v-for :list="list">
        <template v-slot="{ item }">
          <strong>{{ item }}</strong>
        </template>
    </v-for>
</template>

# 函数式组件

函数式组件为没有内部状态,没有生命周期钩子函数,没有this(不需要实例化的组件)。常用于进行纯静态渲染,没有js交互的场景。

  • 写法一:
<template functional>
    <div class="topic">
        <span class="mr-r-10">#{{props.item.topicName}}</span>
        <div v-if="props.type === 'comment'" class="time">{{props.item.addTime}}</div>
        <slot></slot>
    </div>
</template>
  • 写法二:
export default {
  // 通过配置functional属性指定组件为函数式组件
  functional: true,
  // 组件接收的外部属性
  props: {
    avatar: {
      type: String
    }
  },
  /**
   * 渲染函数
   * @param {*} h
   * @param {*} context 函数式组件没有this, props, slots等都在context上面挂着
   */
  render(h, context) {
    const { props } = context
    if (props.avatar) {
      return <img src={props.avatar}></img>
    }
    return <img src="default-avatar.png"></img>
  }
}

函数式组件不需要实例化,无状态,没有生命周期,所以渲染性能要好于普通组件。

函数式组件与普通组件的区别

  • 函数式组件需要在声明组件是指定functional
  • 函数式组件不需要实例化,所以没有this,this通过render函数的第二个参数context来代替;
  • 函数式组件没有生命周期钩子函数,不能使用计算属性,watch等等;
  • 函数式组件不能通过$emit对外暴露事件,调用事件只能通过context.listeners.click的方式调用外部传入的事件;
  • 因为函数式组件是没有实例化的,所以在外部通过ref去引用组件时,实际引用的是HTMLElement
  • 函数式组件的props可以不用显示声明,所以没有在props里面声明的属性都会被自动隐式解析为prop,而普通组件所有未声明的属性都被解析到$attrs里面,并自动挂载到组件根元素上面(可以通过inheritAttrs属性禁止)

# Vue.extend开发插件

直接上完整代码吧~

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>vue test</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">
            <p>extend进阶用法</p>
            <button @click="showLoading">显示Loading</button>
    </div>
    <script>

        // 1.通过Vue.extend创建一个组件的构造函数LoadingComponent
        const LoadingComponent = Vue.extend({
            template: '<div id="loading-wrapper">{{msg}}</div>',
            props: {
                msg: {
                type: String,
                default: 'msg'
                }
            }
        }, 'LoadingComponent');

        // 2.定义Loading方法
        function Loading(msg) {
            const div = document.createElement('div');
            div.setAttribute('id', 'loading-wrapper');
            document.body.append(div);

            // 创建LoadingComponent实例,并通过$mount挂载到元素上,直接覆盖原来的loading-wrapper
            new LoadingComponent({
                props: {
                    msg: {
                        type: String,
                        default: msg
                    }
                }
            }).$mount('#loading-wrapper');

            // 执行该方法移除该dom
            return () => {
                document.body.removeChild(document.getElementById('loading-wrapper'))
            }
        }

        // 3.把Loading方法挂载到原型上面
        Vue.prototype.$loading = Loading;


        new Vue({
            el: '#root',
            methods: {
                showLoading() {
                    // 调用$loading方法
                    const hide = this.$loading('正在加载,请稍等...');
                    setTimeout(() => {
                        hide();
                    },3000)

                }
            }
        })
    
    </script>
</body>
</html>

# Vue.observable进行状态管理

Vue.observablevue2.6提供的新API (opens new window),让一个对象可响应;在小型项目中可以用它来代替Vuex,实现状态管理。

  1. 创建store.js
import Vue from 'vue';

// 通过Vue.observable创建一个可响应的对象
const state = Vue.observable({
    count: 0,
})

// 定义 mutations, 修改属性
const mutations = {
    setState(params) {
        state[params.type] = params.value;
    }
}

export {
    state,
    mutations
}
  1. 组件中引用
<template>
  <div>
    {{count}}
    <button @click="change">add</button>
  </div>
</template>
<script>
import { state, mutations } from '../store'
export default {
  computed: {
    count() {
      return state.count
    }
  },
    methods: {
        change() {
            mutation.setState({type: 'count', value: state.count += 1})
        }
    }
}
</script>

# $dispatch$broadcast通信

$dispatch$broadcast是Vue1.0提供的一种方式 (opens new window),在Vue2.0中废弃了。

  • $dispatch: $dispatch会向上触发一个事件,同时传递要触发的祖先组件的名称与参数,当事件向上传递到对应的组件上时会触发组件上的事件侦听器,同时传播会停止。

  • $broadcast: $broadcast会向所有的后代组件传播一个事件,同时传递要触发的后代组件的名称与参数,当事件传递到对应的后代组件时,会触发组件上的事件侦听器,同时传播会停止(因为向下传递是树形的,所以只会停止其中一个叶子分支的传递)。

这里手动实现下$dispatch$broadcast

  1. 创建
// mixins/emitter.js

/**
 *  broadcast 向下传播事件
 * @param {*} eventName 事件名称
 * @param {*} componentName 要触发组件的名称
 * @param  {...any} params 传递的参数
 */
function broadcast(componentName, eventName, params) {
    // 遍历子组件
    this.$children.forEach(child => {
        var name = child.$options.componentName || child.$options.name;
        if (name === componentName) { // 找到需要触发事件的组件名
            child.$emit.apply(child, [eventName].concat(params));
        } else { // 否则继续在子组件中递归调用broadcast
            broadcast.apply(child, [componentName, eventName].concat([params]));
        }
    });
}


/**
 * dispatch 向上派发事件
 * @param {*} eventName 事件名称
 * @param {*} componentName 接收事件的组件名称
 * @param {...any} params 传递的参数,可以有多个
 */
function dispatch(componentName, eventName, params) {
  // 如果没有$parent, 则取$root
  var parent = this.$parent || this.$root;
  while (parent) {
    // 组件的name存储在组件的$options.componentName 上面
    const name = parent.$options.componentName || parent.$options.name
    // 如果接收事件的组件是当前组件
    if (name === componentName) {
      // 通过当前组件上面的$emit触发事件,传递事件名称与参数,跳出循环
      parent.$emit.apply(parent, [eventName].contat(params))
      break
    } else {
      // 否则继续向上判断
      parent = parent.$parent
    }
  }
}


export default {
    methods: {
        $broadcast(componentName, eventName, params) {
            broadcast.call(this, componentName, eventName, params);
        },
        $dispatch(componentName, eventName, params) {
            dispatch.call(this, componentName, eventName, params);
        },
    }
}
  1. 应用
// Child.vue
import emitter from '@/mixins/emitter'
export default {
  name: 'Child',
  mixins: [emitter],
  mounted() {
     // 在组件渲染完之后,将组件通过$dispatch向上注册到Father组件上
    this.$dispatch('register', 'Father', this)
  },
  created() {
    // 监听刷新事件
    this.$on('refresh',(params) => {
        // 
    })
  }
}


// Father.vue
export default {
  name: 'Father',
  created() {
    this.$on('register',(component) => {
      // 处理注册逻辑
    })
  },
  methods: {
        //在需要的时候,刷新组件
        reload(params) {
            // 将refresh事件向下注册到Child组件
            this.$broadcast('refresh', 'Child', params)
        }
  }
}

这种事件流方式不那么容易理解,维护成本高,且没有解决兄弟组件间的通信问题;替代方案就是使用更加简明清晰的Vuexevent bus

# 通过event bus实现通信

通过使用事件中心,允许组件自由交流,无论组件处于组件树的哪一层。可以通过实例化一个空的 Vue 实例来实现这个目的。

  1. 创建一个eventBus
// utils/eventBus.js
import Vue from 'vue';
const eventBus = new Vue();
export default eventBus;
  1. 通过$emit分发事件
// A.vue
import eventBus from '@/utils/eventBus';
methods: {
    handleClick(el) {
        eventBus.$emit('touchClick', el.target); // 分发事件
    }
}

这样在每次执行handleClick事件时,都会在eventBus中触发这个名为touchClick的事件,并将el.target顺着事件传递出去。

  1. 通过$on、$off实现监听和取消监听
// B.vue
import eventBus from '@/utils/eventBus';

created() {
    // 监听事件
    eventBus.$on('touchClick', res => {
        console.log(res);
    })

    // 在组件销毁前清除监听
    this.$on('hook:beforeDestroy',() => {
        eventBus.$off('touchClick');
    })
}

这样,在A.vue中每次执行handleClick事件时,就会把el.target传递到B.vue中,并打印出来。

# 使用 require.context 自动引入组件和路由、

webpack提供的自动获取文件的方法,具体参考官方文档 (opens new window)

  • 用法
// 实际上是 webpack 的方法,vue 工程一般基于 webpack,所以可以使用
require.context(directory,useSubdirectories,regExp)
// 接收三个参数:
// directory:说明需要检索的目录
// useSubdirectories:是否检索子目录
// regExp: 匹配文件的正则表达式,一般是文件名
  • 例子
///// a、自动遍历router文件夹下的.r.js文件
const allRoutes = [];
const routerContext = require.context('../router', false, /\.r\.js$/);
routerContext.keys().forEach(v => {
    const routerModule = routerContext(v);
    //  兼容 import export 和 require module.export 两种规范
    allRoutes = [...allRoutes, ...(routerModule.default || routerModule)];
});
////


// b、自动注入全局组件:只获取.g.vue类型的子文件
import Vue from 'vue';
const compsCtx = require.context('.', true, /\.g\.vue$/);
compsCtx.keys().forEach(filename => {
    const comp = compsCtx(filename).default;
    Vue.component(comp.name, comp);
});

# 渲染函数 & JSX

JSX是一种Javascript的语法扩展,JSX = Javascript + XML,即在Javascript里面写XML,因为JSX的这个特性,所以他即具备了Javascript的灵活性,同时又兼具html的语义化和直观性。

官方 (opens new window)

(待补充...)

# Vue中Pug模板的使用

(待补充...)

# 其他

动态组件<component/>、混入mixins、过滤filter等这些都是常用的,不再赘述~

# 备注

暂无~

# 参考

Back
上次更新: 2/19/2024, 3:46:14 PM
最近更新
01
taro开发实操笔记
09-29
02
前端跨端技术调研报告
07-28
03
Flutter学习笔记
07-15
更多文章>