View on GitHub

blog

博客;温故而知新

Vue2.x 总结

Vue 是一套用于构建用户界面的渐进式框架

也意味着,既可以把VUE作为该应用的一部分嵌入到一个现成的服务端应用,或者在前后端分离的应用中,利用Vue 的核心库及其生态系统,把更多的逻辑放在前端来实现。

A Progressive Framework

渐进式框架

与Vue相比,React学习曲线陡峭,在学习React之前,需要了解JSX和ES2015,当然入门后,发现还要学习React全家桶。而Vue就可以在简单阅读了文档后,开始构建应用程序。

这就要得益于Vue主张的 渐进式。 可以简单看下官方给出这张图: a progressive framework

可以看出来,主要是介绍了Vue设计思想,就是框架做分层设计,每层都可选,可以单独引入,为不同的业务需求制定灵活的方案。主张最少,不会多做职责以外的事。

Vue作者尤雨溪的观点,Vue设计上包括的解决方案很多,但是使用者完全不需要一上手,就把所有东西全都用上,因为完全没有必要,一般都是根据项目的复杂度,在核心的基础上任意选用其他的部件,不一定要全部整合在一起。

这样渐进式的解决方案,使学习成本大大减少了。

声明式渲染

也就是说,DOM状态只是数据状态的一个映射,基本所有的框架都已经认同了这个看法,Vue也是主张 数据驱动状态

说到这里,基本都会提到现在主流的MVVM的模式。 mvvm

采用了双向数据绑定的思想,基本可以分为三层:

基于这个思想,Vue从一开始就利用ViewModel与view,model进行交互 Vue mvvm ViewModel是Vue.js的核心,它是一个Vue实例,作用在某个HTML元素上,一般都是指定 id= app的元素,图中 的DOM listenersData Bindings可以看做两个工具,它们是实现双向数据绑定的关键。

从用户(View)角度看,DOM Liisteners利用在相应的元素上添加事件绑定,捕获用户的点击,滑动等手势动作,在事件流中改变对应的Model。比如 常用的 v-model 指令,就是捕获表单元素的inputchange等事件,改变相应的绑定值。

从Model方向看,Data Bindings则将操作的数据变化,反应到view上。比如通过ajax 从后台获取的数据,可以刷新数据列表,反应到用户界面。这也是实现双向数据绑定的关键。

Vue2中是通过Object.definedProperty方法中定义的getters和 setters构造器来实现数据响应的。可以简化下源码中的实现:

      Object.defineProperty(obj, key, {
            enumerable: true,
            configurable: true,
            get: function reactiveGetter () {
               return value
            },
            set: function reactiveSetter (newVal) {
                var value = getter ? getter.call(obj) : val;
                /* eslint-disable no-self-compare */
                if (newVal === value || (newVal !== newVal && value !== value)) {
                  return
                }
                /* eslint-enable no-self-compare */
                if ("development" !== 'production' && customSetter) {
                  customSetter();
                }
                if (setter) {
                  setter.call(obj, newVal);
                } else {
                  val = newVal;
                }
                childOb = !shallow && observe(newVal);
                dep.notify();
              }
          });
      }

通过这种方法定义对象obj上的某个属性,每次获取属性值的时候就,会主动触发get对应的回调函数,然后给该属性赋值时,就会触发里面的set对应的回调函数,在set回调函数里面,加入了dep.notify()方法,然后可以看下这个方法

notify () {
 // stabilize the subscriber list first
 const subs = this.subs.slice()
 for (let i = 0, l = subs.length; i < l; i++) {
   subs[i].update()
 }
}

里面的定义的常量subs每次深拷贝this.subs数组,数组里面保存的就是所有的subscriber订阅者,对应的发布者就是obj里面对应的属性,或者说是Vue中的data值。通知所有的订阅者,数据更新了。原生js实现发布订阅模式(publish/Subscribe),可以参考这里

常用基础语法

hello world

   <!DOCTYPE html>
   <html>
     <head>
       <meta charset="utf-8">
       <title>hello world</title>
       <script src="https://gw.alipayobjects.com/as/g/h5-lib/vue/2.4.4/vue.min.js"></script>
     </head>
     <body>
       <div id="app">
         
       </div>
       <script>
         var app = new Vue({
           el:"#app",
           data:{
             message:'hello vue'
           }
         })
       </script>
     </body>
   </html>

这样就简单创建了一个Vue 应用,数据message 和DOM页面产生了关联,类似html模板引擎,把相应的数据渲染到页面中。

指令

指令 (Directives) 是带有 v- 前缀的特殊属性,这些特殊属性可以响应式的作用域DOM,

style or class

v-bind用于classstyle时,Vue.js做了专门的增强,表达式结果的类型除了字符串之外,还可以是对象或数组。

绑定HTML Class

绑定内联样式

条件渲染

列表渲染

v-model 表单绑定

使用v-model在表单input<textarea>元素上创建双向数据绑定。

    <input v-model = "message" placeholer= "edit me">
    <p>Message is </p>

这样input输入框中的值就与P标签中的内容绑定了,同样也适用textareacheckbox, radio,select等表单。

实质上,v-model只是语法糖。

     <input v-model = "something"

对应的完整形式:

      <input
         v-bind:value="something"
         v-on:input="something = $event.target.value">

表单数组校验。 利用修饰符 .number进行数字校验,是最实用的方法,在v-model上添加number修饰符。

    <input v-model.number="age" type= "number" >

组件通信

组件可以用来扩展HTML,封装可重用的代码,所有的组件都是Vue的实例。

命名: 建议遵循W3C规则(小写,并且包含一个短杆)

组件组合:使用中最常见的是形成父子组件的关系,组件A在它的模板中使用了组件B,那么他们之间就需要通信。组件间通信的关系可以用下面的图示表明: props-events

概括为: prop 向下传递,事件向上传递。

状态管理

组件通信变得复杂时,就要考虑使用全局状态管理,Vue也提供了vuex状态管理库。

Vuex 是一个专门为Vue.js应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。

当然,使用Vuex并不是首选,只有在构建中大型单页面应用时,考虑到全局的状态管理,自然就会想到Vuex。 下面这张图,表示状态管理“单向数据流”的理念 vuex

核心概念包括(简单计数器为例):


   getters:{
      getState:state=>{
        return state.count
      }
   },

  mutations:{
    increment:state => state.count++,
    decrement:state => state.count--
  },

  // 模拟异步请求
  var delay = (timeout,cb) => new Promise(resolve => setTimeout(()=>{cb(); resolve("test incrementAsync")},timeout));

  actions:{
    incrementAsync({commit}) {
        return delay(600,function(){commit("increment")})

    },
  }

把所有部分组合起来,就构成一个简单的计数器:

  var delay = (timeout,cb) => new Promise(resolve => setTimeout(()=>{cb(); resolve("test incrementAsync")},timeout));
  var store = new Vuex.Store({
    state:{
      count:0
    },
    getters:{
       getState:state=>{
         return state.count
       }
    },
    mutations:{
      increment:state => state.count++,
      decrement:state => state.count--
    },
    actions:{
      incrementAsync({commit}) {
          return delay(600,function(){commit("increment")})
      },
      decrementAsync({commit}) {
          return delay(600,function(){commit('decrement')});
      }
    }
  })

然后组件中触发actions,就可以

store.dispatch('decrementAsync').then(() => {
// ...
})

在浏览器中,使用vue-devtool,试下时间旅行功能。 vue-devtool

页面路由

使用Vue.js创建单页面应用,就可以使用vue-router,目前版本是3.0.1,把组件映射到对应的路由,通过改变url来渲染不同的页面。官方中文文档

vue-router 默认hash模式,每次url只会改变#后面对应的值,页面就不会重新加载,并且也不需要服务器端作任何配置。

如果使用路由的history模式,url就会正常http://yoursite.com/user/id,只需要添加配置mode:'history',同时需要后端配置,不然页面重新刷新,会匹配不到任何资源。

不同模式下的服务器配置及生产环境部署,可以参考vue、react等单页面项目应该这样部署到服务器.

基础概念:

Vue-cli入门

Vue 提供一个官方命令行工具,可用于快速搭建大型单页面应用

目前已经发布到了V3.0.0-alpha.5

  npm install -g @vue/cli
  vue create my-project

基本用法,文档里面也比较清楚,参考这里, 通过下面几步,快速搭建项目基础结构。

    # 全局安装 vue-cli
    $ npm install --global vue-cli
    # 创建一个基于 webpack 模板的新项目
    $ vue init webpack my-project
    # 安装依赖,走你
    $ cd my-project
    $ npm install/ yarn
    $ npm run dev

(如果没有使用任何框架的基础上,也想快速搭建一个大型项目的目录结构,可以考虑yeoman快速生成一个新的项目)

基础配置:

参考链接