从小白开始学vue学习笔记(一)——基础篇

目录

 

一、引入vue

二、helloWorld程序

三、声明式渲染

四、条件与循环

五、处理用户输入

六、组件化应用构建

与自定义元素的关系

SLOT API

定义

插槽算法

获取分布式节点算法

分布分辨率算法

slot 元件

扩展到 Element

七、Vue实例

1、创建一个Vue实例

2、数据与方法

3、实例生命周期钩子

4、生命周期图示

八、模板语法

1、插值

(1)文本

(2)原始html

(3)特性

(4)使用Js表达式

2、指令

(1)参数

(2)动态参数

(3)修饰符

3、缩写

v-bind缩写 :

v-on缩写 @

九、计算属性和侦听器

1、计算属性

(1)基础例子

(2)计算属性缓存vs方法

(2)计算属性setter

2、侦听器

vm.$watch(expOrFn, callback, [options])

十、Class 与 Style 绑定

1、绑定HTML Class

(1)对象语法

(2)数组语法

(3)用在组件上

2、绑定内联样式

(1)对象语法

(2)数组语法

(3)自动添加前缀

(4)多重值

十一、条件渲染

1、v-if

元素使用v-if条件渲染分组

 

 

 

 

 

 

一、引入vue

 1、开发环境版本,包含了有帮助的命令行警告:

 2、生产环境版本,优化了尺寸和速度:

请注意我们不推荐新手直接使用 vue-cli,尤其是在你还不熟悉基于 Node.js 的构建工具时。

 

二、helloWorld程序

index.html





    
    
    
    学习vue
    
    




    
{{message}}

index.js

var app = new Vue({
    el: '#app',
    data: {
        message: 'Hello, Vue!'
    }
});

 

三、声明式渲染

我们已经成功创建了第一个 Vue 应用!看起来这跟渲染一个字符串模板非常类似,但是 Vue 在背后做了大量工作。现在数据和 DOM 已经被建立了关联,所有东西都是响应式的。我们要怎么确认呢?打开你的浏览器的 JavaScript 控制台 (就在这个页面打开),并修改 app.message 的值,你将看到上例相应地更新。

从小白开始学vue学习笔记(一)——基础篇_第1张图片从小白开始学vue学习笔记(一)——基础篇_第2张图片

 

除了文本插值,我们还可以像这样来绑定元素特性:

鼠标悬停几秒钟查看此处动态绑定的提示信息!
var app2 = new Vue({
  el: '#app-2',
  data: {
    message: '页面加载于 ' + new Date().toLocaleString()
  }
})

·span的title属性就是悬停显示的提示信息

这里我们遇到了一点新东西。你看到的 v-bind 特性被称为指令。指令带有前缀 v-,以表示它们是 Vue 提供的特殊特性。可能你已经猜到了,它们会在渲染的 DOM 上应用特殊的响应式行为。在这里,该指令的意思是:“将这个元素节点的 title 特性和 Vue 实例的 message 属性保持一致”。

(1)完整语法:,解释:v-bind 是指令,: 后面的 class 是参数,classProperty 则在官方文档中被称为“预期值”。

(2)缩写语法:,解释:: 后面的 class 是参数,classProperty 则在官方文档中被称为“预期值”。

如果你再次打开浏览器的 JavaScript 控制台,输入 app2.message = '新消息',就会再一次看到这个绑定了 title 特性的 HTML 已经进行了更新。

从小白开始学vue学习笔记(一)——基础篇_第3张图片

 

四、条件与循环

控制切换一个元素是否显示也相当简单:

现在你看到我了

var app3 = new Vue({
  el: '#app-3',
  data: {
    seen: true
  }
})

从小白开始学vue学习笔记(一)——基础篇_第4张图片从小白开始学vue学习笔记(一)——基础篇_第5张图片

继续在控制台输入 app3.seen = false,你会发现之前显示的消息消失了。

*‘false’有引号的话是个字符串相当于true

这个例子演示了我们不仅可以把数据绑定到 DOM 文本或特性,还可以绑定到 DOM 结构。此外,Vue 也提供一个强大的过渡效果系统,可以在 Vue 插入/更新/移除元素时自动应用过渡效果。

还有其它很多指令,每个都有特殊的功能。例如,v-for 指令可以绑定数组的数据来渲染一个项目列表:

  1. {{ todo.text }}
var app4 = new Vue({
  el: '#app-4',
  data: {
    todos: [
      { text: '学习 JavaScript' },
      { text: '学习 Vue' },
      { text: '整个牛项目' }
    ]
  }
})

在控制台里,输入 app4.todos.push({ text: '新项目' }),你会发现列表最后添加了一个新项目。

 

五、处理用户输入

为了让用户和你的应用进行交互,我们可以用 v-on 指令添加一个事件监听器,通过它调用在 Vue 实例中定义的方法:

{{ message }}

var app5 = new Vue({
  el: '#app-5',
  data: {
    message: 'Hello Vue.js!'
  },
  methods: {
    reverseMessage: function () {
      this.message = this.message.split('').reverse().join('')
    }
  }
})

 

Vue 还提供了 v-model 指令,它能轻松实现表单输入和应用状态之间的双向绑定。

{{ message }}

var app6 = new Vue({
  el: '#app-6',
  data: {
    message: 'Hello Vue!'
  }
})

 

六、组件化应用构建

组件系统是 Vue 的另一个重要概念,因为它是一种抽象,允许我们使用小型、独立和通常可复用的组件构建大型应用。仔细想想,几乎任意类型的应用界面都可以抽象为一个组件树:

从小白开始学vue学习笔记(一)——基础篇_第6张图片

在 Vue 里,一个组件本质上是一个拥有预定义选项的一个 Vue 实例。在 Vue 中注册组件很简单:

// 定义名为 todo-item 的新组件
Vue.component('todo-item', {
  template: '
  • 这是个待办项
  • ' })

    现在你可以用它构建另一个组件模板:

    **************************实现出现错误****************************

        

        var example = new Vue({
            el: '.example',
            data: {}
        })
        Vue.component('todo-item', {
            template: '
  • 这是个待办项
  • ' })

    **************************错误原因****************************

    先构建组件!再创建vue实例!

    vue你可以理解为一个对象模板,使用vue就需要new进行实例化,当你已经实例化了,再去改变模板有何意义?自然出不来。

        Vue.component('todo-item', {
            template: '
  • 这是个待办项
  • ' }) var example = new Vue({ el: '.example', data: {} })

     

    但是这样会为每个待办项渲染同样的文本,这看起来并不炫酷。我们应该能从父作用域将数据传到子组件才对。让我们来修改一下组件的定义,使之能够接受一个 prop:

    Vue.component('todo-item', {
      // todo-item 组件现在接受一个
      // "prop",类似于一个自定义特性。
      // 这个 prop 名为 todo。
      props: ['todo'],
      template: '
  • {{ todo.text }}
  • ' })

    现在,我们可以使用 v-bind 指令将待办项传到循环输出的每个组件中:

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

    尽管这只是一个刻意设计的例子,但是我们已经设法将应用分割成了两个更小的单元。子单元通过 prop 接口与父单元进行了良好的解耦。我们现在可以进一步改进 组件,提供更为复杂的模板和逻辑,而不会影响到父单元。

    **************************个人实现*******************

        
        Vue.component('todo-item', {
            props: ['todo'],
            template: '
  • {{ todo.id }} {{ todo.text }}
  • ' }) var example = new Vue({ el: '.example', data: { groceryList: [ { id: 0, text: '素菜' }, { id: 1, text: '素2菜' }, { id: 2, text: '素23菜' } ] } })

     

    在一个大型应用中,有必要将整个应用程序划分为组件,以使开发更易管理。在后续教程中我们将详述组件,不过这里有一个 (假想的) 例子,以展示使用了组件的应用模板是什么样的:

     

    与自定义元素的关系

    你可能已经注意到 Vue 组件非常类似于自定义元素——它是 Web 组件规范的一部分,这是因为 Vue 的组件语法部分参考了该规范。例如 Vue 组件实现了 Slot API 与 is 特性。但是,还是有几个关键差别:

    1. Web Components 规范已经完成并通过,但未被所有浏览器原生实现。目前 Safari 10.1+、Chrome 54+ 和 Firefox 63+ 原生支持 Web Components。相比之下,Vue 组件不需要任何 polyfill,并且在所有支持的浏览器 (IE9 及更高版本) 之下表现一致。必要时,Vue 组件也可以包装于原生自定义元素之内。

    2. Vue 组件提供了纯自定义元素所不具备的一些重要功能,最突出的是跨组件数据流自定义事件通信以及构建工具集成

    虽然 Vue 内部没有使用自定义元素,不过在应用使用自定义元素、或以自定义元素形式发布时,依然有很好的互操作性。Vue CLI 也支持将 Vue 组件构建成为原生的自定义元素。

    SLOT API

    定义

    这些是新的定义。对于所有其他定义,请参阅当前规范。

    • slot - 阴影树中的已定义位置。由slot元素代表。

    • 插槽名称 -一个名称插槽

    • 默认插槽 -一个插槽用于无指定节点插槽名称

    插槽算法

    开槽算法分配一个影子树主机节点到插槽那棵树。

    输入 HOST - 影子树主机 输出HOST的 所有子节点都已插入

    1. TREE成为HOST的影子树

    2. DEFAULT成为一个空的节点列表

    3. 对于每个子节点NODEHOST,按照树形结构顺序:

    4. NAME成为NODE插槽名称

    5. 如果缺少NAME,请将NODE添加到DEFAULT

    6. SLOTTREE的插槽名称为 NAME的插槽

    7. 如果SLOT不存在,则丢弃节点

    8. 否则,将NODE分配给SLOT

    9. DEFAULT-SLOT是在默认插槽用于TREE

    10. 如果DEFAULT-SLOT不存在,请停止

    11. 否则,将DEFAULT中的所有节点分配给DEFAULT-SLOT

    将每个节点分配给插槽时,此插槽也会添加到节点的目标插入点列表中。

    获取分布式节点算法

    得到分布式节点算法递归收集当前分配到一个给定的所有节点插槽

    输入 SLOT - 阴影树中 的插槽输出 LIST - 分布式节点的列表

    1. 对于分配给SLOT的每个节点NODE

    2. 如果NODE是一个插槽:1。让SUB-LIST成为(递归)运行带有NODE作为参数的获取分布式节点算法的结果2.将SUB-LIST中的所有节点附加到LIST

    3. 否则,将NODE附加到LIST

    分布分辨率算法

    该算法从当前规范中取代分布分辨率算法

    输入 NODE-TREE - 节点树 输出 更新分发结果。

    1. 对于参与NODE-TREE的每个影子主机HOST,按树顺序:

    2. HOST为参数运行插槽算法

    3. SHADOW-TREE成为HOST的影子树

    4. 使用SHADOW-TREE作为输入运行* 分布式解析算法(递归)

    slot 元件

    slotelement表示阴影树中的一个插槽。具有与content元素相同的渲染行为。

    属性:

    • name - 插槽的名称。

    interface HTMLSlotElement:HTMLElement {
      属性DOMString名称;
      NodeList getDistributedNodes();
    }

    • name- 反映name属性。

    • getDistributedNodes---返回运行get distributed nodes算法的结果。

    扩展到 Element

    部分界面 元素 {
      属性DOMString槽;
    }

    • slot- 反映slot属性。该slot属性表示插槽名称

     

    七、Vue实例

    1、创建一个Vue实例

    每个 Vue 应用都是通过用 Vue 函数创建一个新的 Vue 实例开始的:

    var vm = new Vue({
      // 选项
    })

    虽然没有完全遵循 MVVM 模型,但是 Vue 的设计也受到了它的启发。因此在文档中经常会使用 vm (ViewModel 的缩写) 这个变量名表示 Vue 实例。

    当创建一个 Vue 实例时,你可以传入一个选项对象。这篇教程主要描述的就是如何使用这些选项来创建你想要的行为。作为参考,你也可以在 API 文档 中浏览完整的选项列表。

    一个 Vue 应用由一个通过 new Vue 创建的根 Vue 实例,以及可选的嵌套的、可复用的组件树组成。举个例子,一个 todo 应用的组件树可以是这样的:

    根实例
    └─ TodoList
       ├─ TodoItem
       │  ├─ DeleteTodoButton
       │  └─ EditTodoButton
       └─ TodoListFooter
          ├─ ClearTodosButton
          └─ TodoListStatistics

    我们会在稍后的组件系统章节具体展开。不过现在,你只需要明白所有的 Vue 组件都是 Vue 实例,并且接受相同的选项对象 (一些根实例特有的选项除外)。

     

    2、数据与方法

    当一个 Vue 实例被创建时,它将 data 对象中的所有的属性加入到 Vue 的响应式系统中。当这些属性的值发生改变时,视图将会产生“响应”,即匹配更新为新的值。

    // 我们的数据对象
    var data = { a: 1 }
    
    // 该对象被加入到一个 Vue 实例中
    var vm = new Vue({
      data: data
    })
    
    // 获得这个实例上的属性
    // 返回源数据中对应的字段
    vm.a == data.a // => true
    
    // 设置属性也会影响到原始数据
    vm.a = 2
    data.a // => 2
    
    // ……反之亦然
    data.a = 3
    vm.a // => 3

    当这些数据改变时,视图会进行重渲染。值得注意的是只有当实例被创建时 data 中存在的属性才是响应式的。也就是说如果你添加一个新的属性,比如:

    vm.b = 'hi'

    那么对 b 的改动将不会触发任何视图的更新。如果你知道你会在晚些时候需要一个属性,但是一开始它为空或不存在,那么你仅需要设置一些初始值。比如:

    data: {
      newTodoText: '',
      visitCount: 0,
      hideCompletedTodos: false,
      todos: [],
      error: null
    }

    这里唯一的例外是使用 Object.freeze(),这会阻止修改现有的属性,也意味着响应系统无法再追踪变化。

    var obj = {
      foo: 'bar'
    }
    
    Object.freeze(obj)
    
    new Vue({
      el: '#app',
      data: obj
    })

    {{ foo }}

    除了数据属性,Vue 实例还暴露了一些有用的实例属性与方法。它们都有前缀 $,以便与用户定义的属性区分开来。例如:

    var data = { a: 1 }
    var vm = new Vue({
      el: '#example',
      data: data
    })
    
    vm.$data === data // => true
    vm.$el === document.getElementById('example') // => true
    
    // $watch 是一个实例方法
    vm.$watch('a', function (newValue, oldValue) {
      // 这个回调将在 `vm.a` 改变后调用
    })

    以后你可以在 API 参考中查阅到完整的实例属性和方法的列表。

     

    3、实例生命周期钩子

    每个 Vue 实例在被创建时都要经过一系列的初始化过程——例如,需要设置数据监听、编译模板、将实例挂载到 DOM 并在数据变化时更新 DOM 等。同时在这个过程中也会运行一些叫做生命周期钩子的函数,这给了用户在不同阶段添加自己的代码的机会。

    比如 created 钩子可以用来在一个实例被创建之后执行代码:

    new Vue({
      data: {
        a: 1
      },
      created: function () {
        // `this` 指向 vm 实例
        console.log('a is: ' + this.a)
      }
    })
    // => "a is: 1"

    也有一些其它的钩子,在实例生命周期的不同阶段被调用,如 mountedupdateddestroyed。生命周期钩子的 this 上下文指向调用它的 Vue 实例。

    不要在选项属性回调上使用箭头函数,比如

    created: () => console.log(this.a)vm.$watch('a', newValue => this.myMethod())
    因为箭头函数并没有 thisthis 会作为变量一直向上级词法作用域查找,直至找到为止,经常导致

    Uncaught TypeError: Cannot read property of undefined

    Uncaught TypeError: this.myMethod is not a function

    之类的错误。

     

    4、生命周期图示

    下图展示了实例的生命周期。你不需要立马弄明白所有的东西,不过随着你的不断学习和使用,它的参考价值会越来越高。

    Vue 实例生命周期

     

    八、模板语法

    Vue.js 使用了基于 HTML 的模板语法,允许开发者声明式地将 DOM 绑定至底层 Vue 实例的数据。所有 Vue.js 的模板都是合法的 HTML ,所以能被遵循规范的浏览器和 HTML 解析器解析。

    在底层的实现上,Vue 将模板编译成虚拟 DOM 渲染函数。结合响应系统,Vue 能够智能地计算出最少需要重新渲染多少组件,并把 DOM 操作次数减到最少。

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

    1、插值

    (1)文本

    数据绑定最常见的形式就是使用“Mustache”语法 (双大括号) 的文本插值:

    Message: {{ msg }}

    Mustache 标签将会被替代为对应数据对象上 msg 属性的值。无论何时,绑定的数据对象上 msg属性发生了改变,插值处的内容都会更新。

    通过使用 v-once 指令,你也能执行一次性地插值,当数据改变时,插值处的内容不会更新。但请留心这会影响到该节点上的其它数据绑定:

    这个将不会改变: {{ msg }}

    (2)原始html

    双大括号会将数据解释为普通文本,而非 HTML 代码。为了输出真正的 HTML,你需要使用 v-html指令:

    Using mustaches: {{ rawHtml }}

    Using v-html directive:

    Using mustaches: This should be red.

    Using v-html directive: This should be red.

    这个 span 的内容将会被替换成为属性值 rawHtml,直接作为 HTML——会忽略解析属性值中的数据绑定。注意,你不能使用 v-html 来复合局部模板,因为 Vue 不是基于字符串的模板引擎。反之,对于用户界面 (UI),组件更适合作为可重用和可组合的基本单位。

    你的站点上动态渲染的任意 HTML 可能会非常危险,因为它很容易导致 XSS 攻击。请只对可信内容使用 HTML 插值,绝不要对用户提供的内容使用插值。

     

    (3)特性

    Mustache 语法不能作用在 HTML 特性上,遇到这种情况应该使用 v-bind 指令:

    对于布尔特性 (它们只要存在就意味着值为 true),v-bind 工作起来略有不同,在这个例子中:

    如果 isButtonDisabled 的值是 nullundefined 或 false,则 disabled 特性甚至不会被包含在渲染出来的