阅读vue 文档学习笔记

v2.6

模板语法

可以用方括号括起来的 JavaScript 表达式作为一个指令的参数:
<a v-bind:[attributeName]="url"> ... </a>
同样地,你可以使用动态参数为一个动态的事件名绑定处理函数:
<a v-on:[eventName]="doSomething"> ... </a>
对动态参数的值的约束
动态参数预期会求出一个字符串,异常情况下值为 null。
这个特殊的 null 值可以被显性地用于移除绑定。
任何其它非字符串类型的值都将会触发一个警告。

计算属性缓存vs方法

计算属性基于它们的响应式依赖进行缓存,
这也同样意味着下面的计算属性将不再更新,因为 Date.now() 不是响应式依赖:

computed: {
  now: function () {
    return Date.now()
  }
}
计算属性的setter
computed:{
get:function(){
 return this.firstName+' '+this.lastName
},
set:function(newValue){
    var names=newValue.split(' ')
    this.firstName=names[0]
    this.lastName=names[names.length-1]
}
}
侦听器

虽然计算属性在大多数情况下更合适,但有时也需要一个自定义的侦听器。
这就是为什么 Vue 通过 watch 选项提供了一个更通用的方法,来响应数据的变化。
当需要在数据变化时执行异步或开销较大的操作时,这个方式是最有用的。

class与style绑定

绑定class
对象绑定

<div
  class="static"
  v-bind:class="{ active: isActive, 'text-danger': hasError }"
></div>

和如下 data:

data: {
  isActive: true,
  hasError: false
}
数组语法

我们可以把一个数组传给 v-bind:class,以应用一个 class 列表:

<div v-bind:class="[activeClass, errorClass]"></div>
data: {
  activeClass: 'active',
  errorClass: 'text-danger'
}

在数组中使用对象
<div v-bind:class="[{ active: isActive }, errorClass]"></div>

绑定内联样式

v-bind:style 的对象语法十分直观——看着非常像 CSS,但其实是一个 JavaScript 对象。
CSS 属性名可以用驼峰式 (camelCase) 或短横线分隔 (kebab-case,记得用引号括起来) 来命名:

<div v-bind:style="{ color: activeColor, fontSize: fontSize + 'px' }"></div>
data: {
  activeColor: 'red',
  fontSize: 30
}
数组语法数组语法

v-bind:style 的数组语法可以将多个样式对象应用到同一个元素上:

<div v-bind:style="[baseStyles, overridingStyles]"></div>

Vue.component('blog-post',{
    props:['title'],
    template:`<h3>{{title}}</h3>`
})
全局注册
Vue.component('my-component-name', {
  // ... 选项 ...
})
局部注册

在这些情况下,你可以通过一个普通的 JavaScript 对象来定义组件:

var ComponentA = { /* ... */ }
var ComponentB = { /* ... */ }
var ComponentC = { /* ... */ }

然后在 components 选项中定义你想要使用的组件:

new Vue({
  el: '#app',
  components: {
    'component-a': ComponentA,
    'component-b': ComponentB
  }
})
基础组件的自动化全局注册
import Vue from 'vue'
import upperFirst from 'lodash/upperFirst'
import camelCase from 'lodash/cameCase'
const requireComponent=require.context(
   //其组件目录的相对路径
  './components',
  //是否查询其子目录
  false,
  //匹配基础组件的文件名的正则表达式
  /Base[A-Z]\w+\.(vue|js)$/
)
requireComponent.keys().forEach(fileName=>{
    //获取组件配置
    const componentConfig=requireComponent(fileName)
    //获取组件的PascalCase命名
    const componentName=upperFirst(
        cmaeCase(
            fileName.split('/').pop().replace(/\.\w+$/,'')
        )
    )
//全局注册
Vue.component(componentName,
    //如果这个组件选项是通过'export default'导出
    //那么就会优先使用'.default'
    //否则回退到使用模块的根
    componentConfig.default||componnentConfig
)
})

传入一个对象的所有属性
如果你想要将一个对象的所有属性都作为 prop 传入,你可以使用不带参数的 v-bind (取代 v-bind:prop-name)。例如,对于一个给定的对象 post:

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

下面的模板:

<blog-post v-bind="post"></blog-post>
等价于:

<blog-post
  v-bind:id="post.id"
  v-bind:title="post.title"
></blog-post>
单向数据流

所有的 prop 都使得其父子 prop 之间形成了一个单向下行绑定:父级 prop 的更新会向下流动到子组件中,但是反过来则不行。这样会防止从子组件意外改变父级组件的状态,从而导致你的应用的数据流向难以理解。

额外的,每次父级组件发生更新时,子组件中所有的 prop 都将会刷新为最新的值。这意味着你不应该在一个子组件内部改变 prop。如果你这样做了,Vue 会在浏览器的控制台中发出警告。

这里有两种常见的试图改变一个 prop 的情形:

这个 prop 用来传递一个初始值;这个子组件接下来希望将其作为一个本地的 prop 数据来使用。在这种情况下,最好定义一个本地的 data 属性并将这个 prop 用作其初始值:

props: ['initialCounter'],
data: function () {
  return {
    counter: this.initialCounter
  }
}

这个 prop 以一种原始的值传入且需要进行转换。在这种情况下,最好使用这个 prop 的值来定义一个计算属性:

props: ['size'],
computed: {
  normalizedSize: function () {
    return this.size.trim().toLowerCase()
  }
}

注意在 JavaScript 中对象和数组是通过引用传入的,所以对于一个数组或对象类型的 prop 来说,在子组件中改变这个对象或数组本身将会影响到父组件的状态。

propF:{
validator:function(value){
 return ['success','danger'].indexOf(value)!==-1
}
}
将原生事件绑定到组件

在有的时候这是很有用的,不过在你尝试监听一个类似 <input> 的非常特定的元素时,这并不是个好主意。
比如上述 <base-input> 组件可能做了如下重构,所以根元素实际上是一个 <label> 元素:

Vue.component('base-input',{
    inheritAttrs:false,
    props:['label','value'],
    computed:{
        inputListeners:function(){
          var vm=this
          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>

一个不带 name 的 <slot> 出口会带有隐含的名字“default”。

在向具名插槽提供内容的时候,我们可以在一个 <template> 元素上使用 v-slot 指令,并以 v-slot 的参数的形式提供其名称:

<base-layout>
  <template v-slot:header>
    <h1>Here might be a page title</h1>
  </template>

  <p>A paragraph for the main content.</p>
  <p>And another one.</p>

  <template v-slot:footer>
    <p>Here's some contact info</p>
  </template>
</base-layout>

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

过渡js钩子
<transition v-on:enter="enter"></transition>

状态过滤-把过渡放组件里
Vue.component('animated-integer',{
template:'<span>{{tweeningValue}}</span>',
props:{
    value:{
    }
},
data:function(){
},
watch:{
},
mouted:function(){
},
methods:{

}

})
<div id="example">
 <animated-integer></animated-integer>
</div>
new Vue({
 el:'#example',
 data:{
  firstnumber:20,
  lastnumber:40
 },
 computed:{
    result:function(){
    
    }
 }

})

混入
var myMixin={
 created:function(){
  
 }
}
var Component=Vue.extend({
 mixins:[myMixin]
})
var component=new Component()

选项合并
1 数据对象在内部会进行递归合并,并在发生冲突时以组件数据优先。
2 同名钩子函数将合并为一个数组,因此都将被调用。另外,混入对象的钩子将在组件自身钩子之前调用

全局混入

Vue.mixin({
  created:function(){
    var myOption=this.$options.myOption
    if(myOption){
        console.log(myOption)
    }
  }
})

new Vue({
 myOption:'HELLO'
})
自定义选项合并策略

//函数
Vue.config.optionMergeStrategies.myOption=function(toVal,fromVal){
//返回合并后的值
}
//或者使用与methods相同的合并策略

var strategies=Vue.config.optionMergeStrategies
strategies.myOption=strategies.methods


const merge=Vue.config.optionMergeStrategies.computed
Vue.config.optionMergeStragies.vux=function(toVal,fromVal){
 if(!toVal) return fromVal
 if(!fromVal) return toVal
 return {
    getters:merge(toVal.getters,fromVal.getters),
    state:merge(toVal.state,fromVal.state),
    actions:merge(toVal.actions,fromVal.actions)
 }
}

自定义指令
全局指令

Vue.directive('focus',{
    //当被绑定元素插入到dom时
    inserted:function(el){
        //聚焦元素
        el.focus()
    }
})

注册局部指令,组件中也接受一个directives的选项

directives:{
    focus:{
        inserted:function(el){
            el.focus()
        }
    }
}
<input v-focus>

一个指令定义对象可以提供如下几个钩子函数 (均为可选):

bind:只调用一次,指令第一次绑定到元素时调用。在这里可以进行一次性的初始化设置。

inserted:被绑定元素插入父节点时调用 (仅保证父节点存在,但不一定已被插入文档中)。

update:所在组件的 VNode 更新时调用,但是可能发生在其子 VNode 更新之前。指令的值可能发生了改变,也可能没有。
但是你可以通过比较更新前后的值来忽略不必要的模板更新 (详细的钩子函数参数见下)。
componentUpdated:指令所在组件的 VNode 及其子 VNode 全部更新后调用。

unbind:只调用一次,指令与元素解绑时调用。

函数简写

在很多时候,你可能想在 bind 和 update 时触发相同行为,而不关心其它的钩子。比如这样写:

Vue.directive('color-swatch', function (el, binding) {
  el.style.backgroundColor = binding.value
})
渲染函数

createElement 参数

createElement(
  // {String | Object | Function}
  // 一个 HTML 标签名、组件选项对象,或者
  // resolve 了上述任何一种的一个 async 函数。必填项。
    'div',
    //{object} 一个与模板中属性对应的数据对象
    {
    
    },
    //子级虚拟节点(Vnode),由createElement(),构建而成
    //也可以使用字符串来生成‘文本虚拟节点’,可选
    [
     'some word',
     createElment(MyComponent,{
        props:{
            someProp:'foobar'
        }
     })
    ]

)

示例

var getChildrenTextContext=function(children){
    return children.map(function(node){
        return node.children?getChildrenTextContext(node.children):
        node.text
    }).join('')
}

Vue.component('anchored-heading',{
    render:function(createElement){
        var headingId=getChildrenTextContext(this.$slots.default)
        .toLowerCase()
        .replace(/\W+/g,'-')
        .replace(/(^-|-$)/,'')
        
        return createElement(
            'h'+this.level,
            [
              createElement('a',{
                attrs:{
                    name:headingId,
                    href:'#'+headingId
                }
              },this.$slots.default)
            ]
        )
    },
    props:{
        level:{
            type:Number,
            required:true
        }
    }
    
})
//v-model
props:['value'],
render:function(createElement){
 var self=this
 return createElement('input',{
    domProps:{
        value:self.value
    },
    on:{
        input:function(event){
            self.$emit('input',event.target.value)
        }
    }
 })
}
函数式组件

之前创建的锚点标题组件是比较简单,没有管理任何状态,也没有监听任何传递给它的状态,也没有生命周期方法。实际上,它只是一个接受一些 prop 的函数。
在这样的场景下,我们可以将组件标记为 functional,这意味它无状态 (没有响应式数据),也没有实例 (没有 this 上下文)。

Vue.component('my-component',{
 functional:true,
 props:{
    
 },
 render:function(createElement,content){
 
 }
})
插件

插件通常用来为 Vue 添加全局功能。插件的功能范围没有严格的限制——一般有下面几种:

添加全局方法或者属性。如: vue-custom-element

添加全局资源:指令/过滤器/过渡等。如 vue-touch

通过全局混入来添加一些组件选项。如 vue-router

添加 Vue 实例方法,通过把它们添加到 Vue.prototype 上实现。

一个库,提供自己的 API,同时提供上面提到的一个或多个功能。如 vue-router

Vue.js 的插件应该暴露一个 install 方法。这个方法的第一个参数是 Vue 构造器,第二个参数是一个可选的选项对象:

MyPlugin.install=function(Vue,options){
    //全局方法或属性
    Vue.myGlobalMethod=function(){
    
    }
    //添加全局资源
    Vue.directive('my-directive',{
        bind(el,binding,vnode,oldVnode){
        
        }
    })
    //注入组件选项
    Vue.mixin({
        created:function(){
        
        }
        
    })
    //添加实例方法
    Vue.prototype.$myMethod=function(methodOptions){
    
    }
}
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,839评论 6 482
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,543评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 153,116评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,371评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,384评论 5 374
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,111评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,416评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,053评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,558评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,007评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,117评论 1 334
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,756评论 4 324
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,324评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,315评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,539评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,578评论 2 355
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,877评论 2 345