Vue基础

MVVM框架

在这里插入图片描述
在MVVM的架构下,View跟Model是不能直接通信的,它通常要通过ViewModel来做通信,ViewModel通常要实现一个观察者的身份。
当数据发生变化时,ViewModel能观察到数据的变化,然后通知到对应的视图做自动更新;而当用户操作视图,ViewModel也能监听到视图的变化,然后通知数据做改动。这就实现了数据的双向绑定。

MVVM框架的应用场景

针对具有复杂交互逻辑的前端应用
提供基础的架构抽象;通过Ajax做数据持久化,保证前端用户体验:当前端对数据做一些操作时,可以通过ajax请求对后端做数据持久化,不需要刷新整个页面,只需要改动DOM里你需要的那部分数据和内容。尤其是在移动端应用场景,刷新页面的代价太昂贵了,会重新加载很多资源,虽然有些资源会被缓存,但是页面的DOM、css、js都会被浏览器重新解析一遍,因此移动端页面通常会做成SPA单页应用,在这个基础上就诞生了很多MVVM框架:
在这里插入图片描述

什么是Vue.js

1、它是一个轻量级的MVVM框架,压缩后大小只有20K+
2、数据驱动+组件化前端开发(核心思想)

vue.js的核心思想

1、数据驱动:
在这里插入图片描述

如果没有MVVM框架,数据与视图是如何交互的?
1、页面通过ajax从后端获取数据,为了让视图改变,开发人员要手动触发DOM的改变;2、通过前端交互改变一些数据,为了让视图发生变化,仍然需要手动触发DOM的改变。
这个过程不仅繁琐而且易出错。

使用Vue.js就可以省去手动操作Dom的步骤了。

在vue.js里,只需要改变数据(Model),vue.js通过directives指令去修改对应的DOM,数据驱动DOM变化,DOM是数据的一种自然映射
vue.js还会对操作做一些监听,当我们修改视图(View)时,Vue.js监听到这些变化,从而改变数据。这样就实现了数据的双向绑定。

2、组件化
目的:扩展HTML元素,封装可重用的代码。
组件设计规则:
A.页面上每个独立的可视/可交互区域都可以视为一个组件,比如头部、尾部、还有一些可复用的区块,都可以抽象成一个组件
B.每个组件对应一个工程目录,组件所需要的各种资源在这个目录下就近维护。
C.页面不过是组件的容器,组件可以嵌套组合成完整的页面。

vue的脚手架工具[vue-cli]

脚手架的作用:帮助开发人员编写好基础代码。已经搞定目录结构、本地调试、代码部署、热加载、单元测试等工作。

全局安装:

npm install -g vue-cli

使用(创建项目)

vue init <template-name> <project-name>

for example:
vue init webpack myproject

<template-name>指代码模板,分为三类:官方模板(常用)、自定义模板、本地模板

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

VUE实例

我们可以创建一个.html文件,通过以下方式在<head></head>内引入vue:

<!-- 开发环境版本,包含了有帮助的命令行警告 -->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<!-- 生产环境版本,优化了尺寸和速度 -->
<script src="https://cdn.jsdelivr.net/npm/vue"></script>

1、声明式渲染

html

<div id="demo">
        {{ message }}
</div>

js

<script>
	var demo = new Vue({
    	el: '#demo',  // 绑定要素
    	data: {
        	message: 'Hello Vue!'
    	}
	})
</script>

页面呈现效果
在这里插入图片描述

现在数据和 DOM 已经被建立了关联,所有东西都是响应式的。
在浏览器打开控制台,并修改demo.message的值,页面上的数据会相应地更新。
在这里插入图片描述
我们不再和 HTML 直接交互了。一个 Vue 应用会将其挂载到一个 DOM 元素上 (对于这个例子是 #demo) 然后对其进行完全控制。

除此之外,我们还可以这样绑定元素属性:

html

<div id="demo2">
  <span v-bind:title="message">
    鼠标悬停几秒钟查看此处动态绑定的提示信息!
  </span>
</div>

js

var demo2 = new Vue({
  el: '#demo2',
  data: {
    message: '页面加载于 ' + new Date().toLocaleString()
  }
})

页面效果
在这里插入图片描述

当编写 HTML 源码时,你能在 HTML 元素里定义 attributes。然后,一旦浏览器解析你的代码,该 HTML 元素相应的 DOM节点就会被创建。该节点是一个对象,因此它就拥有 properties。
因此,我们知道:attributes 是 HTML元素(标签)的属性,而 properties 是 DOM 对象的属性。

v-bind指令:将这个元素节点的 title attributes 和 Vue 实例的 message property 保持一致

title属性:规定关于元素的额外信息,这些信息通常会在鼠标移动到元素上时显示一段工具提示文本。

2、条件(v-if)

html

<div id="demo3">
        <p v-if="seen">现在你看到我了</p>
</div>

js

var demo3 = new Vue({
     el: '#demo3',
     data: {
         seen: true
     }
})

效果
在这里插入图片描述

在控制台输入demo3.seen=false,会发现之前显示的消息就会消失

3、循环(v-for)

html

<div id="demo4">
  <ol>
    <li v-for="todo in todos">
      {{ todo }}
    </li>
  </ol>
</div>

js

var demo4 = new Vue({
    el: '#demo4',
    data: {
        todos: [
            '学习 JavaScript' ,
            '学习 Vue' ,
            '整个牛项目' 
        ]
    }
})

效果
在这里插入图片描述

<ol></ol>定义有序列表;<ul></ul>定义无序列表

!! 如果不用vue里面的v-for指令,而时用原生JS将数组的数据循环遍历到HTML中。代码是这样的:

html

<div id="todo"></div>

js

var arr = ['学习 JavaScript', '学习 Vue', '整个牛项目'];
//自定义字符串,用于拼接标签
var arrStr = "";
/****for循环****/
for (let i = 0; i < arr.length; i++) {
    arrStr += '<div>' + arr[i] + '</div>';
};
console.log(arrStr)
//拼接完字符串数组后用innerHTML把它渲染到页面中
document.getElementById("todo").innerHTML = arrStr;

效果:
在这里插入图片描述
这样做的话代码就变得多且复杂了。

还有一种将数组的数据循环遍历到HTML中的方法:利用ECMAScript语法中的forEach()方法。实现的效果跟上面是一样的。

js

	//自定义字符串,用于拼接标签
   var arrStr = "";
   //自定义数组
   var arr = ['学习 JavaScript', '学习 Vue', '整个牛项目'];
   /****forEach循环****/
   arr.forEach(e => {
       arrStr += `<div>${e}</div>`;
   })
   console.log(arrStr)
   //拼接完字符串数组后用innerHTML把它渲染到页面中
   document.getElementById("todo").innerHTML = arrStr;

但是不论是普通循环还是forEach()循环,都没有v-for用起来香!

4、处理用户输入(v-on)

1).v-on指令:事件监听器(用户与应用的交互)
html

<div id="demo5">
    <p>{{ message }}</p>
    <button v-on:click="reverseMessage">反转消息</button>
</div>

js

var demo5 = new Vue({
       el: '#demo5',
       data: {
           message: 'Hello Vue.js!'
       },
       methods: {
           reverseMessage: function () {
               this.message = this.message.split('').reverse().join('')
               // split('') 方法用于把一个字符串分割成字符串数组。
               // reverse() 方法用于颠倒数组中元素的顺序。
               // join('') 方法用于把数组中的所有元素以字符串的形式输出
           }
       }
})

效果
在这里插入图片描述

2). v-model 指令,它能轻松实现表单输入和应用状态之间的双向绑定。

html

<div id="demo6">
        <p>{{ message }}</p>
        <input v-model="message">
    </div>

js

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

效果
在这里插入图片描述

5、组件化应用构建

全局注册组件:

在components目录新增一个vue文件:test.vue
在这里插入图片描述
在main.js中注册组件

import test from './components/test'
Vue.component('test',test)

在其他任意组件用标签引用

<test></test>

局部注册

新建一个testtwo组件。
在这里插入图片描述

在需要引用组件的组件中导入组件并注册(eg:helloworld.vue)

import testtwo from './testtwo'
export default {
	component: {
		testtwo
	}
}

局部注册的组件只能在注册组件内使用。

计算属性

基础例子:字符串翻转

html

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

js

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

效果:
在这里插入图片描述
你可以打开浏览器的控制台,自行修改例子中的 vm。vm.reversedMessage 的值始终取决于 vm.message 的值。

1、计算属性缓存 vs 方法

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

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

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

用methods:

html

<div id="demo9">
    <p>Original name:'{{ name }}'</p>
    <p>methods reversed name: '{{ getName() }}'</p>
    <p>age: {{ getAge() }}</p>
    <p>job: {{ getJob() }}</p>
</div>

js

var demo9 = new Vue({
    el: '#demo9',
    data: {
        name: 'hellokty',
        age: 90,
        job: 'web'
    },
    methods: {
        getName() {
            console.log(this.name + '......')
            return this.name.split('').reverse().join('')
        },
        getAge() {
            console.log(this.age + '......')
            return this.age
        },
        getJob() {
            console.log(this.job + '.....')
            return this.job
        }
    }
})

在这里插入图片描述
当修改其中一个属性时,其他属性的值都没改变,但会发现methods里的方法都被执行.

用computed:

html

<div id="demo10">
    <p>Original name:'{{ name }}'</p>
    <p>methods reversed name: '{{ getName }}'</p>
    <p>age: {{ getAge }}</p>
    <p>job: {{ getJob }}</p>
</div>

js

var demo10 = new Vue({
    el: '#demo10',
    data: {
        name: 'tytty',
        age: 80,
        job: 'java'
    },
    computed: {
        getName() {
            console.log(this.name + '......')
            return this.name.split('').reverse().join('')
        },
        getAge() {
            console.log(this.age + '......')
            return this.age
        },
        getJob() {
            console.log(this.job + '.....')
            return this.job
        }
    }
})

在这里插入图片描述
会发现当修改其中一个值的时候,只会执行于其相关的方法。

3.总结:
1).methods方法和computed计算属性,两种方式的最终结果确实是完全相同
2).不同的是计算属性是基于它们的响应式依赖进行缓存的。只在相关响应式依赖发生改变时它们才会重新求值,多次访问 getAge 计算属性会立即返回之前的计算结果,而不必再次执行函数。
3).methods方法,每当触发重新渲染时,调用方法将总会再次执行函数。
4).所以,官网的一句话,对于任何复杂逻辑,你都应当使用计算属性。
5)可以说使用 computed 性能会更好,但是如果你不希望缓存,你可以使用 methods 属性。

2、计算属性的setter

计算属性默认只有 getter,不过在需要时你也可以提供一个 setter:
范例:
html

<div id="demo13">{{ fullName }}</div>

js

var demo13 = new Vue({
    el: '#demo13',
    data: {
        firstName: 'Foo',
        lastName: 'Bar'
    },
    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]
            }
        }
    }
})

在这里插入图片描述
从实例运行结果看在运行 demo13.fullName = ‘qwe ert’; 时,setter 会被调用, demo13.firstName 和 demo13.lastName 也会被对应更新。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值