VUE 入门基础(9)

十一,深入响应式原理 

  声明响应式属性
    由于Vue不允许动态添加根级响应式属性,所以你必须在初始化实例钱声明根级响应式属性,哪怕只有一个空值。   

     var vm = new Vue({ 
          data:{ 
            // 声明 message 为一个空字符串
            message: ' '
          },
        template: '<div>{{ message }}</div>'
      })
      // vm.message = 'Hello!'
      vm.message = 'Hello!'

      如果你在data 选项中未声明 message,Vue 将警告你渲染函数早试图访问的属性不存在。

     异步更新队列

     <div id="example">{{message}}</div>
      var vm = new Vue({ 
        el:'#example',
        data: { 
          message: '123'
        }
      })
     vm.message = 'new message' // 更改数据
     vm.$el.textContent === 'new message' // false
     Vue.nextTick(function() { 
        vm.$el.textContent === 'new message' //true
      })

    在组件内使用 vm.$nextTick() 实例方法特别方便,应为它不需要全局Vue ,并且回调函数中 this
    将自动绑定到当前Vue

    Vue.component('example', { 
      template: '<span> {{ message }}</span>',
      data: function() { 
        return { 
            message: 'not updated'
          } 
      },
      methods: { 
      updateMessage: function() { 
      this.message = 'updated'
      console.log(this.$el.textContent) // => 'not updated'
      this.$nextTick(function () { 
          console.log(this.$el.textContent) // => 'updated'
      })
      }
       } 
    })

十二,过度效果
   在插入,更新或者移除DOM 时,提供多种不同方式的应用过度效果。
      在css过度和动画中自动应用class
        可以配合使用第三方css 动画库,如Animate.css
        在过度钩子函数中使用JavaScript 直接操作DOM
        可以配合使用第三方JavaScript 动画库,如velocity.js

  

   单元素/组件的过度。
      vue提供l了 transition 的封装组件,在下列情形中,可以给任何元素和组件添加entering/leaving过度
        条件渲染使用(使用 v-if)
        条件展示(使用 v-show)
   动态组件
     组件跟节点
        例子:

          <div id="demo">
              <button v-on:click="show = !show">
                Toggle
              </button>
              <transition name=fade>
                 <p v-if="show">hello</p>
              </transition>
          </div>
          new Vue({ 
              el:'#demo',
              data: { 
                show: true
              }
          })
          .fade-enter-active, .fade-leave-active { 
              transition:opacity .5s
           }
          .fade-enter, .fade-leave { 
              opacity: 0
          }

    元素封装成过渡组件之后,在遇到插入或删除时,Vue 将
      1.自动嗅探目标元素是否有 CSS 过渡或动画,并在合适时添加/删除 CSS 类名。
      2.如果过渡组件设置了过渡的 JavaScript 钩子函数,会在相应的阶段调用钩子函数
      3.如果没有找到 JavaScript 钩子并且也没有检测到 CSS 过渡/动画,DOM 操作(插入/删除)在下一帧中立即执行

   #过度的-css-类名
      会有4个css 类名在enter/leave 的过度中切换
          1. v-enter: 定义进入过度的开始状态,在元素被插入的时生效,在下一个帧移除。
          2.v-enter-actvie 定义进入过度的结束状态,在元素被插入时生效,在transition
             /animation 完成之后移除。
          3.v-leave: 定义离开过度的开始状态,在离开过度被触发时生效,在下一个帧移除。
          4.v-leave-active: 定义离开过度的结束状态,在离开过度被处罚时生效,在transition/animation 完成之后移除。

     css 过渡
      常用的过度都是使用css 过渡
        例子

         <div id="example-1">
            <button @click="show= !show">
              Toggle render
            </button>
            <transition name="slide-fade">
              <p v-if="show">hello</p>
            </transition>
          </div>
            new Vue({ 
              el: '#example-1,
              data: { 
                  show:true
                }
            })

        // 可以设置不同的进入和离开动画
        //设置持续时间和动画函数

         .slide-fade-enter-active{ 
              transition: all .3s ease;
          }
          .slide-fade-leave-active{ 
              transition: all .8s cubic-bezier(1.0,0.5,0.8,1.0);
          }
          .slide-fade-enter, .slide-fade-leave-active{ 
              transition: translateX(10px);
              opacity: 0;
          }

   css 动画

      css 动画用法同 css 过渡,区别是在动画中v-enter 类名节点插入DOM后
      会不会立即删除,而是在animationend 事件触发时删除。
       实例:

         <div id="example-2">
              <button @click="show = !show">Toggle show</button>
              <transition name="bounce">
                <p v-if="show">Look at me!</p>
              </transition>
          </div>
           new Vue({ 
               el: '#example-2',
               data: { 
                    show: true
              }
          })
          .bounce-enter-active { 
            animation: bounce .5s;
          }
          .bounce-leave-active { 
            animation: bounce .5s;
          }
          @keyframes bounce-in { 
              0%{ 
                transeform: sceale(0);
              }
              50%{ 
                transeform: sceale(1.5);
              }
              100%{ 
                transeform: sceale(1);
              }
            }
          @keyframes bounce-out { 
              0%{ 
                transeform: sceale(1);
              }
              50%{ 
                transeform: sceale(1.5);
            }
            100%{ 
                transeform: sceale(0);
            }
          }

    自定义过渡名
        我们可以通过以下特性来自定义过渡名:
          enter-class
          enter-active-class
          leave-class
          leace-active-class
        他们的优先级别高于普通的类名,对于 Vue 的过渡系统和其他第三方 CSS 动画库,如 Animate.css 结合使用十分有用

          实例

          <div id="example-3">
              <button @click="show = !show">
                Toggle render
              </button>
              <transition
                  name="custom-classes-transititon"
                  enter-active-class="aniamated tada"
                  leave-active-class="animated bounceOutRight"
                >
                <p v-if="show">hello</p>
              </transition>
           </div>    
            new Vue({ 
                el:'#example-3',
                data: { 
                    show: true
                }
            })  

    同时使用Transitions 和Animations
      Vue 为了知道过渡的完成,必须设置相应的事件监听器

    JavaScript 钩子
      可以在属性中声明 JavaScript 钩子

        <transition
            v-on:before-enter="beforeEnter"
            v-on:enter="enter"
            v-on:after-enter="afterEnter"
            v-on:enter-cancelled="enterCancelled"

            v-on:before-leave="beforeLeave"
            v-on:leave="leave"
            v-on:after-leave="afterLeave"
            v-on:leave-cancelled="leaveCancelled"
        >
      </transition>    
       methods: { 
            // 进入中

          beforeEnter: function (el) { 
            //...
          },
          // 此回调函数是可选项的设置
          // 与 css 结合时使用
          enter: function (el, done) { 
              done()
            },
          afterEnter: function ( el) { 
            },
          enterCancelled: function (el) { 
          },

          // 离开时

        beforeLeave: function(el) { 
          //
      },
      // 此函数是可选项的设置
      // 与 css 结合时使用

      leave: function (el, done) { 
          //...
        done()
         },
      afterLeave: function (el) { 
        //...
      },
      // leaveCancelled 只用于v-show 中
      leaveCancelled: function(el) { 
      // ...
      }

    }

    这些钩子函数可以结合 CSS transitions/animations 使用,也可以单独使用。

   初始渲染的过度
      可以通过 appear 特性设置节点的在初始渲染的过度。

        <transition appear></transition>
          这里默认的和进入和离开过度一样,同样也可以自定义css类名
        <tranaition appear
          appear-class="custom-appear-class"
          appear-active-class="custom-appear-active-class"
        >

        </tranaition>

        自定义 JavaScript 钩子:

      <transition
          appear
            v-on:before-appear="customBeforAppearHook"
            v-on:appear="customAppearHook"
            v-on:after-appear="customAfterAppearHook"
        >

      </transition>

    多个元素的过度
      多个组件的过度很简单-我们不需要使用key 特性。我们只需要使用动态组件。

      <transition name="component-fade" mode="out-in">
        <component v-bind:is="view"></component>
      </transition>
      new Vue({ 
        el: '#transition-components-demo',
        data: { 
          view: 'v-a'
        },
        components: { 
          'v-a': { 
              template: '<div>Component A</div>'
          },
          'v-b': { 
              template: '<div>Component B</div>'
          }
          }
        })
      .component-fade-enter-active, .component-fade-leave-active { 
          transition: opacity .3s ease;
        }
      .component-fade-enter, .component-fade-leave-active { 
          opacity: 0;
      }

    列表过度
        目前为止,关于过度我们已经完成了:
         单个节点
         多个节点,其中每次只渲染一个
         有一个完整的列表 v-for 我们如何做到同时渲染,我们将使用
        <transition -group> 组件。
          不同于 <transition> 他会以一个真实元素渲染。默认为<span>也可以通过 tag 属性更换为其他渲染元素。
        他的元素必须具有为一个的key 属性

   列表的进入和离开
      进入和离开的过度使用之前一样的CSS 类名

     <div id="list-demo" class="demo">
          <button v-on:click="add">Add</button>
          <button v-on:click="remove">Remove</button>
          <transition-group name="list" tag="p">
          <span v-for="item in items" v-bind:key="item"
            class="list-item"
            >{{ item }}
          </span>
        </transition-group>
        </div>
      new Vue({ 
          el: '#list-demo',
          data: { 
              items: [1,2,3,4,5,6,7,8,9],
              nextNum: 10
          },
          methods: { 
            randomIndex: function() { 
            return Math.floor(Math.random() * this.items.length)
          },
          add: function () { 
          this.items.splice(this.radomIndex(), 0,this.nextNum++)
          },
          remove: function () { 
              this.items.splice(this.randomIndex(), 1)
          }
        }
      })
    .list-item { 
        display: inline-balock;
        margin-right:10px;
    }
    .list-enter-active, .list-leave-active { 
        transition: all ls;
    }
    .list-enter, .list-leave-active { 
        opacity: 0;
        transform: translateY(30px);
      }

    列表的位移过度
      <transition-group> 组件还有一个特殊之处,不仅可以进入和离开动画,还可以改变定位,
      要使用这个新功能 v-move 特性,它会在元素的改变定位的过程中应用。
      可以通过 name 属性来定义前缀,也可以通过move-class 属性手动设置。
      v-move 对于设置过度的过度的切换时机和过度曲线非常有用,

       <div id="flip-list-demo" class="demo">
            <button v-on:click="shuffle">Shuffle</button>
            <transition-group name="flip-list" tage="ul">
              <li v-for="item in items" v-bind:key="item">
                {{item}}
              </li>
            </transition-group>
        </div>
        new Vue({ 
            el: '#flip-list-demo',
            data: { 
                items: [1,2,3,4,5,6,7,8,9]
            },
            methods: { 
              shuffle: function () { 
                this.items = _.shuffle(this.items)
                }
              }
         })
        .flip-list-move { 
            transition: transform 1s;
        }

    列表的渐进过度
      通过data 属性 与 JavaScript 通信,可以实现列表的渐进过度

     <div id="staggered-list-demo">
          <input v-mode="query">
          <transition-group
            name="staggered-fade"
            tage="ul"
            v-bind:css= " false"
            v-on:before-enter="beforeEnter"
            v-on:enter = "enter"
            v-on:leave="l            >

              <li 
                v-for="{item, index} in computedList"
                v-bind:key = "item.msg"
                v-bind:data-index="index"
              >{{ item.msg}}</li>
        </transition-group>
      </div>
      new Vue({ 
          el: '#staggered-list-demo',
          data: { 
                query:' ',
                list: [ 
                    {msg: 'Bruce Lee'},
                    {msg: 'Jackie Chan'},
                    {msg: 'Chunck Norris'},
                    {msg: 'Jet Li'},
                    {msg: 'Kung Fury'}    ]
            },
          computed: { 
              computedList: function () { 
                  var vm = this
                  return this.list.filter(function (item) { 
                    return item.msg.toLowerCase().indexOf
                    (vm.query.toLowerCase()) !=== -1
                  })
                }
              },
            methods: { 
                beforeEnter: function (el) { 
                    el.style.opacity = 0
                    el.style.height = 0
                },
                enter: function (el,done) { 
                  var delay= el.dataset.index * 150
                    setTimeout(function () { 
                        Velocity( 
                            el,
                        {opacity: 1, height: '1.6em'},
                        {complete: done}
                    )
                  }, delay)
                },
                leave: function (el, done) { 
                    var delay = el.dataset.index * 150
                    setTimeout(function () { 
                        Velocity( 
                              el,
                          {opacity:0, height:0},
                          {complete: done}

                        )
                    },delay)
                   }
                  }
                })   

    可复用的过度
      过度可以通过 Vue 的组件系统实现复用,要创建一个可复用的过度组件,你需要做的就是
      将 <transition> 或者 <transition-group> 作为一个跟=根组件,放置在其中就可以了
      使用 template 的简单例子

        Vue.component('my-special-transition', { 
                  template:`\ 
                      <transition\
                        name="very-special-transition"\
                        mode= "out-in"\
                        v-on:before-enter="beforeEnter"\
                        v-on:after-enter="afterEnter"\
                        >\
                        <slot></slot>
                      </transition>\
                      \`,
                methods: { 
                    beforeEnter: function(el) { 
                        // ...
                    },
                    afterEnter: function (el) { 
                       // ...
                    }
                }
        })

      函数组件更适合完成这个任务:

    动态过渡
      在Vue 中及时是过度也是数据驱动的,动态过度基本是通过name 特性来绑定动态值
        <transition v-bind:name="transitionName"></transition>
        所有的过渡特性都是动态绑定。它不仅是简单的特性,通过事件的钩子函数方法,可以在获取到相应上下文数据

       <div id="dynmic-fade-">
            Fade In: <input type="range" v-model="fadeInDuration"
                   min="0" v-bind:max="maxFadeFuration">
            Fade Out: <input type="range" v-model="fadeOtDuration"
                min="0" v-bind:max="maxFadeFuration">
            <transition
                v-bind:css="false"
                v-on:before-enter="beforeEnter"
                v-on:enter="enter"
                v-on:leave="leave"
              >
              <p v-if="show">hello</p>
          </transition>
          <button v-on:click="stop = true">Stop it!</button>
        </div>
        new Vue({
            el: '#dynamic-fade-demo',
            data: {
                show: true,
                fadeInDuration: 1000,
                fadeOutDuration: 1000,
                maxFadeDuration: 1500,
                stop: false
            },
            mounted: function () {
                this.show = false
            },
            methods: {
              beforeEnter: function (el) {
                  el.style.opacity = 0
            },
          enter: function (el, done) {
                var vm = this
                  Velocity(el,
                      { opacity: 1 },
                      {
                          duration: this.fadeInDuration,
                          complete: function () {
                              done()
                              if (!vm.stop) vm.show = false
                          }
                      }
                    )
                },
              leave: function (el, done) {
                  var vm = this
                    Velocity(el,
                      { opacity: 0 },
                      {
                        duration: this.fadeOutDuration,
                        complete: function () {
                            done()
                            vm.show = true
                          }
                        }
                       )
                    }
                  }
              })
posted @ 2016-12-28 17:48  柠檬先生  阅读(7471)  评论(0编辑  收藏  举报