前言
本文是通读vue文档的笔记,记录了自己忽略或者不熟悉的知识点,以便后续查阅。有些语言描述是根据自己的理解而来的,表达可能不够准确,如有疑惑,还请查阅官方文档,当然也希望与您一起谈论,共同进步。(未完)
基础
- v-once: 使用它可以计算一次后不再计算,大大提高性能,但是只要在确定不会再有更新的时候使用
- 强制更新$forceUpdate
- key 管理可复用的元素:Vue 会尽可能高效地渲染元素,通常会复用已有元素而不是从头开始渲染。但是有时这些元素需要相互独立,不能复用他们,此时需要添加一个唯一的key值即可;
- v-if 与 v-show
- 可以在
<template>元素上使用v-if条件渲染分组,v-for列表渲染 - v-for 可以使用对象
vue 实例
- vue实例在生成的过程中会有一系列的动作,需要设置数据监听 编译模板 将实例挂载到dom并在数据变化是更新dom等
- 生命周期
模板语法
- v-html: 你的站点上动态渲染的任意 HTML 可能会非常危险,因为它很容易导致 XSS 攻击。
计算属性和侦听器
- computed具有缓存功能,不能传参;methods没有缓存功能,可以传参; watch 当需要根据变化执行异步操作或者开销比较大的时候使用。
事件处理
- 事件修饰符:
.stop .prevent .capture .self .once .passive - 按键修饰符:
.enter .tab .delete .esc .space .up .down - 系统修饰符:
ctrl .alt .shift .meta - .exact修饰符 : 精确触发
- 鼠标按钮修饰符:
.left .right .middle
深入了解组件
组件注册
-
全局注册基础组件:对于一些可能频繁用到的基础组件,可以在webpack(或者vue-cli3)中使用require.context 全局注册
import Vue from 'vue' import upperFirst from 'lodash/upperFirst' import camelCase from 'lodash/camelCase' const requireComponent = require.context( // 其组件目录的相对路径 './components', // 是否查询其子目录 false, // 匹配基础组件文件名的正则表达式 /Base[A-Z]\w+\.(vue|js)$/ ) requireComponent.keys().forEach(fileName => { // 获取组件配置 const componentConfig = requireComponent(fileName) // 获取组件的 PascalCase 命名 const componentName = upperFirst( camelCase( // 获取和目录深度无关的文件名 fileName .split('/') .pop() .replace(/\.\w+$/, '') ) ) // 全局注册组件 Vue.component( componentName, // 如果这个组件选项是通过 `export default` 导出的, // 那么就会优先使用 `.default`, // 否则回退到使用模块的根。 componentConfig.default || componentConfig ) })
Prop
- 动态prop: prop作为父级向子组件传递数据时使用,可使用
:传递动态prop(包括boolean,数组,对象,变量,表达式,数字); - prop验证:子组件接受数据是可以使用对象的方式验证(type,default,require)
- 单项数据流:子组件可以通过data,compute接受传递的数据。对于作为引用类型的对象和数组,需要格外小心,不能在子组件中修改prop。确实需要修改可以复制一分副本
- 合并/替换:对于大多数prop,使用替换的方式作用的组件的根元素中,而style class则可以智能的合并;如果不希望根元素被替换可以使用
Vue.component('my-component', {
inheritAttrs: false,
// ...
})
自定义事件
-
组件和prop名称都会自动将大写字母转换为小写,事件名称不会
-
v-model
Vue.component('base-checkbox', { model: { prop: 'checked', event: 'change' }, props: { checked: Boolean }, template: ` <input type="checkbox" v-bind:checked="checked" v-on:change="$emit('change', $event.target.checked)" > ` }) -
.sync 修饰符
<text-document v-bind:title="doc.title" v-on:update:title="doc.title = $event" ></text-document>等价于
<text-document v-bind:title.sync="doc.title"></text-document> -
将原生事件绑定到组件 :
.native具有局限性 可以使用v-on="$listeners"Vue.component('base-input', { inheritAttrs: false, props: ['label', 'value'], computed: { inputListeners: function () { var vm = this // `Object.assign` 将所有的对象合并为一个新对象 return Object.assign({}, // 我们从父级添加所有的监听器 this.$listeners, // 然后我们添加自定义监听器, // 或覆写一些监听器的行为 { // 这里确保组件配合 `v-model` 的工作 input: function (event) { vm.$emit('input', event.target.value) } } ) } }, template: ` <label> {{ label }} <input v-bind="$attrs" v-bind:value="value" v-on="inputListeners" > </label> ` })
插槽
-
父级模板里的所有内容都是在父级作用域中编译的;子模板里 的所有内容都是在子作用域中编译的
-
后备内容
-
具名插槽
组件实例:
<div class="container"> <header> <slot name="header"></slot> </header> <main> <slot></slot> </main> <footer> <slot name="footer"></slot> </footer> </div>使用实例:
<base-layout> <template v-slot:header> <h1>Here might be a page title</h1> </template> <!--或者使用<template v-slot:default>--> <p>A paragraph for the main content.</p> <p>And another one.</p> <template v-slot:footer> <p>Here is some contact info</p> </template> </base-layout> -
作用域插槽示例:
组件中绑定 <span> <slot v-bind:user="user"> {{ user.lastName }} </slot> </span> 使用: <current-user> <template v-slot:default="slotProps"> {{ slotProps.user.firstName }} </template> </current-user> -
动态插槽名
<base-layout> <template v-slot:[dynamicSlotName]> ... </template> </base-layout> -
具名插槽缩写
<base-layout> <template #header> <h1>Here might be a page title</h1> </template> </base-layout> -
解构
-
旧语法
<slot-example>
<template slot="default" slot-scope="slotProps">
{{ slotProps.msg }}
</template>
</slot-example>
动态组件&异步组件
- 在动态组件上使用keep-alive
- 在大型应用中,我们可能需要将应用分割成小一些的代码块,并按需加载:如下代码示例:
Vue.component('async-webpack-example', function (resolve) { // 这个特殊的 `require` 语法将会告诉 webpack // 自动将你的构建代码切割成多个包,这些包 // 会通过 Ajax 请求加载 require(['./my-async-component'], resolve) })Vue.component( 'async-webpack-example', // 这个 `import` 函数会返回一个 `Promise` 对象。 () => import('./my-async-component') )
组件间传值
- 关键词:根组件
$route父级$parent父级到子组件prop子组件触发父级$emit祖级传递给子级provide子级接收祖级inject混入mixinx - 父级访问子组件实例或子元素ref,子级不能访问不要父级ref
- 事件监听器
$on$once$off
模板定义的替代品
-
inline-template : 这里组件会使用组件里面的内容作为模板
<my-component inline-template> <div> <p>These are compiled as the component's own template.</p> <p>Not parent's transclusion content.</p> </div> </my-component> -
X-Template
<script type="text/x-template" id="hello-world-template"> <p>Hello hello hello</p> </script>Vue.component('hello-world', { template: '#hello-world-template' })
过渡 & 动画
可复用性 & 组合
混入
- mixins 可以混合到组件中,选项合并,也可以定义合并策略
自定义指令
- directive
渲染函数 & JSX
插件
- 插件使用示例:
或者// 调用 `MyPlugin.install(Vue)` Vue.use(MyPlugin) new Vue({ // ...组件选项 })Vue.use(MyPlugin, { someOption: true }) - 插件开发实例:
MyPlugin.install = function (Vue, options) { // 1. 添加全局方法或属性 Vue.myGlobalMethod = function () { // 逻辑... } // 2. 添加全局资源 Vue.directive('my-directive', { bind (el, binding, vnode, oldVnode) { // 逻辑... } ... }) // 3. 注入组件选项 Vue.mixin({ created: function () { // 逻辑... } ... }) // 4. 添加实例方法 Vue.prototype.$myMethod = function (methodOptions) { // 逻辑... } }