魏名华

不要偷懒,做更好的自己

Nothing


No Welcome Message

Vue学习

Vue在国内的应用还是挺多的,也许比React多,公司的项目,小程序,很多的Vue的使用。

React还是Vue:你该如何选择?

学习计划:

  1. 先学官方文档,从基础开始,初步感受,有了vue这些框架,前端开发本身应该很简单啊
  2. 学习demo,包含官方的demo,其他开源的demo,公司的项目,了解Vue的应用
  3. 看一看Vue技术内幕
  4. 将Vue应用到小程序的开发
  5. 前端技术,感觉不是1-2个月可以学好的,先花时间学一学,后续再慢慢补充,如果没机会实战,那也许只能是了解熟悉,而不能掌握,这也是没办法的事情,任何一项技术都是如此

FAQ

dist: 全称是distribution

打包后,chunk-vendors.js文件超大,几百k

Babel 入门教程: Babel是一个广泛使用的转码器,可以将ES6代码转为ES5代码,从而在现有环境执行。

Flow 是 facebook 出品的 JavaScript 静态类型检查工具。Vue.js 的源码利用了 Flow 做了静态类型检查,所以了解 Flow 有助于我们阅读源码。认识 Flow

Flow是工具,TypeScript是语言。 Flow - JS静态类型检查工具

ESLint TSLint: 代码检查工具,就像OCLint一样,对代码进行自动review,与flow是不同的东西,flow是编译时做静态类型检查,而lint是做代码规范,代码结构等简单,比如判断代码是否有太多层的if

css pre-processor

浅谈css预处理器,Sass、Less和Stylus

test

展望 2018 年 JavaScript Testing

vue-cli 创建项目功能配置

功能(在项目创建后,仍然可以通过安装插件来增加功能)

babel: Babel是一个广泛使用的转码器,可以将ES6代码转为ES5代码,从而在现有环境执行 TypeScript: 支持使用 TypeScript 书写源码 Progressive Web App (PWA) Support: PWA 支持 Router: 支持 vue-router Vuex: 支持 vuex CSS Pre-processors: 支持 CSS 预处理器 Linter / Formatter: 支持代码风格检查和格式化 Unit Testing: 支持单元测试 E2E Testing: 支持 E2E 测试 使用配置文件: 将插件的配置保存在各自的配置文件中

vue-router

vue-router两种模式:hash 模式、history 模式

Progressive Web App (PWA) Support

就是可以将web应用添加到主屏幕的技术

基础

Vue实例

  1. 真双向绑定,UI输入直接改变model
<div id="app-6">
  <p></p>
  <input v-model="message">
</div>
var app6 = new Vue({
  el: '#app-6',
  data: {
    message: 'Hello Vue!'
  }
})
  1. 组件化应用构建

demo如下

<div id="app-7">
  <ol>
    <!--
      现在我们为每个 todo-item 提供 todo 对象
      todo 对象是变量,即其内容可以是动态的。
      我们也需要为每个组件提供一个“key”,稍后再
      作详细解释。
    -->
    <todo-item
      v-for="item in groceryList"
      v-bind:todo="item"
      v-bind:key="item.id">
    </todo-item>
  </ol>
</div>
Vue.component('todo-item', {
  props: ['todo'],
  template: '<li></li>'
})

var app7 = new Vue({
  el: '#app-7',
  data: {
    groceryList: [
      { id: 0, text: '蔬菜' },
      { id: 1, text: '奶酪' },
      { id: 2, text: '随便其它什么人吃的东西' }
    ]
  }
})

有几个注意点:

  1. 组件todo-item直接在 html 中当标签使用
  2. bind的意思是:将标签的 todo 属性,与 Vue 实例的 item 属性保持一致,这里的 item,是遍历 Vue 实例的 groceryList 得到的
  3. 在一个大型应用中,有必要将整个应用程序划分为组件,以使开发更易管理。在后续教程中我们将详述组件,不过这里有一个 (假想的) 例子,以展示使用了组件的应用模板是什么样的(都是组件化,更简洁直观语义化,避免一堆html标签):
<div id="app">
  <app-nav></app-nav>
  <app-view>
    <app-sidebar></app-sidebar>
    <app-content></app-content>
  </app-view>
</div>
  1. 与自定义元素的关系:原来原生Web 组件规范已经有自定义原素了,是html更简洁直观语义化,避免一堆html标签,具体不清楚,先不管了,Vue的组件说它比原生强大

Vue实例

  1. Vue 实例暴露的属性和方法,需要前缀$
var data = { a: 1 }
var vm = new Vue({
  el: '#example',
  data: data
})

// 获得这个实例上的属性
// 返回源数据中对应的字段
vm.a == data.a // => true

// 设置属性也会影响到原始数据
vm.a = 2
data.a // => 2

// ……反之亦然
data.a = 3
vm.a // => 3

vm.$data === data // => true
vm.$el === document.getElementById('example') // => true

// $watch 是一个实例方法
vm.$watch('a', function (newValue, oldValue) {
  // 这个回调将在 `vm.a` 改变后调用
})
  1. 实例生命周期

模板语法

  1. Vue.js 使用了基于 HTML 的模板语法,允许开发者声明式地将 DOM 绑定至底层 Vue 实例的数据。HTML 的模板语法,什么意思?

  2. 如果你熟悉虚拟 DOM 并且偏爱 JavaScript 的原始力量,你也可以不用模板,直接写渲染 (render) 函数,使用可选的 JSX 语法。难道React用的不是 HTML 的模板语法?

  3. “Mustache”语法 (双大括号)
    <span>Message: </span>
    
  4. 双大括号会将数据解释为普通文本,而非 HTML 代码。为了输出真正的 HTML,你需要使用 v-html 指令: ```html

Using mustaches:

Using v-html directive:


5. Mustache 语法不能作用在 HTML 特性上,遇到这种情况应该使用 v-bind 指令:
```html
<div v-bind:id="dynamicId"></div>
  1. 指令 (Directives) 是带有 v- 前缀的特殊特性。一些指令能够接收一个“参数”,在指令名称之后以冒号表示。例如,v-bind 指令可以用于响应式地更新 HTML 特性:
    <a v-bind:href="url">...</a>
    <a v-on:click="doSomething">...</a>
    
  2. 指令修饰符 (Modifiers) 是以半角句号 . 指明的特殊后缀,用于指出一个指令应该以特殊方式绑定。例如,.prevent 修饰符告诉 v-on 指令对于触发的事件调用 event.preventDefault(): ```html
...

8. 在构建由 Vue.js 管理所有模板的单页面应用程序 (SPA - single page application) 时,v- 前缀也变得没那么重要了。因此,Vue.js 为 v-bind 和 v-on 这两个最常用的指令,提供了特定简写:(SPA的概念不是特别清楚)

```html
<!-- 完整语法 -->
<a v-bind:href="url">...</a>
<!-- 缩写 -->
<a :href="url">...</a>

<!-- 完整语法 -->
<a v-on:click="doSomething">...</a>
<!-- 缩写 -->
<a @click="doSomething">...</a>

计算属性和侦听器

  1. demo
<div id="example">
  <p>Original message: ""</p>
  <p>Computed reversed message: ""</p>
</div>
var vm = new Vue({
  el: '#example',
  data: {
    message: 'Hello'
  },
  computed: {
    // 计算属性的 getter
    reversedMessage: function () {
      // `this` 指向 vm 实例
      return this.message.split('').reverse().join('')
    }
  }
})
  1. 计算属性和方法:计算属性有缓存,方法没有

  2. 侦听属性

<div id="demo"></div>
var vm = new Vue({
  el: '#demo',
  data: {
    firstName: 'Foo',
    lastName: 'Bar',
    fullName: 'Foo Bar'
  },
  watch: {
    firstName: function (val) {
      this.fullName = val + ' ' + this.lastName
    },
    lastName: function (val) {
      this.fullName = this.firstName + ' ' + val
    }
  }
})

// 上面代码是命令式且重复的。将它与计算属性的版本进行比较:

var vm = new Vue({
  el: '#demo',
  data: {
    firstName: 'Foo',
    lastName: 'Bar'
  },
  computed: {
    fullName: function () {
      return this.firstName + ' ' + this.lastName
    }
  }
})
  1. 计算属性默认只有 getter ,不过在需要时你也可以提供一个 setter :
// ...
computed: {
  fullName: {
    // getter
    get: function () {
      return this.firstName + ' ' + this.lastName
    },
    // setter
    set: function (newValue) {
      var names = newValue.split(' ')
      this.firstName = names[0]
      this.lastName = names[names.length - 1]
    }
  }
}
// ...
  1. 侦听器:一个很好的demo,对于初步了解vue的实战
<div id="watch-example">
  <p>
    Ask a yes/no question:
    <input v-model="question">
  </p>
  <p></p>
</div>
<!-- 因为 AJAX 库和通用工具的生态已经相当丰富Vue 核心代码没有重复 -->
<!-- 提供这些功能以保持精简这也可以让你自由选择自己更熟悉的工具 -->
<script src="https://cdn.jsdelivr.net/npm/axios@0.12.0/dist/axios.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/lodash@4.13.1/lodash.min.js"></script>
<script>
var watchExampleVM = new Vue({
  el: '#watch-example',
  data: {
    question: '',
    answer: 'I cannot give you an answer until you ask a question!'
  },
  watch: {
    // 如果 `question` 发生改变,这个函数就会运行
    question: function (newQuestion, oldQuestion) {
      this.answer = 'Waiting for you to stop typing...'
      this.debouncedGetAnswer()
    }
  },
  created: function () {
    // `_.debounce` 是一个通过 Lodash 限制操作频率的函数。
    // 在这个例子中,我们希望限制访问 yesno.wtf/api 的频率
    // AJAX 请求直到用户输入完毕才会发出。想要了解更多关于
    // `_.debounce` 函数 (及其近亲 `_.throttle`) 的知识,
    // 请参考:https://lodash.com/docs#debounce
    this.debouncedGetAnswer = _.debounce(this.getAnswer, 500)
  },
  methods: {
    getAnswer: function () {
      if (this.question.indexOf('?') === -1) {
        this.answer = 'Questions usually contain a question mark. ;-)'
        return
      }
      this.answer = 'Thinking...'
      var vm = this
      axios.get('https://yesno.wtf/api')
        .then(function (response) {
          vm.answer = _.capitalize(response.data.answer)
        })
        .catch(function (error) {
          vm.answer = 'Error! Could not reach the API. ' + error
        })
    }
  }
})
</script>

Class与Style绑定

  1. 操作元素的 class 列表和内联样式,demo:

当有如下模板:

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

和如下 data:

data: {
  isActive: true,
  hasError: false
}

结果渲染为:

<div class="static active"></div>

ps: class即为样式,(css选择器)[http://www.w3school.com.cn/cssref/css_selectors.ASP]

  1. 内联样式
<div v-bind:style="{ color: activeColor, fontSize: fontSize + 'px' }"></div>
data: {
  activeColor: 'red',
  fontSize: 30
}

条件渲染

就是一些 if else 之类的

列表渲染

就是for的使用

事件处理

  1. 可以用 v-on 指令监听 DOM 事件,并在触发时运行一些 JavaScript 代码。

示例:

<div id="example-1">
  <button v-on:click="counter += 1">Add 1</button>
  <p>The button above has been clicked  times.</p>
</div>
var example1 = new Vue({
  el: '#example-1',
  data: {
    counter: 0
  }
})
  1. 为什么在 HTML 中监听事件? 你可能注意到这种事件监听的方式违背了关注点分离 (separation of concern) 这个长期以来的优良传统。什么是关注点分离?

表单输入绑定

表单相关

组件基础

组件相关

深入了解组件

vue.js官方的example

todomvc

  1. vue 怎么会设计过滤器这种难以理解的东西

  2. 从数组删除元素用的是splice

firebase

  1. 搞清楚函数定义,类定义,对象定义。混乱的JavaScript语法,我靠
// vue实例内的computed的validation,并不是函数,而是对象{name: false, email: false}
computed: {
    validation: function () {
      return {
        name: !!this.newUser.name.trim(),
        email: emailRE.test(this.newUser.email)
      }
    },
    isValid: function () {
      var validation = this.validation
      return Object.keys(validation).every(function (key) {
        return validation[key]
      })
    }
  }

  validation(): Uncaught TypeError: validation is not a function

var person = {
  name : ['Bob', 'Smith'],
  age : 32,
  gender : 'male',
  interests : ['music', 'skiing'],
  bio : function() {
    alert(this.name[0] + ' ' + this.name[1] + ' is ' + this.age + ' years old. He likes ' + this.interests[0] + ' and ' + this.interests[1] + '.');
  },
  greeting: function() {
    alert('Hi! I\'m ' + this.name[0] + '.');
  },
  validation: function () {
    return {
      name: false,
      email: true
    }
  }
};

// person.validation(): {name: false, email: true}

grid

  1. 计算属性 filteredData 的值始终取决于 filterKey 等 props 的值,即 props filterKey值的变化,会触发计算属性 filteredData 的更新,从而更新到 Dom。

  2. 我们可以将同一函数定义为一个方法而不是一个计算属性。两种方式的最终结果确实是完全相同的。然而,不同的是计算属性是基于它们的依赖进行缓存的。只在相关依赖发生改变时它们才会重新求值。这就意味着只要 props 还没有发生改变,多次访问 filteredData 计算属性会立即返回之前的计算结果,而不必再次执行函数。

  3. 当异步时,应该使用watch(参考官方文档: https://cn.vuejs.org/v2/guide/computed.html)

  4. data 的变化,也会触发计算属性 filteredData 的值的变化,从而更新到 Dom。

markdown

  1. methods 里面的 update 方法,有入参 e: InputEvent,e.target.value 是 textarea 的值

  2. _.debounce 是 lodash 的防抖工具函数

  1. 组件定义的2种示例:(总共3种,还有1种在move-animations里面)
// 定义一个名为 button-counter 的新组件
Vue.component('button-counter', {
  data: function () {
    return {
      count: 0
    }
  },
  template: '<button v-on:click="count++">You clicked me 8 times.</button>'
})
<!-- template for the modal component -->
    <script type="text/x-template" id="modal-template">
      <transition name="modal">
        <div class="modal-mask">
          <div class="modal-wrapper">
            <div class="modal-container">

              <div class="modal-header">
                <slot name="header">
                  default header
                </slot>
              </div>

              <div class="modal-body">
                <slot name="body">
                  default body
                </slot>
              </div>

              <div class="modal-footer">
                <slot name="footer">
                  default footer
                  <button class="modal-default-button" @click="$emit('close')">
                    OK
                  </button>
                </slot>
              </div>
            </div>
          </div>
        </div>
      </transition>
    </script>

    <!-- app -->
    <div id="app">
      <button id="show-modal" @click="showModal = true">Show Modal</button>
      <!-- use the modal component, pass in the prop -->
      <modal v-if="showModal" @close="showModal = false">
        <!--
          you can use custom content here to overwrite
          default content
        -->
        <h3 slot="header">custom header</h3>
      </modal>
    </div>

    <script>
      // register modal component
      Vue.component('modal', {
        template: '#modal-template'
      })

      // start app
      new Vue({
        el: '#app',
        data: {
          showModal: false
        }
      })
    </script>
  1. 事件的处理:

modal 组件内的 button 的 click 事件:@click=”$emit(‘close’)” -> modal 组件的 click 事件:@close=”showModal = false” -> 修改 vue 实例 app 的 data,或调用 vue 实例 app 的方法

  1. demo中有1个 transition tag, Vue 提供了 transition 的封装组件,在下列情形中,可以给任何元素和组件添加进入/离开过渡

move-animations

  1. vue 实例里面,components 定义了一个 item 组件

  2. lodash shuffle函数, 创建一个被打乱元素的集合

select2

  1. vue 实例里面,直接使用 template 属性,使用 html 的 demo-template 模板

  2. 这个demo有点复杂,没看懂

其他demo

awesome-vue: 太多东西了,各种资源,教程,开源项目,等等

vue-typescript-dpapp-demo

https://github.com/SimonZhangITer/vue-typescript-dpapp-demo

  1. template 竟然可以这样写
<template lang="pug">
  .main-wrapper
    v-header
    .content-wrapper
      modules
      div(v-if="load")
        headline
        board
        super_sale
        shop_list
      .loading(v-else)
</template>

vue-loader 支持使用非默认语言,比如 CSS 预处理器,预编译的 HTML 模版语言,通过设置语言块的 lang 属性。例如,你可以像下面这样使用 Sass 语法编写样式:

<style lang="sass">
  /* write Sass! */
</style>

更多细节可以在预处理器中找到。

模版的处理方式略有不同,因为大多数 webpack 模版处理器 (比如 pug-loader) 会返回模版处理函数,而不是编译的 HTML 字符串,我们使用原始的 pug 替代 pug-loader:

npm install pug –save-dev

<template lang="pug">
div
  h1 Hello world!
</template>
  1. 通过https://github.com/WingGao/mpvue-ts-demo 这个demo,尝试将项目转为小程序,发现太多问题,解决不了,因为很多东西不了解,比如typescript,vuex等等。还是要先打基础,需要更多的时间投入学习

vuejsexamples

https://vuejsexamples.com

Mall-Vue

https://github.com/PowerDos/Mall-Vue

这是一个基于VUE + VUEX + iView做的一个电商网站前端项目, 附带前后端分离实现版本(在forMallServer分支),很强大,要学一下

项目预览地址(demo): https://powerdos.github.io/Mall-Vue/index.html