美文网首页
vue.js基础入门

vue.js基础入门

作者: 二熊不是熊二 | 来源:发表于2019-04-14 21:23 被阅读0次

该文章只是我对vue基础知识的一点总结,详细vue知识请看Vue官方文档

一、什么是vue.js

是一个轻量级MVVM框架,数据驱动+组件化的前端开发。

  • 数据驱动:数据响应原理——数据(model)改变驱动视图(view)自动更新。

  • 组件化:扩展html元素,封装可重用代码。

    组件设计原则

    • 页面上每个独立的可视/可交互区域视为一个组件

    • 每个组件对于一个工程目录,组件所需要的各种资源在这个目录下就近维护

    • 页面不过是组件的容器,组件可以嵌套自由组合形成完整的页面

二、MVVM

响应式,双向数据绑定,即MVVM。是指数据层(Model)-视图层(View)-数据视图(ViewModel)的响应式框架。它包括:

1.修改View层,Model对应数据发生变化。

2.Model数据变化,不需要查找DOM,直接更新View。

mvvm.png MVVM框架.png

在MVVM架构下,View 和 Model 之间并没有直接的联系,而是通过ViewModel进行交互,Model 和 ViewModel 之间的交互是双向的, 因此View 数据的变化会同步到Model中,而Model 数据的变化也会立即反应到View 上。

ViewModel 通过双向数据绑定把 View 层和 Model 层连接了起来,而View 和 Model 之间的同步工作完全是自动的,无需人为干涉,因此开发者只需关注业务逻辑,不需要手动操作DOM, 不需要关注数据状态的同步问题,复杂的数据状态维护完全由 MVVM 来统一管理。

三、vue基础

1、创建第一个vue实例
<!DOCTYPE html>
<html lang="en">
<head>
 <meta charset="UTF-8">
 <title>Vue入门</title>
 <script src="vue.js"></script>
</head>
<body>
 <div id="root"><h1>{{msg}}</h1></div>
​
 <script>
 new Vue({
 el:"#root",
 data:{
 msg:"hello world"
 }
 })
 </script>
</body>
</html>
运行结果:
  • 挂载点,模板,实例之间的关系

    • 一个 Vue 应用由一个通过 new Vue 创建的根 Vue 实例,以及可选的嵌套的、可复用的组件树组成。

    • <div id="root"></div>是vue实例的挂载点。vue只会去处理挂载点下面的内容。

    • 挂载点内部的内容即为模板内容,如示例中的{{msg}}。也可以将模板内容放在vue实例中(template):

     new Vue({
         el:"#root",
         template:'<h1>{{msg}}</h1>',
         data:{
         msg:"hello world"
         }
        })
2、vue的生命周期

下面部分参考详解vue生命周期,可详细阅读该文章

生命周期函数就是vue实例在某一个时间点会自动执行的函数。

PS:其中created和mounted比较重要,一个是data数据和事件的初始化,一个是html模板,挂载渲染到页面完毕。

生命周期图示:下图展示了实例的生命周期。

lifecycle.png
<!DOCTYPE html>
<html lang="en">
<head>
 <meta charset="UTF-8">
 <title>Vue实例生命周期函数</title>
 <script src="./vue.js"></script>
</head>
<body>
 <div id="app">
 <h1>{{message}}</h1>
 </div>
 <script>
 var vm = new Vue({
 el: '#app',
 data: {
 message: 'Vue的生命周期'
 },
 beforeCreate: function() {
 console.group('------beforeCreate创建前状态------');
 console.log("%c%s", "color:red" , "el     : " + this.$el); //undefined
 console.log("%c%s", "color:red","data   : " + this.$data); //undefined 
 console.log("%c%s", "color:red","message: " + this.message) 
 },
 created: function() {
 console.group('------created创建完毕状态------');
 console.log("%c%s", "color:red","el     : " + this.$el); //undefined
 console.log("%c%s", "color:red","data   : " + this.$data); //已被初始化 
 console.log("%c%s", "color:red","message: " + this.message); //已被初始化
 },
 beforeMount: function() {
 console.group('------beforeMount挂载前状态------');
 console.log("%c%s", "color:red","el     : " + (this.$el)); //已被初始化
 console.log(this.$el);
 console.log("%c%s", "color:red","data   : " + this.$data); //已被初始化
 console.log("%c%s", "color:red","message: " + this.message); //已被初始化
 },
 mounted: function() {
 console.group('------mounted 挂载结束状态------');
 console.log("%c%s", "color:red","el     : " + this.$el); //已被初始化
 console.log(this.$el);
 console.log("%c%s", "color:red","data   : " + this.$data); //已被初始化
 console.log("%c%s", "color:red","message: " + this.message); //已被初始化 
 },
 beforeUpdate: function () {
 console.group('beforeUpdate 更新前状态===============》');
 console.log("%c%s", "color:red","el     : " + this.$el);
 console.log(this.$el); 
 console.log("%c%s", "color:red","data   : " + this.$data); 
 console.log("%c%s", "color:red","message: " + this.message); 
 },
 updated: function () {
 console.group('updated 更新完成状态===============》');
 console.log("%c%s", "color:red","el     : " + this.$el);
 console.log(this.$el); 
 console.log("%c%s", "color:red","data   : " + this.$data); 
 console.log("%c%s", "color:red","message: " + this.message); 
 },
 beforeDestroy: function () {
 console.group('beforeDestroy 销毁前状态===============》');
 console.log("%c%s", "color:red","el     : " + this.$el);
 console.log(this.$el);
 console.log("%c%s", "color:red","data   : " + this.$data); 
 console.log("%c%s", "color:red","message: " + this.message); 
 },
 destroyed: function () {
 console.group('destroyed 销毁完成状态===============》');
 console.log("%c%s", "color:red","el     : " + this.$el);
 console.log(this.$el);
 console.log("%c%s", "color:red","data   : " + this.$data); 
 console.log("%c%s", "color:red","message: " + this.message)
 }
 })
 </script>
 </body>
</html>

控制台:

初始化实例: 更新实例: 销毁实例:
3、模板语法
  • 插值

区别:v-text会转译,v-html不会转译

<div id="app">
 <!-- 插值表达式 -->
 <div>{{name}}</div>          <!--  <h1>hello</h1> -->
 <!-- v-text 与 {{}} 作用相同 -->
 <div v-text="name"></div>    <!--  <h1>hello</h1> -->
 <div v-html="name"></div>    <!--  hello -->
 </div>

对于所有的数据绑定,Vue.js 都提供了完全的 JavaScript 表达式支持。注意:每个绑定都只能包含单个表达式

{{ number + 1 }}
{{ ok ? 'YES' : 'NO' }}
{{ message.split('').reverse().join('') }}
<div v-bind:id="'list-' + id"></div>
​
<!-- 这是语句,不是表达式 -->
{{ var a = 1 }}
<!-- 流控制也不会生效,请使用三元表达式 -->
{{ if (ok) { return message } }}
  • 指令

  • 事件绑定:v-on

<body>
         <div id="root">
         <!--  事件绑定 v-on: 简写为 @ -->
         <div v-on:click="handleClick"><h1>{{content}}</h1></div>
         </div>
        ​
         <script>
         new Vue({
         el:"#root",
         data:{
         content:"hello"
         },
         methods:{
         handleClick:function(){
         this.content = "world"
         }
         }
         })
         </script>
        </body>
  • 属性绑定:v-bind
<body>
         <div id="root">
         <!-- 属性绑定 v-bind: 简写为 : -->
         <div :title="title">hello world</div>
         </div> 
        ​
         <script>
         new Vue({
         el:"#root",
         data:{
         title:"this is hello world"
         }
         })
         </script>
        </body>
  • 双向数据绑定:v-model
<body>
         <div id="root">
         <!-- 双向数据绑定 v-model -->
         <input v-model="content"/>
         <div>{{content}}</div>
         </div> 
        ​
         <script>
         new Vue({
         el:"#root",
         data:{
         content:"this is content"
         }
         })
         </script>
        </body>
  • v-if,v-else指令
       <body>
         <div id="root">
         <!-- v-if 条件渲染指令,存在与否,它根据表达式的真假来删除和插入元素
         当show=false时,直接从dom中移除 -->
         <div v-if="show">hello world</div>
         <!-- v-if的值为false时显示v-else内容,v-if 与 v-else必须紧贴
         另外 还有 v-else-if  -->
         <div v-else>bye world</div>
         <button @click="handleClick">toggle</button>
         </div>
        ​
         <script>
         new Vue({
         el: "#root",
         data: {
         show: true
         },
         methods:{
         handleClick:function(){
         this.show = !this.show
         }
         }
         })
         </script>
        </body>
  • v-show指令
<body>
         <div id="root">
         <!-- v-show 条件渲染指令,显示与否
         当show=false时,div中的display属性变为none,不会dom中移除。
         推荐使用v-show -->
         <div v-show="show">hello world</div>
         <button @click="handleClick">toggle</button>
         </div>
        ​
         <script>
         new Vue({
         el: "#root",
         data: {
         show: true
         },
         methods:{
         handleClick:function(){
         this.show = !this.show
         }
         }
         })
         </script>
        </body>
  • v-for指令
<body>
         <div id="root">
         <ul>
         <!-- v-for 循环显示  :key 提升每一项渲染效率,不能相同
         一般与后端数据库相连时该项为数据id -->
         <li v-for="(item,index) of list" :key="index">{{item}}</li>
         </ul>
         </div>
        ​
         <script>
         new Vue({
         el: "#root",
         data: {
         list: [1,2,3]
         }
         })
         </script>
        </body>
  • 缩写
  • v-bind
<!-- 完整语法 -->
<a v-bind:href="url">...</a>

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

<!-- 缩写 -->
<a @click="doSomething">...</a>
4、计算属性、方法与监听器
  • 计算属性

    对于任何复杂逻辑,你都应当使用计算属性。

<body>
     <div id="example">
     <p>Original message: "{{ message }}"</p>
     <p>Computed reversed message: "{{ reversedMessage }}"</p>
     </div>

     <script>
     var vm = new Vue({
     el: '#example',
     data: {
     message: 'Hello'
     },
     computed: {
     // 计算属性的 getter
     reversedMessage: function () {
     // `this` 指向 vm 实例
     return this.message.split('').reverse().join('')
     }
     }
     })
     </script>
    </body>

结果:

Original message: "Hello"

Computed reversed message: "olleH"

  • 计算属性缓存 vs 方法

    我们可以通过在表达式中调用方法来达到同样的效果:

        // 在组件中
        methods: {
         reversedMessage: function () {
         return this.message.split('').reverse().join('')
         }
        }

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

这也同样意味着下面的计算属性将不再更新,因为 Date.now() 不是响应式依赖:

       computed: {
             now: function () {
               return Date.now()
           }
        }

相比之下,每当触发重新渲染时,调用方法将总会再次执行函数。

  • 计算属性vs侦听属性
      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
            }
          }
        })
  • 计算属性的setter

    计算属性默认只有 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]
            }
          }
        }
        // ...

现在再运行 vm.fullName = 'John Doe' 时,setter 会被调用,vm.firstNamevm.lastName 也会相应地被更新。

  • 监听器

    虽然计算属性在大多数情况下更合适,但有时也需要一个自定义的侦听器。

    当需要在数据变化时执行异步或开销较大的操作时,这个方式是最有用的。

<body> 
    <div id="root">
        姓:<input v-model="firstName" />
        名:<input v-model="lastName" />
        <div>{{fullName}}</div>
        <div>{{count}}</div>
    </div>

    <script>
        new Vue({
            el:"#root",
            data:{
                firstName: '',
                lastName: '',
                count: 0
            },
            // 计算属性,内置缓存,其中内置属性没改变就不会再次计算
            computed:{
                fullName: function() {
                    return this.firstName + ' ' + this.lastName
                }
            },
            // 侦听器,监听变化次数
            watch: {
                fullName: function() {
                    this.count++
                }
            }
        })
    </script>
</body>
5、class与style绑定

下面通过一个点击改变颜色例子来说明样式绑定。

  • class的对象绑定
 <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>class的对象绑定</title>
        <script src="./vue.js"></script>
        <style>
            .activited {
                color: red;
            }
        </style>
    </head>
    <body>
        <div id="app">
            <!-- 方法一:class的对象绑定 -->
            <div @click="handleDivClick"
                 :class="{activited:isActivited}">
                 Hello world
            </div>
        </div>

        <script>
            var vm = new Vue ({
                el: "#app",
                data: {
                    isActivited: false
                },
                methods: {
                    handleDivClick: function() {
                        this.isActivited = ! this.isActivited
                    }
                }
            })
        </script>
    </body>
    </html>
  • class的数组绑定
<!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>class的数组绑定</title>
        <script src="./vue.js"></script>
        <style>
            .activited {
                color: red;
            }
        </style>
    </head>
    <body>
        <div id="app">
            <!-- 方法二:class的数组绑定 -->
            <div @click="handleDivClick1"
                 :class="[activited]">
                 Hello world!
            </div>
        </div>

        <script>
            var vm = new Vue ({
                el: "#app",
                data: {
                    activited:""
                },
                methods: {
                    handleDivClick1: function() {
                        this.activited = this.activited === "activited" ? "" : "activited"
                    }
                }
            })
        </script>
    </body>
    </html>
  • style的对象绑定
 <body>
        <div id="app">
            <!-- 方法三:style的对象绑定 -->
            <div @click="handleDivClick2"
                 :style="styleObj">
                 Hello world!!
            </div>
        </div>

        <script>
            var vm = new Vue ({
                el: "#app",
                data: {
                    styleObj: {
                        color: ""
                    }
                },
                methods: {
                    handleDivClick2: function() {
                        this.styleObj.color = this.styleObj.color === "" ? "red" : "";
                    }
                }
            })
        </script>
    </body>
  • style的数组绑定
<body>
        <div id="app">
        <!-- 方法四:style的数组绑定(与方法三相似) -->
            <div @click="handleDivClick3"
                 :style=[styleObj]>
                 Hello world!!!
            </div>
        </div>

        <script>
            var vm = new Vue ({
                el: "#app",
                data: {
                    styleObj: {
                        color: ""
                    }
                },
                methods: {
                    handleDivClick3: function() {
                        this.styleObj.color = this.styleObj.color === "" ? "red" : "";
                    }
                }
            })
        </script>
    </body>
6、条件渲染

v-ifv-elsev-show基础知识详见上文指令部分。

  • 在<template>元素上使用v-if条件渲染分组

    当我们需要切换多个元素时,可以把一个 <template> 元素当做不可见的包裹元素,并在上面使用 v-if

    最终的渲染结果将不包含 <template> 元素。

<template v-if="ok">
      <h1>Title</h1>
      <p>Paragraph 1</p>
      <p>Paragraph 2</p>
    </template>
  • v-else-if

    充当 v-if 的“else-if 块”,可以连续使用:

   <div v-if="type === 'A'">
      A
    </div>
    <div v-else-if="type === 'B'">
      B
    </div>
    <div v-else-if="type === 'C'">
      C
    </div>
    <div v-else>
      Not A/B/C
    </div>

类似于 v-elsev-else-if 也必须紧跟在带 v-if 或者 v-else-if 的元素之后。

  • key管理可复用的元素

    Vue 会尽可能高效地渲染元素,通常会复用已有元素而不是从头开始渲染。

    但有时我们并不需要这样的功能,如当我们在使用账号登录时,可以选择用户名登录和邮箱登录,而这两者的信息可能是不一样的,这时我们可以增加key使切换时输入的内容清空。如下面的例子:

<body>
    <!-- 通过增加key能使v-if 与 v-else 切换时的内容清空 -->
        <div id="app">
            <div v-if="show">
                用户名:<input key="username" />
            </div>
            <div v-else>
                邮箱名:<input key="email"/>
            </div>
            <button @click="toggle">切换</button>
        </div>

        <script>
            var vm = new Vue({
                el: "#app",
                data: {
                    show: true,
                },
                methods: {
                    toggle: function() {
                        this.show = !this.show
                    }
                }
            })
        </script>
    </body>
7、列表渲染
  • v-for把一个数组对应为一组元素
<body>
    <div id="app">
    <!-- v-for 循环显示  :key 提升每一项渲染效率,不能相同 一般与后端数据库相连时该项为数据id -->
    <!-- 可以用 of 替代 in 作为分隔符,因为它是最接近 JavaScript 迭代器的语法 -->
        <div v-for="(item, index) in list"
             :key="item.id">
            {{index}}----{{item.text}}----{{item.id}}
        </div>
    </div>

    <script>
        var vm = new Vue({
            el: "#app",
            data: {
                list: [{
                    id:"010120201",
                    text:"hello"
                },{
                    id:"010120202",
                    text:"hello"
                },{
                    id:"010120203",
                    text:"hello"
                }]
            }
        })
    </script>
</body>
输出结果:
  • 一个对象的v-for
<body>
    <div id="app">
        <div v-for="(value, key, index) in object">
          {{ index }}. {{ key }}: {{ value }}
        </div>
    </div>

    <script>
        var vm = new Vue({
            el: "#app",
            data: {
                object: {
                    firstName: 'John',
                    lastName: 'Doe',
                    age: 30
                }
            }
        })
    </script>
</body>
输出结果:

当我们要在此基础上再加一个数据,在控制台中我们要重新定义该对象才能使页面改变。

vm.object={
                firstName: 'John',
                lastName: 'Doe',
                age: 30,
                address: 'hangzhou'
            }

除此之外,我们还可以通过set方法向对象注入数据,同时页面更新。

方法一:Vue.set(vm.object,"address","hangzhou")

方法二:vm.$set(vm.object,"address","hangzhou")

结果:
  • 变异方法

    Vue 包含一组观察数组的变异方法,所以它们也将会触发视图更新。这些方法如下:

    • push()

    • pop()

    • shift()

    • unshift()

    • splice()

    • sort()

    • reverse()

  • 非变异方法

    filter(), concat()slice() 。这些不会改变原始数组,但总是返回一个新数组

    当使用非变异方法时,可以用新数组替换旧数组:

    example1.items = example1.items.filter(function (item) {
      return item.message.match(/Foo/)
    })
  • 注意事项

    由于 JavaScript 的限制,Vue 不能检测以下变动的数组:

    1.当你利用索引直接设置一个项时,例如:vm.items[indexOfItem] = newValue

    2.当你修改数组的长度时,例如:vm.items.length = newLength

  • 为了解决第一类问题,以下两种方式都可以实现和 vm.items[indexOfItem] = newValue 相同的效果,同时也将触发状态更新:

        // Vue.set
        Vue.set(vm.items, indexOfItem, newValue)
        // Array.prototype.splice
        vm.items.splice(indexOfItem, 1, newValue)

你也可以使用 vm.$set 实例方法,该方法是全局方法 Vue.set 的一个别名:

vm.$set(vm.items, indexOfItem, newValue)

  • 为了解决第二类问题,你可以使用 splice:

vm.items.splice(newLength)

相关文章

  • Vue.js基础入门

    今天,给大家分享下Vue.js基础入门,我主要由了解Vue.js、开始起步、语法三个部分简单的写了基础入门知识,希...

  • Vue.js基础入门

    今天,给大家分享下Vue.js基础入门,我主要由了解Vue.js、开始起步、语法三个部分简单的写了基础入门知识,希...

  • 渐进式框架 Vue.js 基础入门及简单编程演示

    渐进式框架 Vue.js 基础入门及简单编程演示 ---------------------- 概念基础 ----...

  • VUE基础知识入门

    VUE基础知识入门 VUE官方文档教程链接:VUE 1.什么是Vue.js Vue.js(读音 /vjuː/, 类...

  • Vue基础知识总结

    请阅读以下博客,通俗易懂 Vue基础知识总结 Vue.js——60分钟快速入门 Vue.js——60分钟组件快速入...

  • Vue.js开发常见问题解析

    此前的Vue.js系列文章: Vue.js常用开发知识简要入门(一) Vue.js常用开发知识简要入门(二) Vu...

  • Vue.js 入门基础

    书写动机 前端工程师是一个机会与辛劳并存的职位,说它 “机会” 可能是由于各家大厂开出的工资,说它 “辛劳” 是因...

  • vue.js基础入门

    该文章只是我对vue基础知识的一点总结,详细vue知识请看Vue官方文档。 一、什么是vue.js 是一个轻量级M...

  • Vue.js状态管理工具Vuex快速上手

    Vue2简单入门 Vue.js再入门 Vue.js使用vue-router构建单页应用 Vue.js状态管理工具V...

  • Vue2简单入门

    Vue2简单入门 Vue.js再入门 Vue.js使用vue-router构建单页应用 Vue.js状态管理工具V...

网友评论

      本文标题:vue.js基础入门

      本文链接:https://www.haomeiwen.com/subject/patewqtx.html