Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Vue.js实战经验小结 #1

Open
luoway opened this issue Feb 15, 2017 · 0 comments
Open

Vue.js实战经验小结 #1

luoway opened this issue Feb 15, 2017 · 0 comments
Labels

Comments

@luoway
Copy link
Owner

luoway commented Feb 15, 2017

Vue.js介绍

Vue.js(读音 /vjuː/, 类似于 view) 是一套构建用户界面的 渐进式框架。与其他重量级框架不同的是,Vue 采用自底向上增量开发的设计。Vue 的核心库只关注视图层,并且非常容易学习,非常容易与其它库或已有项目整合。另一方面,Vue 完全有能力驱动采用单文件组件和 Vue 生态系统支持的库开发的复杂单页应用。

Vue.js 的目标是通过尽可能简单的 API 实现响应的数据绑定组合的视图组件

技术选型——为什么要使用Vue.js?

  • 需求:实现一个通过选择、输入等方式创建项目,以及对项目进行管理、查看、编辑等操作的应用。应用中多处需要数据双向绑定
  • 体验:单页应用(Single page application, SPA)用户体验好、快,接近原生应用的体验
  • 效率:提供常用逻辑的封装实现,编程效率高
  • 扩展:允许异步加载组件,并允许直接操作DOM(React需通过refs访问到特定DOM)
  • 轻量:轻量级框架不带有侵略性API,对容器也没有依赖性,易于进行配置,易于通用,启动时间较短。允许我们同时使用习惯的jQuery.js/Zepto.js

项目构建——Vue单文件组件刮来的清新风

  • 目录结构:

    {
        "src":{
            "app":{
                "index":["index.html", "index.js", "index.less"]
            },
            "common":[]//js,image等
            "components":{
                "common":["cover.vue", "loading.vue", "toast.vue"],//通用组件
                "home":["index.vue", "tab.vue", "list.vue"],//页面组件
                  //...
                  //单文件组件同HTML文件一样,支持文件内写HTML、CSS、JS
                  //但首页入口需要是常规的html、js
            }
        }
    }
  • 组件化:

    • 组件与模块的关系

      来源:Jasin Yip的回答@知乎

    • 组件化的粒度:本项目以文件夹划分页面,以UI层级及重用关系划分组件

  • 小结

    vue单文件组件将一个组件的结构、样式、逻辑集中在单个类HTML文件里,这样的内容集中降低了工程项目的碎片化,在编程过程中也可以避免写一个组件需要在html、css、js不同文件之间进行频繁切换。

代码结构——Vue的使用概览

  • 使用入门

    1. 创建根实例

      index.html

      <div id="app"></div>

      index.js

      var app = new Vue().$mount('#app');
    2. 创建单文件组件

      demo.vue

      <template>
      	<div>{{greeting}} world!</div>
      </template>
      <style>
      
      </style>
      <script>
      	module.exports = {
          	data: function(){
                	return {
                    	greeting: 'Hello'
                	}
          	}
      	}
      </script>
    3. 挂载组件

      index.js

      var demo = require('demo.vue')//Webpack用require,ES6用import
      var app = new Vue({
        	components: {
              demo: demo
          }
      }).$mount('#app');

      index.html

      <div id="app">
      	<demo></demo>
      </div>
    4. 运行结果

      <div id="app">
      	<div>Hello world!</div>
      </div>
  • 实践中遇到的难点

    • 数据双向绑定及监听变化:

      • 数据双向绑定

        双向数据绑定指的就是,绑定对象属性的改变到用户界面的变化的能力,反之亦然

        双向:数据->视图、视图->数据

        绑定:一个内容发生改变,另一个内容随之改变

        demo.vue:一个典型的数据双向绑定示例

        <template>
        	<input type="text" v-bind:value="msg" v-on:input="changeMsg($event)"/>
          	<div>{{msg}}</div>
        </template>
        <script>
        	module.exports = {
                data: function(){
                  	'msg':'hello'
                },
              	methods: {
                	changeMsg: function(e){
                      	this.msg = e.target.value
                	}
              	}
        	}
        </script>

        Vue提供了v-model指令,对上面的代码简写如下

        demo.vuev-model指令示例

        <template>
        	<input type="text" v-model="msg"/>
          	<div>{{msg}}</div>
        </template>
        <script>
        	module.exports = {
                data: function(){
                  	'msg':'hello'
                },
        	}
        </script>

        目前为止,要在数据变化后执行逻辑,可以扩展changeMsg内容,或监听inputchange事件。Vue提供了computed、watch两种方式来监听变化

      • computed

        demo.vuecomputed示例

        <template>
        	<input type="text" v-model="msg"/>
          	<div>{{msg}}</div>
          	<div>{{rs}}</div>
        </template>
        <script>
        	module.exports = {
              	 data:function () {
                     return {
                         msg: 'hello',
                     }
                 },
            	 computed: {
                      rs: function () {
                          console.log(this.msg)
                          return this.msg.split('').reverse().join('')
                      }
                  }
        	}
        </script>
      • watch

        demo.vuewatch示例

        <template>
        	<input type="text" v-model="msg"/>
          	<div>{{msg}}</div>
          	<div>{{rs}}</div>
        </template>
        <script>
        	module.exports = {
              	 data:function () {
                     return {
                         msg: 'hello',
                         rs: 'olleh'
                     }
                 },
            	 watch: {
                     msg: function (val) {
                         console.log(val)
                         this.rs = val.split('').reverse().join('')
                     }
                 },
        	}
        </script>
      • computed与watch的异同

        1. 相同

          受现代 Javascript 的限制(以及废弃 Object.observe),Vue 不能检测到对象属性的添加或删除

          它们都只能观察到Vue实例对象(Vue实例中,this指向的对象)上存在的属性变化

        2. 不同

          • computed会自动给Vue实例对象上添加属性、覆盖已有属性,watch不会

          • computed中的方法只在被访问时执行,而不是在监听属性变化发生时立即执行

            watch中的方法,在监听属性变化发生时立即执行

            遇到 computed 监听无效,而 watch 有效,原因往往出在这里

          • computed只关心计算结果,不限制多少个属性发生了变化,可以监听多个属性变化的结果

            计算属性的结果会被缓存,除非依赖的响应式属性变化才会重新计算。

            watch只关心某个属性变化,发生变化则执行相应逻辑

    • 单向数据流

      • Vue只封装了从父组件到子组件的通信方式:prop

        props中包含父组件传入的属性、方法,这些内容会被添加到Vue组件的实例对象上

      • Vue建议的从子组件到父组件的通信方式:自定义事件

        父组件提供一个自定义事件,用于接收子组件的信息,执行相应的函数

      • Vue补充的任意组件之间的通信方式:全局自定义事件(非父子组件通信

        1. 设置一个新的Vue实例:

          var bus = new Vue()
        2. *建议将其挂在window上以供工程中全局使用window.Bus = bus

        3. 在组件A中监听自定义事件

          A.vue

          <script>
          	module.exports = {
                	 created: function(){
                     	bus.$on('event-A', function (something) {
                        // ...
                      })
                	 }
          	}
          </script>
        4. 在组件B中触发自定义事件

          B.vue

          <script>
          	module.exports = {
                	 created: function(){
                     	bus.$emit('event-A', 'say something')
                	 }
          	}
          </script>
    • 生命周期

      • 基本图示

      • 加入keep-alive后的生命周期

        <template>
        	<div id="parent">
              	<keep-alive>
                  	<component v-bind:is="nowChild"></component>
              	</keep-alive>
          	</div>
        </template>
        <script>
          	var child1 = require('child1.vue')
          	var child2 = require('child2.vue')
        	module.exports = {
              	data: function(){
                  	return {
                      	nowChild: 'child1'
                  	}
              	},
              	components:{
                  	child1: child1,
                  	child2: child2
              	}
        	}
        </script>

        keep-alive的子组件的基本生命周期同keep-alive的父组件相似,但keep-alive的子组件间切换,会触发activateddeactivated,而不会二次触发子组件的基本生命周期

体验优化——单页应用的用户体验

  • 原则一:避免外链跳转

    单页应用在单页内有一致的、流畅的用户体验。而单页与外链间的跳转,则会产生大量的计算、渲染,反而暴露出单页应用不“轻量”的缺点。因此,避免外链跳转,降低单页内存在的外链被点击的可能,有助于减少用户对明显体验差异的感知,一定程度上提高用户体验。

    存在需要直接打开外链的情况,优化措施可以是在新窗口中打开。

  • 原则二:优化首屏

    上述“单页应用不 ‘轻量’ ”的问题,在首屏表现尤其明显。进入一个单页,往往是长时间的等待,情况类似于打开一个APP,先看到的一般是首屏图片、动画、引导、广告。

    这里的优化也需要从技术、视图两方面入手。技术上采用服务端渲染、异步加载组件等方案,视图上则需要做到首屏尽快从一片空白变成有点东西。

  • 原则三:使用缓存

    单页应用可以充分实践MV*的理念,视图的更新反映了数据的更新。时间花销主要在于DOM渲染、逻辑运算、等待请求返回中,这些数据均可以被缓存以留到下次使用。

    使用缓存是单页应用体验趋近原生应用的主要因素。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

1 participant