Vue的插槽,组件,边界情况,自定义指令,渲染函数,插件,过滤器

复习

  • 组件注册

    • 全局组件:用vue.component 必须有templete
    • 全局注册的行为必须在根 Vue 实例 (通过 new Vue) 创建之前发生
    • 组件命名:
    • 局部组件:定义组件名,给一个对象自变量。放的组件定义的option
  • options

    • 关于选项、数据开头的
  • yarn init

    在script写脚本在这里插入图片描述

    yarn start

  • 局部组件可以自定义属性

  • props

    • prop定义规则:camelCase(驼峰命名) 需要使用其等价的kebab-case(短横线分隔命名法)

    • 验证方式:手工定义props,不能约束属性类型

      Vue.component('my-component', {
        props: {
          // 基础的类型检查 (`null` 和 `undefined` 会通过任何类型验证)
          propA: Number,
          // 多个可能的类型
          propB: [String, Number],
          // 必填的字符串
          propC: {
            type: String,
            required: true
          },
          // 带有默认值的数字
          propD: {
            type: Number,
            default: 100
          },
          // 带有默认值的对象
          propE: {
            type: Object,
            // 对象或数组默认值必须从一个工厂函数获取
            default: function () {
              return { message: 'hello' }
            }
          },
          // 自定义验证函数
          propF: {
            validator: function (value) {
              // 这个值必须匹配下列字符串中的一个
              return ['success', 'warning', 'danger'].indexOf(value) !== -1
            }
          }
        }
      })
      
    • 属性类型[String,Number,Boolean,Array,Object,Function,Date,Symbol]

    • 属性传递类型

      • 静态传递
      • 动态传递
    • 继承方向:inhertAttrs

      • true 允许继承
      • false禁用继承(不会影响style和class的绑定)
  • 单向数据流:不许在子组件直接修改props

    • 解决方法:
      在这里插入图片描述
  • sync修饰符

    • 能不能在子组件修改父组件遍历

    • $parent 直接改

    • 在子组件通过派发事件让父组件改变

    • bind绑定属性,加sync

    • 通过update前缀的事件

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

      • v-bind:title.sync=”doc.title + ‘!’” 是无效的
        
    • 当我们用一个对象同时设置多个 prop 的时候,也可以将这个 .sync 修饰符和 v-bind 配合使用:

      <text-document v-bind.sync="doc"></text-document>
      
  • 自定义事件

    • 需要始终使用 kebab-case 的事件名。

    • $emit

    • v-model 具有checkbox能力

    • 将原始事件绑定到组件上,可以使用v-on 的.native修饰符

      • <base-input v-on:focus.native="onFocus"></base-input>
        

插槽slot

  • 缩写 #( 该缩写只在其有参数的时候才可用)

  • 在子组件通过slot读取内容

  • slot里没有内容,就自动读取默认值,

  • 作用域

    • 父级模板的所有内容都是在父组件定义的
  • 作用域插槽

动态组件和异步组件

  • 缓存操作 keep-alive
  • activated 处理keep-alive缓存组件
  • deactivated 离开keep-alive组件,没有卸载,
  • activated,deactivated 钩子只针对keep-alive

处理边界情况 gap

  • 在绝大多数情况下,我们最好不要触达另一个组件实例内部或手动操作 DOM 元素,不过也确实在一些情况下做这些事情是合适的。

    • 访问根实例

      • 所有的子组件都可以将这个实例作为一个全局 store 来访问或使用
      • 获取根组件的数据
      • 写入根组件的数据
      • 访问根组件的计算属性
      • 调用根组件的方法
    • 访问父级组件实例

      • $root 类似,$parent property 可以用来从一个子组件访问父组件的实例。它提供了一种机会,可以在后期随时触达父级组件,以替代将数据以 prop 的方式传入子组件的方式。
    • 访问子组件实例或子元素

      • 可以通过 ref 这个 attribute 为子组件赋予一个 ID 引用

        <base-input ref="usernameInput"></base-input>
             
             this.$refs.usernameInput
        
      • refv-for 一起使用的时候,你得到的 ref 将会是一个包含了对应数据源的这些子组件的数组。

      • $refs 只会在组件渲染完成之后生效,并且它们不是响应式的。这仅作为一个用于直接操作子组件的“逃生舱”——你应该避免在模板或计算属性中访问 $refs

依赖注入 inject

  • 组件间数据传递(共享)

    • 父子组价间:属性+props类型定义,$emit
    • 亲兄弟组件间:中间人模式/状态提升
    • 有共同祖先节点的组件:依赖注入
    • BUS总线 (不推荐) :是vue的一个实例
    • Vuex(通用的实现方案)
  • 依赖注入:在某个祖先节点R上注入信息,R的后代都能拿到信息

  • 提供器 provide provide:{x:0 }

    • 修改了 provide,后代组件不响应
    • 不要在后代组件试图修改 provide
  • 注入器 inject

    • inject:[‘x’] 把注入的内容用数组定义
  • bus总线

    • 在当前模块内定义的变量,是不能再当前组件的实例上使用的

    • 没有响应特性,需要有$forceUpDate()

递归组件 recursive

  • 组件调用自己
  • 可能会造成堆栈溢出,需要添加递归出口来终止循环
  • 组件间循环引用
    • 使用webpack异步组件可以解决
    • 使用全局组件来解决

模板定义的替代品

  • x-template
    • 在一个 <script> 元素中,并为其带上 text/x-template 的类型,然后通过一个 id 将模板引用过去
    • x-template 需要定义在 Vue 所属的 DOM 元素外。
  • 内联模板
    • 内联模板需要定义在 Vue 所属的 DOM 元素内。
  • 控制更新
    • 强制更新forceUpdata
    • v-once 创建低开销的静态组件

可复用性组合

混入 mixin

  • 为什么要使用混入

    • 混入 (mixin) 提供了一种非常灵活的方式,来分发 Vue 组件中的可复用功能。一个混入对象可以包含任意组件选项。当组件使用混入对象时,所有混入对象的选项将被“混合”进入该组件本身的选项。
  • 全局混入

    • Vue.mixin
    • 一旦使用全局混入,它将影响每一个之后创建的 Vue 实例
  • 局部混入

    • mixin:[mixin]
  • 会进行覆盖,组件内部定义的优先

  • mixin会深覆盖

    • object.assign() 浅覆盖
  • 生命周期钩子都会执行

  • 生命周期钩子中,混入的先之后,自己的后执行

  • 当组件和混入对象含有同名选项时,这些选项将以恰当的方式进行“合并”。比如,数据对象在内部会进行递归合并,并在发生冲突时以组件数据优先。

  • 值为对象的选项,例如 methodscomponentsdirectives,将被合并为同一个对象。两个对象键名冲突时,取组件对象的键值对。

    var mixin = {
      methods: {
        foo: function () {
          console.log('foo')
        },
        conflicting: function () {
          console.log('from mixin')
        }
      }
    }
    
    var vm = new Vue({
      mixins: [mixin],
      methods: {
        bar: function () {
          console.log('bar')
        },
        conflicting: function () {
          console.log('from self')
        }
      }
    })
    
    vm.foo() // => "foo"
    vm.bar() // => "bar"
    vm.conflicting() // => "from self"
    
  • 同名钩子函数将合并为一个数组,因此都将被调用。另外,混入对象的钩子将在组件自身钩子之前调用。

    var mixin = {
      created: function () {
        console.log('混入对象的钩子被调用')
      }
    }
    
    new Vue({
      mixins: [mixin],
      created: function () {
        console.log('组件钩子被调用')
      }
    })
    
    // => "混入对象的钩子被调用"
    // => "组件钩子被调用"
    

自定义指令 directive

  • 需要写DOM操作

  • 怎么定义

    • // 注册一个全局自定义指令 `v-focus`
      Vue.directive('focus',{ 
          // 当被绑定的元素插入到 DOM 中时
         inserted(el){
           // 聚焦元素
          el.focud()
        }
      })
      
  • 如果想注册局部指令,组件中也接受一个 directives 的选项:

    directives: {
      focus: {
        // 指令的定义
        inserted: function (el) {
          el.focus()
        }
      }
    }
    
  • 钩子函数

    • bind : 只调用一次,指令第一次绑定到元素时调用。在这里可以进行一次性的初始化设置。
    • inserted : 被绑定元素插入父节点时调用 (仅保证父节点存在,但不一定已被插入文档中)。
    • updated: 所在组件的 VNode 更新时调用,但是可能发生在其子 VNode 更新之前。指令的值可能发生了改变,也可能没有。
    • unbind:只调用一次,指令与元素解绑时调用。
    • componentUpdated:指令所在组件的 VNode 及其子 VNode 全部更新后调用。
  • 指令需要具备的要素

    • v-开头
    • 参数
    • 修饰符
  • 定义指令的范式

    • Vue.directive('font',(el,binding)=>{
        el.style.color="red"
      })
      
      
      //解构
      Vue.directive('font',(el,{arg,modifiers,value})=>{
        el.style.color=arg
        el.style.fontWeight=Object.keys(modifiers)[0]
        el.style.fontSize=value  
      })
      
      • el:指令所绑定的元素,可以用来直接操作 DOM。
      • binding 是形参,是一个对象,可以用来直接操作DOM
        • name:指令名,不包括 v- 前缀。
        • value:指令的绑定值,例如:v-my-directive="1 + 1" 中,绑定值为 2
        • oldvalue:指令绑定的前一个值,仅在 updatecomponentUpdated 钩子中可用。无论值是否改变都可用。
        • expression:字符串形式的指令表达式.例如 v-my-directive="1 + 1" 中,表达式为 "1 + 1"
        • arg:传给指令的参数,可选.例如 v-my-directive:foo 中,参数为 "foo"
        • modifiers:一个包含修饰符的对象。可以连缀.例如:v-my-directive.foo.bar 中,修饰符对象为 { foo: true, bar: true }
      • vnode:Vue 编译生成的虚拟节点
      • oldVnode:上一个虚拟节点,仅在 updatecomponentUpdated 钩子中可用。
      • 除了 el 之外,其它参数都应该是只读的,切勿进行修改。如果需要在钩子之间共享数据,建议通过元素的 dataset 来进行。
  • 如何取对象的key

    • Object.keys
  • 局部定义

渲染函数

  • 特殊钩子函数render

    • Vue.component('Child',{
       
        created(){
          console.log('created')
        }
        
         render(createElement){
             return createElement(
             'div' ,         //创建的元素节点名字
            
            {
                attrs:{      //自定义属性
                  aaa:'aaaaa'
                 }
             },             //属性,可以写对象
            
            'hello'        //子节点
             )
          
        }
        
        mounted(){
           console.log('mounted')
         }
      
         //render会自动调用,处于created和mouted之间
         
      })
      
      • 参数
        • 名字
        • 属性
        • 子节点

节点,树以及虚拟DOM

  • 节点

    • 每个元素都是一个节点。每段文字也是一个节点。甚至注释也都是节点。一个节点就是页面的一个部分。就像家谱树一样,每个节点都可以有孩子节点 (也就是说每个部分可以包含其它的一些部分)。
  • 虚拟DOM

    • Vue 通过建立一个虚拟 DOM 来追踪自己要如何改变真实 DOM
  • createElement参数

    • (String|Object|Function)

      • 一个 HTML 标签名、组件选项对象,或者resolve 了上述任何一种的一个 async 函数。必填项。
    • {Object}

      • 一个与模板中 attribute 对应的数据对象。可选。
    • (String|Array)

      • 子级虚拟节点 (VNodes),由 createElement() 构建而成,也可以使用字符串来生成“文本虚拟节点”。可选。
  • 语法糖 JSX

    • render(){
      return  <div>hello</div>
      }
      
  • 约束

    • vNode必须唯一

    • 如果你真的需要重复很多次的元素/组件,你可以使用工厂函数来实现

      render: function (createElement) {
        return createElement('div',
          Array.apply(null, { length: 20 }).map(function () {
            return createElement('p', 'hi')
          })
        )
      }
      

插件 plugin

  • 增加vue的全局功能或者property
  • 在全局里加方法属性
  • 添加全局资源:指令/过滤器/过渡等
  • 通过全局混入来添加一些组件选项:如vue-route
  • 添加实例方法,通过把他们添加到Vue.prototype上实现
  • 一个库,提供自己的 API,同时提供上面提到的一个或多个功能,如vue-route

开发插件

const myPlugin={}
//(function(){})(Vue)
myPlugin.install=function(Vue,options){
   
   //1.全局的方法或者属性,自己定义的
     Vue.foo=(args)=>{
     
     }
     Vue.set()
    
    //2.添加全局的资源
    Vue.component('my-component',{
      template:`
       <div>hello</div>`
    })
    Vue.directive('font',(el,binding)=>{
      el.style.color=binding.value
    })
    
    //3.注入组件选项
    Vue.mixin({
    
    })
    
    //4.添加实例的方法
    Vue.protptype.$meta='aabbcc'
}
  
  Vue.use(myPlugin,{ x:0})
  • 1.添加全局的方法或者属性:在vue上直接调用

    • Vue.component
  • 2.添加全局的资源

    • 内置组件
      • component
      • template
      • keep-alive
  • 3.注入组件选项

  • 4.添加实例的方法

使用插件

  • 通过全局方法 Vue.use() 使用插件。它需要在你调用 new Vue() 启动应用之前完成
  • Vue.use 会自动阻止多次注册相同插件,届时即使多次调用也只会注册一次该插件。

过滤器 filter

  • Vue.js 允许你自定义过滤器,可被用于一些常见的文本格式化。过滤器可以用在两个地方:双花括号插值和 v-bind 表达式 (后者从 2.1.0+ 开始支持)。过滤器应该被添加在 JavaScript 表达式的尾部,由“管道”符号指示

    <!-- 在双花括号中 -->
    {{ message | capitalize }}
    
    <!-- 在 `v-bind` 中 -->
    <div v-bind:id="rawId | formatId"></div>
    
  • 你可以在一个组件的选项中定义本地的过滤器:

    filters: {
      capitalize: function (value) {
        if (!value) return ''
        value = value.toString()
        return value.charAt(0).toUpperCase() + value.slice(1)
      }
    }
    
  • 或者在创建 Vue 实例之前全局定义过滤器

    Vue.filter('capitalize', function (value) {
      if (!value) return ''
      value = value.toString()
      return value.charAt(0).toUpperCase() + value.slice(1)
    })
    
    new Vue({
      // ...
    })
    
  • 当全局过滤器和局部过滤器重名时,会采用局部过滤器:

  • 过滤器函数总接收表达式的值 (之前的操作链的结果) 作为第一个参数

  • 过滤器可以串联:

    {{ message | filterA | filterB }}
    
  • 过滤器是 JavaScript 函数,因此可以接收参数:

    {{ message | filterA('arg1', arg2) }}
    


value = value.toString()
return value.charAt(0).toUpperCase() + value.slice(1)
}
}


- 或者在创建 Vue 实例之前全局定义过滤器

Vue.filter(‘capitalize’, function (value) {
if (!value) return ‘’
value = value.toString()
return value.charAt(0).toUpperCase() + value.slice(1)
})

new Vue({
// …
})




- 当全局过滤器和局部过滤器重名时,会采用局部过滤器:

- 过滤器函数总接收表达式的值 (之前的操作链的结果) 作为第一个参数

- 过滤器可以串联:

{{ message | filterA | filterB }}


- 过滤器是 JavaScript 函数,因此可以接收参数:

{{ message | filterA(‘arg1’, arg2) }}


- 这里,`filterA` 被定义为接收三个参数的过滤器函数。其中 `message` 的值作为第一个参数,普通字符串 `'arg1'` 作为第二个参数,表达式 `arg2` 的值作为第三个参数。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值