Vue.js学习笔记

目录

Vue 的核心库只关注视图层,方便与第三方库或既有项目整合。

HTML + CSS + JS : 视图 : 给用户看,刷新后台给的数据

网络通信 : axios

页面跳转 : vue-router

状态管理:vuex

Vue-UI : ICE , Element UI

  1. VUE 概述

    Vue (读音/vju/, 类似于view)是一套用于构建用户界面的渐进式框架,发布于2014年2月。与其它大型框架不同的是,Vue被设计为可以自底向上逐层应用。Vue的核心库只关注视图层,不仅易于上手,还便于与第三方库(如: vue-router: 跳转,vue-resource: 通信,vuex:管理)或既有项目整合
  2. 前端三要素

    HTML (结构) :超文本标记语言(Hyper Text Markup Language) ,决定网页的结构和内容

    CSS (表现) :层叠样式表(Cascading Style sheets) ,设定网页的表现样式

    JavaScript (行为) :是一种弱类型脚本语言,其源代码不需经过编译,而是由浏览器解释运行,用于控制网页的行为
  3. JavaScript框架

    jQuery: 大家熟知的JavaScript框架,优点是简化了DOM操作,缺点是DOM操作太频繁,影响前端性能;在前端眼里使用它仅仅是为了兼容IE6、7、8;

Angular: Google收购的前端框架,由一群Java程序员开发,其特点是将后台的MVC模式搬到了前端并增加了模块化开发的理念,与微软合作,采用TypeScript语法开发;对后台程序员友好,对前端程序员不太友好;最大的缺点是版本迭代不合理(如: 1代-> 2代,除了名字,基本就是两个东西;截止发表博客时已推出了Angular6)

React: Facebook出品,一款高性能的JS前端框架;特点是提出了新概念[虚拟DOM]用于减少真实DOM操作,在内存中模拟DOM操作,有效的提升了前端渲染效率;缺点是使用复杂,因为需要额外学习一门[JSX] 语言;

Vue:一款渐进式JavaScript框架,所谓渐进式就是逐步实现新特性的意思,如实现模块化开发、路由、状态管理等新特性。其特点是综合了Angular (模块化)和React (虚拟DOM)的优点;

Axios :前端通信框架;因为Vue 的边界很明确,就是为了处理DOM,所以并不具备通信能力,此时就需要额外使用一个通信框架与服务器交互;当然也可以直接选择使用jQuery提供的AJAX通信功能;

前端三大框架:Angular、React、Vue

ES6语法

1.不一样的变量声明:const和let

ES6推荐使用let声明局部变量,相比之前的var(无论声明在何处,都会被视为声明在函数的最顶部)

let和var声明的区别:

var x = '全局变量';
{
let x = '局部变量';
console.log(x); // 局部变量
}
console.log(x); // 全局变量
<body>
<button>按钮1</button>
<button>按钮2</button>
<button>按钮3</button>
<button>按钮4</button>
<button>按钮5</button>
<script>
// 变量作用域:变量在什么位置内是可用的
// ES5之前因为if和for都没有块级作用域的概念,所以在很多时候,我们都必须借助于function的作月域来解决应用外面变量的问题
// 闭包可以解决这个问题: 函数是一个作用域
// ES6中加入了let,let它是有if和for块级作用域 // ES5语法
// var btns = document.getElementsByTagName('button');
// for(var i = 0; i<btns.length; i++){
// (function(num){
// bnts[num].addEventListener('click',function(){
// console.log('第'+num+'个按钮被点击');
// })
// })(i)
// } // ES6语法
const btns = document.getElementsByTagName('button')
for (let i = 1; i < btns.length; i++) {
btns[i].addEventListener('click', function () {
console.log('第' + i + '个按钮被点击');
})
}
</script>
</body>

let表示声明变量,而const表示声明常量,两者都为块级作用域;

const 声明的变量都会被认为是常量,意思就是它的值被设置完成后就不能再修改了,且const定义标识符时,必须赋值:

建议:在ES6开发中,优先使用const,只有需要改变某一个标识符的时候才使用let。

const a = 1
a = 0 //报错

如果const的是一个对象,对象所包含的值(内部属性)是可以被修改的。抽象一点儿说,就是对象所指向的地址没有变就行:

const student = { name: 'cc' }

student.name = 'yy';// 不报错
student = { name: 'yy' };// 报错

有几个点需要注意:

  • let 关键词声明的变量不具备变量提升(hoisting)特性
  • let 和 const 声明只在最靠近的一个块中(花括号内)有效
  • 当使用常量 const 声明时,请使用大写变量,如:CAPITAL_CASING
  • const 在声明时必须被赋值

2.模板字符串

在ES6之前,我们往往这么处理模板字符串:

通过“\”和“+”来构建模板

$("body").html("This demonstrates the output of HTML \
content to the page, including student's\
" + name + ", " + seatNumber + ", " + sex + " and so on.");

而对ES6来说

  1. 基本的字符串格式化。将表达式嵌入字符串中进行拼接。用${}来界定;
  2. ES6反引号(``)直接搞定;
$("body").html(`This demonstrates the output of HTML content to the page,
including student's ${name}, ${seatNumber}, ${sex} and so on.`);

3.箭头函数(Arrow Functions)

ES6 中,箭头函数就是函数的一种简写形式,使用括号包裹参数,跟随一个 =>,紧接着是函数体;

箭头函数最直观的三个特点。

  • 不需要 function 关键字来创建函数
  • 省略 return 关键字
  • 继承当前上下文的 this 关键字
// ES5
var add = function (a, b) {
return a + b;
};
// 使用箭头函数
var add = (a, b) => a + b; // ES5
[1,2,3].map((function(x){
return x + 1;
}).bind(this)); // 使用箭头函数
[1,2,3].map(x => x + 1);

细节:当你的函数有且仅有一个参数的时候,是可以省略掉括号的。当你函数返回有且仅有一个表达式的时候可以省略{} 和 return;

4. 函数的参数默认值

在ES6之前,我们往往这样定义参数的默认值:

// ES6之前,当未传入参数时,text = 'default';
function printText(text) {
text = text || 'default';
console.log(text);
} // ES6;
function printText(text = 'default') {
console.log(text);
} printText('hello'); // hello
printText();// default

5.Spread / Rest 操作符

Spread / Rest 操作符指的是 ...,具体是 Spread 还是 Rest 需要看上下文语境。

当被用于迭代器中时,它是一个 Spread 操作符:

function foo(x,y,z) {
console.log(x,y,z);
} let arr = [1,2,3];
foo(...arr); // 1 2 3

当被用于函数传参时,是一个 Rest 操作符:当被用于函数传参时,是一个 Rest 操作符:

function foo(...args) {
console.log(args);
}
foo( 1, 2, 3, 4, 5); // [1, 2, 3, 4, 5]

6.二进制和八进制字面量

ES6 支持二进制和八进制的字面量,通过在数字前面添加 0o 或者0O 即可将其转换为八进制值:

let oValue = 0o10;
console.log(oValue); // 8 let bValue = 0b10; // 二进制使用 `0b` 或者 `0B`
console.log(bValue); // 2

7.对象和数组解构

// 对象
const student = {
name: 'Sam',
age: 22,
sex: '男'
}
// 数组
// const student = ['Sam', 22, '男']; // ES5;
const name = student.name;
const age = student.age;
const sex = student.sex;
console.log(name + ' --- ' + age + ' --- ' + sex); // ES6
const { name, age, sex } = student;
console.log(name + ' --- ' + age + ' --- ' + sex);

8.对象超类

ES6 允许在对象中使用 super 方法:

var parent = {
foo() {
console.log("Hello from the Parent");
}
} var child = {
foo() {
super.foo();
console.log("Hello from the Child");
}
} Object.setPrototypeOf(child, parent);
child.foo(); // Hello from the Parent
// Hello from the Child

9.for...of 和 for...in

for...of 用于遍历一个迭代器,如数组:

let letters = ['a', 'b', 'c'];
letters.size = 3;
for (let letter of letters) {
console.log(letter);
}
// 结果: a, b, c

for...in 用来遍历对象中的属性:

 let stus = ["Sam", "22", "男"];
for (let stu in stus) {
console.log(stus[stu]);
}
// 结果: Sam, 22, 男

10.ES6中的类

ES6 中支持 class 语法,不过,ES6的class不是新的对象继承模型,它只是原型链的语法糖表现形式。

函数中使用 static 关键词定义构造函数的的方法和属性:

class Student {
constructor() {
console.log("I'm a student.");
} study() {
console.log('study!');
} static read() {
console.log("Reading Now.");
}
} console.log(typeof Student); // function
let stu = new Student(); // "I'm a student."
stu.study(); // "study!"
stu.read(); // "Reading Now."

类中的继承和超集:

class Phone {
constructor() {
console.log("I'm a phone.");
}
} class MI extends Phone {
constructor() {
super();
console.log("I'm a phone designed by xiaomi");
}
} let mi8 = new MI();

extends 允许一个子类继承父类,需要注意的是,子类的constructor 函数中需要执行 super() 函数。

当然,你也可以在子类方法中调用父类的方法,如super.parentMethodName()。

在 这里 阅读更多关于类的介绍。

有几点值得注意的是:

  • 类的声明不会提升(hoisting),如果你要使用某个 Class,那你必须在使用之前定义它,否则会抛出一个 ReferenceError 的错误
  • 在类中定义函数不需要使用 function 关键词

1、基本认识vue

  • 轻量级,体积小是一个重要指标。Vue.js 压缩后有只有 20多kb (Angular 压缩后 56kb+,React 压缩后 44kb+)
  • 移动优先。更适合移动端,比如移动端的 Touch 事件
  • 易上手,学习曲线平稳,文档齐全
  • 吸取了 Angular(模块化)和 React(虚拟 DOM)的长处,并拥有自己独特的功能,如:计算属性
  • Vue是一个渐进式的框架可以将Vue作为你应用的一 部分嵌入其中,带来更丰富的交互体验。
  • 开源,社区活跃度高
  • Vue有很多特点和Web开发中常见的高级功能
    • 解耦视图和数据.
    • 可复用的组件
    • 前端路由技术
    • 状态管理
    • 虚拟DOM

下载地址

<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script>
  • NPM安装

初识vue.js

<body>

    <div id="app">{{message}}</div> //执行到这里显然出对应的HTML

    <script src="../js/vue.js"></script>
<script>
//执行这里创建Vue实例,并且对原HTML进行解析和修改。
//编程范式:声明式编程
const app = new Vue({ //创建Vue实例
el:'#app', //用于指定要挂载的元素
data:{ //定义数据
message:"洛依尘!"
}
})
//元素js的做法(编程范式:命令式编程)
// 1.创建div元素,设置id属性
// 2.定义一个变量叫message
// 3.将message变量放在前面的div元素中显示
</script>
</body>

MVVM 模式

MVVM 源自于经典的 Model–View–Controller(MVC)模式(期间还演化出了 Model-View-Presenter(MVP)模式,可忽略不计)。MVVM 的出现促进了 GUI 前端开发与后端业务逻辑的分离,极大地提高了前端开发效率。MVVM 的核心是 ViewModel 层,它就像是一个中转站(value converter),负责转换 Model 中的数据对象来让数据变得更容易管理和使用,该层向上与视图层进行双向数据绑定,向下与 Model 层通过接口请求进行数据交互,起呈上启下作用。

如下图所示:

简单画了一张图来说明 MVVM 的各个组成部分:

分层设计一直是软件架构的主流设计思想之一,MVVM 也不例外。

View 层

View 是视图层,也就是用户界面。前端主要由 HTML 和 CSS 来构建,为了更方便地展现 ViewModel 或者 Model 层的数据,已经产生了各种各样的前后端模板语言,比如 FreeMarker、Marko、Pug、Jinja2等等,各大 MVVM 框架如 KnockoutJS,Vue,Angular 等也都有自己用来构建用户界面的内置模板语言。

Model 层

Model 是指数据模型,泛指后端进行的各种业务逻辑处理和数据操控,主要围绕数据库系统展开。后端的处理通常会非常复杂

ViewModel 层

ViewModel 是由前端开发人员组织生成和维护的视图数据层。在这一层,前端开发者对从后端获取的 Model 数据进行转换处理,做二次封装,以生成符合 View 层使用预期的视图数据模型。需要注意的是 ViewModel 所封装出来的数据模型包括视图的状态和行为两部分,而 Model 层的数据模型是只包含状态的,比如页面的这一块展示什么,那一块展示什么这些都属于视图状态(展示),而页面加载进来时发生什么,点击这一块发生什么,这一块滚动时发生什么这些都属于视图行为(交互),视图状态和行为都封装在了 ViewModel 里。这样的封装使得 ViewModel 可以完整地去描述 View 层。由于实现了双向绑定,ViewModel 的内容会实时展现在 View 层,这是激动人心的,因为前端开发者再也不必低效又麻烦地通过操纵 DOM 去更新视图,MVVM 框架已经把最脏最累的一块做好了,我们开发者只需要处理和维护 ViewModel,更新数据视图就会自动得到相应更新,真正实现数据驱动开发。看到了吧,View 层展现的不是 Model 层的数据,而是 ViewModel 的数据,由 ViewModel 负责与 Model 层交互,这就完全解耦了 View 层和 Model 层,这个解耦是至关重要的,它是前后端分离方案实施的重要一环。

Vue实例的options

  • el:

    类型 : string | HTMLElement

    作用 : 决定之后Vue实例会管理哪一个DOM。
  • data:

    类型 : Object | Function (组件当中data必须是一个函数)

    作用 : Vue实例对应的数据对象。
  • methods:

    类型 : { [key: string]: Function }

    作用 : 定义属于Vue的一 些方法,可以在其他地方调用,也可以在指令中使用。

vue实例的生命周期

一、解析

1、什么是生命周期:从Vue实例创建、运行、到销毁期间,总是伴随着各种各样的事件,这些事件,统称为生命周期!

2、生命周期钩子 = 生命周期函数 = 生命周期事件

3、主要的生命周期函数分类:

- 创建期间的生命周期函数:

+ beforeCreate:实例刚在内存中被创建出来,此时,还没有初始化好 data 和 methods 属性

+ created:实例已经在内存中创建OK,此时 data 和 methods 已经创建OK,此时还没有开始 编译模板

+ beforeMount:此时已经完成了模板的编译,但是还没有挂载到页面中

+ mounted:此时,已经将编译好的模板,挂载到了页面指定的容器中显示

- 运行期间的生命周期函数:

+ beforeUpdate:状态更新之前执行此函数, 此时 data 中的状态值是最新的,但是界面上显示的 数据还是旧的,因为此时还没有开始重新渲染DOM节点

+ updated:实例更新完毕之后调用此函数,此时 data 中的状态值 和 界面上显示的数据,都已经完成了更新,界面已经被重新渲染好了!

- 销毁期间的生命周期函数:

+ beforeDestroy:实例销毁之前调用。在这一步,实例仍然完全可用。

+ destroyed:Vue 实例销毁后调用。调用后,Vue 实例指示的所有东西都会解绑定,所有的事件监听器会被移除,所有的子实例也会被销毁。

<body>
<div id="app">
<input type="button" value="修改msg" @click="msg='No'">
<h3 id="h3">{{ msg }}</h3>
</div> <script>
// 创建 Vue 实例,得到 ViewModel
var vm = new Vue({
el: '#app',
data: {
msg: 'ok'
},
methods: {
show() {
console.log('执行了show方法')
}
},
beforeCreate() { // 这是我们遇到的第一个生命周期函数,表示实例完全被创建出来之前,会执行它
console.log(this.msg)
this.show()
// 注意: 在 beforeCreate 生命周期函数执行的时候,data 和 methods 中的 数据都还没有没初始化
},
created() { // 这是遇到的第二个生命周期函数
console.log(this.msg)
this.show()
// 在 created 中,data 和 methods 都已经被初始化好了!
// 如果要调用 methods 中的方法,或者操作 data 中的数据,最早,只能在 created 中操作
},
beforeMount() { // 这是遇到的第3个生命周期函数,表示 模板已经在内存中编辑完成了,但是尚未把 模板渲染到 页面中
console.log(document.getElementById('h3').innerText)
// 在 beforeMount 执行的时候,页面中的元素,还没有被真正替换过来,只是之前写的一些模板字符串
},
mounted() { // 这是遇到的第4个生命周期函数,表示,内存中的模板,已经真实的挂载到了页面中,用户已经可以看到渲染好的页面了
console.log(document.getElementById('h3').innerText)
// 注意: mounted 是 实例创建期间的最后一个生命周期函数,当执行完 mounted 就表示,实例已经被完全创建好了,此时,如果没有其它操作的话,这个实例,就静静的 躺在我们的内存中,一动不动
}, // 接下来的是运行中的两个事件
beforeUpdate() { // 这时候,表示 我们的界面还没有被更新【数据被更新了吗? 数据肯定被更新了】
console.log('界面上元素的内容:' + document.getElementById('h3').innerText)
console.log('data 中的 msg 数据是:' + this.msg)
// 得出结论: 当执行 beforeUpdate 的时候,页面中的显示的数据,还是旧的,此时 data 数据是最新的,页面尚未和 最新的数据保持同步
},
updated() {
console.log('界面上元素的内容:' + document.getElementById('h3').innerText)
console.log('data 中的 msg 数据是:' + this.msg)
// updated 事件执行的时候,页面和 data 数据已经保持同步了,都是最新的
}
});
</script>
</body>

2、基本语法

1、插值操作

Mustache语法

<div id="app">
<h2>{{massage}}</h2>
<h2>{{massage}},洛依尘</h2>
<h2>{{firstName+lastName}}</h2>
<h2>{{firstName+' '+lastName}}</h2>
<h2>{{counter*2}}</h2>
</div> <body>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el: "#app",
data: {
massage: "你好",
firstName:"kobe",
lastName:"bryant",
counter:200
}
})
</script>
</body>

v-once指令

该指令后面不需要跟任何表达式(比如之前的v-for后面是由跟表达式的

该指令表示元素和组件(组件后面才会学习)只渲染- 次,不会随着数据的改变而改变

<h2 v-once>{{massage}}</h2>

v-html

该指令后面往往会跟上一个string类型

会将string的html解析出来并且进行渲染

	<h2>{{url}}</h2>  <!-- <a href="www.baidu.com">百度一下</a> -->
<h2 v-html="url"></h2> <!-- 百度一下 -->

v-text

都是用于将数据显示在界面中,但是通常只接受一个string类型

	<h2 v-text="massage">,洛依尘</h2>	<!--你好-->

v-pre

用于跳过这个元素和它子元素的编译过程,用于显示原本的Mustache语法

	<h2 v-pre>{{massage}}</h2> <!-- {{massage}} -->

v-cloak

在某些情况下,f防止浏览器可能会直接显然出未编译的Mustache标签。

<style>
[v-cloak] {
display: none;
}
</style>
</head> <div id="app" v-cloak>
<h2>{{massage}}</h2>
<h2 v-once>{{massage}}</h2>
<h2>{{url}}</h2> <!-- <a href="www.baidu.com">百度一下</a> -->
<h2 v-html="url"></h2> <!-- 百度一下 -->
<h2 v-text="massage">,洛依尘</h2>
<!--你好-->
<h2 v-pre>{{massage}}</h2> <!-- {{massage}} -->
</div> <body>
<script src="../js/vue.js"></script>
<script>
//在vue解析之前,div里有一个属性c-cloak
//在vue解析之后,div里没有一个属性c-cloak
const app = new Vue({
el: "#app",
data: {
massage: "你好",
url: '<a href="www.baidu.com">百度一下</a>'
}
})
</script>
</body>

2、绑定属性

v-bind

v-bind用于绑定一个或多个属性值,或者向另-一个组件传递props值

<div id="app">

  <!-- <img src="{{imgURL}}" alt=""> -->
<!-- 错误的用法:这里不可以使用mustache语法--> <!-- 正确用法:使用v-band指令 -->
<a v-bind:href="aHref">百度</a>
<img v-bind:src='imgURL' alt="" > <!-- 语法糖的写法 -->
<a :href="aHref">百度</a>
<img :src='imgURL' alt="" > </div> <body>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el: "#app",
data: {
massage: "你好",
imgURL:'https://www.baidu.com/img/PCtm_d9c8750bed0b3c7d089fa7d55720d6cf.png',
aHref:"https://www.baidu.com/"
}
})
</script>
</body>

v-bind 动态绑定class(对象语法)

  • 可以通过{ }绑定一个类
  • 也可以通过判断,传入多个值
  • 和普通类同时存在,并不冲突
  • 如果过于复杂,可以放在一个methods或者computed中
<style>
.active{
color: red;
}
</style>
</head> <div id="app">
<!-- <h2 class="active">{{massage}}</h2>
<h2 :class="active">{{massage}}</h2> --> <!-- <h2 :class="{类名1:ture,类名2:boolean}">{{massage}}</h2> 对class对象进行选择-->
<h2 v-bind:class="{active: isActive , line: isLine}">{{massage}}</h2>
<!-- 将内容放在一个methods里,并调用 -->
<h2 v-bind:class="getClasses()">{{massage}}</h2>
<button v-on:click="bntClick">按钮</button>
<!-- 监听按钮,使用bntClick方法 -->
</div> <body>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el: "#app",
data: {
massage: "你好",
active:'active',
isActive:true, //设置boolean值决定是否启用
isLine:true
},
methods:{
bntClick: function(){
this.isActive=!this.isActive
},
getClasses:function(){
return {active: this.isActive, line: this.isLine}
}
}
})
</script>
</body>

v-bind 动态绑定class(数组语法)

<div id="app">
<!-- 如果在[]数组里的元素加了引号,代表他是一个字符串,而不是引用一个变量 -->
<h2 :class="[active,line]">{{massage}}</h2>
<h2 :class="['active','line']">{{massage}}</h2>
<h2 :class="getClasses()">{{massage}}</h2>
</div> <body>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el: "#app",
data: {
massage: "你好",
active:"aaa",
line:"bbb"
},
methods:{
getClasses:function(){
return [this.active,this.line]
}
}
})
</script>
</body>

小作业:点击列表中的哪一项, 那么该项的文字变成红色

<style>
.active {
color: red;
}
</style>
</head> <div id="app">
<ul>
<li v-for="(item, index) in movies" :class="{active: currentIndex === index}" @click="liClick(index)">
<!-- {active: currentIndex === index}当currentIndex === index为true时,改变颜色 -->
{{index}}.{{item}}
</li>
</ul>
</div> <body>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el: "#app",
data: {
movies: ['海王', '火影忍者', '进击的巨人', '死神'],
currentIndex: 0
},
methods: {
liClick(index) {
this.currentIndex = index
}
}
})
</script>
</body>

v-bind 绑定style

<div id="app">	<!-- <h2 :style="{key(属性名):value(属性值)}">{{massage}}</h2> -->  <!-- 这里要加' '要不然vue会去解析50px这个变量然后报错 -->  <h2 :style="{fontSize: '50px'}">{{massage}}</h2>    <!-- finalSize当成一个变量在使用 -->  <h2 :style="{fontSize: finalSize}">{{massage}}</h2>  <!-- 也可以拼接 -->  <h2 :style="{fontSize: finalSize + 'px',color:finalColor}">{{massage}}</h2>  <!-- 数组语法 -->  <h2 :style="[baseStyle,baseStyle1]">{{massage}}</h2></div><body>	<script src="../js/vue.js"></script>	<script>		const app = new Vue({			el: "#app",			data: {				massage: "你好",        finalSize: 100,        finalColor: 'red',        baseStyle:{color:'red'},        baseStyle1:{fontSize:'75px'}			}		})	</script></body>

3、计算属性

一、什么是计算属性

  模板内的表达式非常便利,但是设计它们的初衷是用于简单运算的。在模板中放入太多的逻辑会让模板过重且难以维护。

二、计算属性的用法

  在一个计算属性里可以完成各种复杂的逻辑,包括运算、函数调用等,只要最终返回一个结果就可以。

<div id="app">	<h2>{{firstName+' '+lastName}}</h2>  <h2>{{fullName}}</h2>  <h2>总价格:{{totalPrice}}</h2></div><body>	<script src="../js/vue.js"></script>	<script>		const app = new Vue({			el: "#app",			data: {				firstName:"luo",        lastName:"yichen",        books:[          {id:100, name: 'java核心技术' , price:100},          {id:101, name: 'c核心技术' , price:100},          {id:102, name: 'php核心技术' , price:100},          {id:103, name: 'python核心技术' , price:100}        ]			},      // computed: 计算属性()      computed:{        fullName:function(){          return this.firstName+' '+this.lastName        },        totalPrice:function(){          let result =0          for (let i=0;i < this.books.length; i++){            result += this.books[i].price          }          return result;        }      }		})	</script>

计算属性的getter和setter

每个计算属性都包含一个getter和一个setter

  • 在上面的例子中,我们只是使用getter来读取。
  • 在某些情况下,你也可以提供一个setter方法 (不常用)。
  • 在需要写setter的时候,代码如下: .
<div id="app">  <h2>{{fullName}}</h2></div><body>  <script src="../js/vue.js"></script>  <script>    const app = new Vue({      el: "#app",      data: {        firstName: "luo",        lastName: "yichen",      },      computed: {        // fullName: function () {        //   return this.firstName + ' ' + this.lastName        // }        // 计算属性一般没有set值,只读属性。        fullName:{          set: function(newValue){            const names = newValue.split(" ");            this.firstName = names[0];            this.lastName = names[1];          },           get: function(){            return this.firstName + ' ' + this.lastName          }        },        // 简洁写法        // fullName:function(){        //   return this.firstName+' '+this.lastName        // }      }    })  </script></body>

计算属性与methods对比

<div id="app">  <!-- 通过拼接:语法过于繁琐 -->  <h2>{{firstName}} {{lastName}}</h2>  <!-- 通过定义methods 每次都要调用-->  <h2>{{getFullName()}}</h2>  <!-- 通过computed 如果没有发生改变只需要调用一次-->  <h2>{{fullName}}</h2></div><body>  <script src="../js/vue.js"></script>  <script>    const app = new Vue({      el: "#app",      data: {        firstName: "luo",        lastName: "yichen"      },      methods: {        getFullName: function () {          return this.firstName + ' ' + this.lastName        }      },      computed: {        fullName: function () {          return this.firstName + ' ' + this.lastName        }      }    })  </script></body>

4、事件监听

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

获取到浏览器参数的event对象: $event

<div id="app">	<h2>{{counter}}</h2>  <button v-on:click="increment">+</button>  <button v-on:click="decrement">-</button>  <!-- 语法糖 当没参数时()可以不用写 -->  <button @click="increment">+</button>  <button @click="decrement">-</button>  <!-- 事件调用时没有参数 -->  <button @click="bnt1Click()">按钮1</button>  <button @click="bnt1Click">按钮1</button>  <!-- 在事件定义前,写函数省略了小括号,但是方法本身需要一个参数,这个时候  Vue会将浏览器默认生成的event事件对象作为参数传入方法中 -->  <button @click="bnt2Click(123)">按钮2</button>   <button @click="bnt2Click()">按钮2</button>  <button @click="bnt2Click">按钮2</button>  <!-- 定义方法时,我们需要event对象,同时又需要其他参数 -->  <!-- 在调用方式时,如何手动的获取到浏览器参数的event对象: $event -->  <button @click="bnt3Click('abc',$event)">按钮3</button></div><body>	<script src="../js/vue.js"></script>	<script>		const app = new Vue({			el: "#app",			data: {				counter: 0			},      methods:{        increment(){          this.counter++        },        decrement(){          this.counter--        },        bnt1Click(){          console.log("bnt1Click");        },        bnt2Click(abc){          console.log("--------------",abc);        },        bnt3Click(abc,event){          console.log("++++++++++++++", abc,event);        }      }		})    // 如果我们函数需要参数,但是没有传入参数,那么函数的形参为undefined    function abc(name){      console.log(name);    }    abc()	</script></body>

v-on的修饰符

  1. .stop修饰符的使用

    当多对标签进行重叠的时候, 你点击最上面的一层标签的时候, 会自动的冒泡到他下面的所有标签上面

    .stop就是阻止冒泡使用的

  2. .prevent修饰符的使用

    form表单提交时候或者在点击a标签的时候, 会阻止提交或跳转

  3. .keyup监听某个键盘的键帽

    监听某个键盘的键位

  4. .once修饰符的使用

    绑定后只会触发一次

<div id="app">  <!-- 1. .stop -->  <div @click='divClick'>    aaaaa    <button @click.stop='bntClick'>按钮</button>  </div>  <!-- 2. .prevent  -->  <form action="baidu">    <input type="submit" value="提交" @click.prevent='submitClick'>  </form>  <!-- 3. 监听某个键盘的键位 -->  <input type="text" @keyup.enter="keyUp">  <!-- 4. once修饰符的使用 -->  <button @click.once='bnt2Click'>按钮</button></div><body>  <script src="../js/vue.js"></script>  <script>    const app = new Vue({      el: "#app",      data: {        massage: "你好"      },      methods: {        bntClick() {          console.log('bnt')        },        divClick() {          console.log('div')        },        submitClick() {          console.log("submitClick")        },        keyUp() {          console.log("up")        },        bnt2Click() {          console.log('bnt2');        }      }    })  </script></body>

5、条件判断

v-if的原理:

v-if后面的条件为false时,对应的元素以及其子元素不会渲染。

也就是根本没有不会有对应的标签出现在DOM中。

<div id="app">  <h2 v-if="score>90">优秀</h2>  <h2 v-else-if="score>80">良好</h2>  <h2 v-else-if="score>60">及格</h2>  <h2 v-else>不及格</h2>  <h1>{{result}}</h1>  <h2 v-if="isShow">{{massage}}</h2>  <h1 v-else>当isShow为false时显示我</h1></div><body>  <script src="../js/vue.js"></script>  <script>    const app = new Vue({      el: "#app",      data: {        massage: "你好",        isShow: true,        score: 99      },      computed: {        result() {          let showMessage = '';          if (this.score >= 90) {            showMessage = "优秀"          } else if (this.score >= 80) {            showMessage = "良好"          }          // ...          return showMessage        }      }    })  </script></body>

用户切换的小案例

<div id="app">	<span v-if="isUser">    <label for="username">用户账号</label>    <input type="text" id="username" placeholder="用户账号" key='username'>  </span>  <span v-else>    <label for="emailname">用户邮箱</label>    <input type="text" id="emailname" placeholder="用户邮箱" key='emailname'>  </span>  <button @click="isUser = !isUser">切换类型</button></div><body>	<script src="../js/vue.js"></script>	<script>		const app = new Vue({			el: "#app",			data: {				isUser:true			}		})	</script></body>

小问题:

  • 如果我们在有输入内容的情况下,切换了类型,我们会发现文字依然显示之前的输入的内容。
  • 但是按道理讲,我们应该切换到另外一个input元素中了。
  • 在另一个input元素中,我们并没有输入内容。
  • 为什么会出现这个问题呢?

问题解答:

  • 这是因为Vue在进行DOM渲染时,出于性能考虑,会尽可能的复用已经存在的元素,而不是重新创建新的元素。
  • 在上面的案例中, Vue内部会发现原来的input元素不再使用,直接作为else中的input来使用了.

解决方案:

  • 如果我们不希望Vue出现类似重复利用的问题,可以给对应的input添加key
  • 并且我们需要保证key的不同

Virtual DOM 是什么?

Virtual DOM 其实就是一棵以 JavaScript 对象( VNode 节点)作为基础的树,用对象属性来描述节点,实际上它只是一层对真实 DOM 的抽象。最终可以通过一系列操作使这棵树映射到真实环境上。

简单来说,可以把Virtual DOM 理解为一个简单的JS对象,并且最少包含标签名( tag)、属性(attrs)和子元素对象( children)三个属性。不同的框架对这三个属性的命名会有点差别。

对于虚拟DOM,咱们来看一个简单的实例,就是下图所示的这个,详细的阐述了模板 → 渲染函数 → 虚拟DOM树 → 真实DOM的一个过程

Virtual DOM 作用是什么?

虚拟DOM的最终目标是将虚拟节点渲染到视图上。但是如果直接使用虚拟节点覆盖旧节点的话,会有很多不必要的DOM操作。例如,一个ul标签下很多个li标签,其中只有一个li有变化,这种情况下如果使用新的ul去替代旧的ul,因为这些不必要的DOM操作而造成了性能上的浪费。

为了避免不必要的DOM操作,虚拟DOM在虚拟节点映射到视图的过程中,将虚拟节点与上一次渲染视图所使用的旧虚拟节点(oldVnode)做对比,找出真正需要更新的节点来进行DOM操作,从而避免操作其他无需改动的DOM。

其实虚拟DOM在Vue.js主要做了两件事:

  • 提供与真实DOM节点所对应的虚拟节点vnode
  • 将虚拟节点vnode和旧虚拟节点oldVnode进行对比,然后更新视图

v-if和v-show的区别

v-show控制的是节点的display属性 v-if是将节点删除了 如果节点需要频繁显示隐藏 使用v-show性能更佳!

<div id="app">  <!-- v-if: 当条件为false时,包含v-if指令的元素,根本就不会存在dom中 -->  <h2 v-if='isShow' id="aaa">{{massage}}</h2>  <!-- V- show:当条件为false时,v-show只是给我们的元素添加一个行内样式: display: none -->  <h2 v-show='isShow' id="bbb">{{massage}}</h2></div><body>  <script src="../js/vue.js"></script>  <script>    const app = new Vue({      el: "#app",      data: {        massage: "你好",        isShow: true      }    })  </script></body>

6、循环遍历

当我们有一组数据需 要进行渲染时,我们就可以使用v-for来完成。

v-for的语法类似于JavaScript中的for循环。

格式如下: item in items的形式。

<div id="app">  <!-- 1.在遍历的过程中,没有使用索引值(下标值) -->  <ul>    <li v-for='item in names'>{{item}}</li>  </ul>  <!-- 2.在遍历过程中,获取索引值 -->  <ul>    <li v-for='(item,index) in names'>      {{index+1}}.{{item}}    </li>  </ul>  <!-- 1.在遍历对象的过程中,如果只是获取一个值,那么获取到的是value -->  <ul>    <li v-for="item in info">{{item}}</li>  </ul>  <!-- 2., 获取key和value 格式(value,key) -->  <ul>    <li v-for="(value,key) in info">{{value}}-{{key}}</li>  </ul>  <!-- 3. 获取key和value和index 格式(value,key,index)-->  <ul>    <li v-for="(value,key,index) in info">{{value}}-{{key}}-{{index}}</li>  </ul></div><body>  <script src="../js/vue.js"></script>  <script>    const app = new Vue({      el: "#app",      data: {        names: ['why', 'who', 'what', 'where']	//遍历数组      },      info: {									//遍历对象        name: 'lyc',        age: 18,        height: 1.88      }    })  </script></body>

v-for加key属性

  • 为什么需要这个key属性呢(了解) ?

    • 这个其实和Vue的虚拟DOM的Diff算法有关系。
    • 这里我们借用React' S diff algorithm中的一张图来简单说明一下:
  • 当某一层有很多相同的节点时,也就是列表节点时,我们希望插入一一个新

    的节点

    • 我们希望可以在B和C之间加一一个F , Diff算法默认执行起来是这样的。
    • 即把C更新成F , D更新成C , E更新成D ,最后再插入E ,是不是很没有

      效率?
  • 所以我们需要使用key来给每个节点做一个唯一标识

    • Diff算法就可以正确的识别此节点

    • 0找到正确的位置区插入新的节点。

所以一句话, key的作用主要是为了高效的更新虚拟DOM。

哪些数组方法是响应式的

<body>  <script src="../js/vue.js"></script>  <script>    const app = new Vue({      el: "#app",      data: {        letters: ['A', 'C', 'B', 'D', 'E']      },      methods: {        btnClick() {          // 1.push()   在数组最后添加元素          this.letters.push('aaa','bbb')          // 2.pop()      在数组最后删除一个元素          this.letters.pop();          // 3.shift()   删除在数组第一个元素          this.letters.shift();          // 4.unshift() 在数组最前面添加元素          this.letters.unshift('ddd','ddd');          // 5.splice()   删除/插入/替换元素          // 删除元素: 第一参数传入你从第几个元素开始删除,第二参数传入你要删除的几个元素(如果没有传,就删除后面所有元素)          // 插入元素: 第二个传入0,后面跟上要添加的值          // 替换元素: 第二参数传入你要删除元素,后面追加你要写入的元素完成替换          this.letters.splice(1,3,'m','n','l')          // 6.sort()     排序          this.letters.sort()          // 7.reverse()  反转          this.letters.reverse()          // 注意:通过索引值直接来修改数组中的元素 不是响应式          // this.letters[0]='bbbbbbbbbbbb'          // set(要修改的对象,索引值,修改后的值)          Vue.set(this.letters,0,'bbbbbb')        }      }    })    // 扩展知识:可变参数    // function sum(...sum){    //   console.log(sum);    // }    // sum(11,223,44,56,77,889,9,1)  </script></body>

6、表单绑定

  • 表单控件在实际开发中是非常常见的。特别是对于用户信息的提交,需要大量的表单。
  • Vue中使用v-model指令来实现表单元素和数据的双向绑定。
<body>  <div id="app">    <input type="text" v-model="massage">    {{massage}}  </div>  <script src="../js/vue.js"></script>  <script>    const app = new Vue({      el: "#app",      data: {        massage: "你好"      }    })  </script></body>
  • 当我们在输入框输入内容时
  • 因为input中的v-model绑定了message ,所以会实时将输入的内容传递给message , message发生改变。
  • 当message发生改变时,因为上面我们使用Mustache语法,将message的值插入到DOM中,所以DOM会发生响应的改变。
  • 所以,通过v-model实现了双向的绑定。

原理:

  <div id="app">    <!-- <input type="text" v-model="massage"> -->    <!-- <input type="text" :value="massage" @input="valueChange"> -->    <input type="text" :value="massage" @input="massage = $event.target.value">    {{massage}}  </div>  <script src="../js/vue.js"></script>  <script>    const app = new Vue({      el: "#app",      data: {        massage: "你好"      },      methods: {        valueChange(event) {          this.massage = event.target.value;        }      }    })  </script></body>

v-model结合radio类型

<div id="app">  <label for="">    <input type="radio" id="male" value="男" v-model="sex">男  </label>  <label for="">    <input type="radio" id="female" value="女" v-model="sex">女  </label>  <h2>{{sex}}</h2></div><body>  <script src="../js/vue.js"></script>  <script>    const app = new Vue({      el: "#app",      data: {        message: "你好",        sex:'男'      }    })  </script></body>

v-model结合checkbox类型

单个勾选框: .

  • v-modelI即为布尔值。
  • 此时input的value并不影响v-model的值。

多个复选框:

  • 多个复选框时,因为可以选中多个,所以对应的data中属性是一个数组。
  • 当选中某一个时 ,就会将input的value添加到数组中。
<div id="app">  <!-- 单选框 -->  <!-- <label for="agree">    <input type="checkbox" id="agree" v-model="isAgree">同意协议  </label>  <h2>{{isAgree}}</h2>  <button :disabled="!isAgree">下一步</button> -->  <!-- 多选框 -->    <!-- <input type="checkbox" value="篮球" v-model="hobbies">篮球    <input type="checkbox" value="足球" v-model="hobbies">足球    <input type="checkbox" value="排球" v-model="hobbies">排球    <input type="checkbox" value="手球" v-model="hobbies">手球    <h2>{{hobbies}}</h2> -->    <label v-for="item in originHobbies" :for="item">      <input type="checkbox" :value="item" :id="item" v-model="hobbies">{{item}}    </label>  </div><body>  <script src="../js/vue.js"></script>  <script>    const app = new Vue({      el: "#app",      data: {        message: "你好",        isAgree: false,//单选框        hobbies:[],//多选框         originHobbies:['篮球','足球','乒乓球','台球','高尔夫球']          //也可以通过值绑定来从服务器获取值      }    })  </script></body>

v-model结合select

单选:只能选中一个值。

  • v-model绑定的是一个值。
  • 当我们选中option中的一个时,会将它对应的value赋值到mySelect中

多选:可以选中多个值。

  • v-model绑定的是一个数组。
  • 当选中多个值时,就会将选中的option对应的value添加到数组mySelects中
<body>  <div id="app">    <!-- 1、选择一个 -->    <select name="abc" id=""  v-model="fruit">      <option value="苹果">苹果</option>      <option value="香蕉">香蕉</option>      <option value="榴莲">榴莲</option>      <option value="西瓜">西瓜</option>    </select>    <h2>{{fruit}}</h2>    <!-- 2、选择多个 -->    <select name="abc" id=""  v-model="fruits" multiple>      <option value="苹果">苹果</option>      <option value="香蕉">香蕉</option>      <option value="榴莲">榴莲</option>      <option value="西瓜">西瓜</option>    </select>    <h2>{{fruits}}</h2>  </div>    <script src="../js/vue.js"></script>    <script>      const app = new Vue({        el: "#app",         data: {          message: "你好",          fruit:"香蕉",          fruits:[]        }      })    </script></body>

v-model的修饰符

lazy修饰符:

  • 默认情况下, v- model默认是在input事件中同步输入框的数据的。
  • 也就是说, 一旦有数据发生改变对应的data中的数据就会自动发生

    改变。
  • lazy修饰符可以让数据在失去焦点或者回车时才会更新:

number修饰符:

  • 默认情况下,在输入框中无论我们输入的是字母还是数字,都会被

    当做字符串类型进行处理。
  • 但是如果我们希望处理的是数字类型,那么最好直接将内容当做数

    字处理。
  • number修饰符可以让在输入框中输入的内容自动转成数字类型:

trim修饰符:

  • 如果输入的内容首尾有很多空格,通常我们希望将其去除
  • trim修饰符可以过滤内容左右两边的空格
<div id="app">  <!-- 1.修饰符:lazy -->  <input type="text" v-model.lazy="message">  <h2>{{message}}</h2>  <!-- 2.修饰符:number -->  <input type="number" v-model.number="age">  <h2>{{typeof age}}</h2>  <!-- 3.修饰符:trim -->  <input type="text" v-model.trim="name">  <h2>{{name}}</h2></div><body>   <script src="../js/vue.js"></script>  <script>    const app = new Vue({      el: "#app",      data: {        message: "你好",        age:12,        name:''      }    })  </script></body>

综合-书籍购物车案例

  • HTML
<!DOCTYPE html><html lang="en"><head>  <meta charset="UTF-8">  <meta http-equiv="X-UA-Compatible" content="IE=edge">  <meta name="viewport" content="width=device-width, initial-scale=1.0">  <title>Document</title>  <link rel="stylesheet" href="./style.css"></head><body>  <div id="app">    <div v-if="books.length">      <table>        <thead>          <tr>            <th></th>            <th>书籍名称</th>            <th> 出版日期</th>            <th> 价格</th>            <th> 购买数量</th>            <th> 操作</th>          </tr>        </thead>        <tbody>          <tr v-for="(item,index) in books">            <td>{{item.id}}</td>            <td>{{item.name}}</td>            <td>{{item.date}}</td>            <td>{{item.price | showPrice}}</td>            <td>              <button @click="decrement(index)" v-bind:disabled="item.count <= 1">-</button>              {{item.count}}              <button @click="increment(index)">+</button>            </td>            <td><button @click="removeHandler(index)">移除</button></td>          </tr>        </tbody>      </table>      <h2>        总价格: {{totalPrice | showPrice}}      </h2>    </div>    <div v-else>      <h1>购物车为空</h1>    </div>  </div>  <script src="../js/vue.js"></script>  <script src="./main.js"></script></body></html>
  • CSS
table{  border: 1px solid #000;  border-collapse: collapse;  border-spacing: 0;}th,td{  padding: 8px 16px;  border: 1px solid #000;  text-align: left;}th{  background-color: #f7f7f7;  color: #5c6b77;  font-weight: 600;}
  • JS
const app = new Vue({  el: "#app",  data: {    books: [{        id: 1,        name: '《算法导论》',        date: "2006-9",        price: 85.00,        count: 1      },      {        id: 2,        name: '《算法导论》',        date: "2006-9",        price: 85.00,        count: 1      },      {        id: 3,        name: '《算法导论》',        date: "2006-9",        price: 85.00,        count: 1      },      {        id: 4,        name: '《算法导论》',        date: "2006-9",        price: 85.00,        count: 1      }    ]  },  methods: {    // getFinalPrice(price){    //   return '¥'+price.toFixed(2) //toFixed(2)保留两位小数    // }    increment(index) {      this.books[index].count++    },    decrement(index) {      this.books[index].count--    },    removeHandler(index) {      this.books.splice(index, 1)    }  },  filters: { //过滤器    showPrice(price) {      return '¥' + price.toFixed(2)    }  },  computed: {    totalPrice() {      let totalPrice = 0;      for (let i = 0; i < this.books.length; i++) {        totalPrice += this.books[i].price * this.books[i].count;      }      return totalPrice;    }  }})

JS高阶函数

编程范式:命令式编程/声明式编程

编程范式:面向对象编程(第一公民:对象)/函数式编程(第一公民:函数)

filter/map/reduce

filter中的回调函数有一个要求:必须返回一个 boolean值

true:当返回true时,函数内部会自动将这次回调的n加入到新的数组中

false:当返回false时,函数内部会过滤掉这次的n

  • 基本写法
const nums = [10,20,111,222,444,40,50]// 1.需求:取出小于100的数字let newNums = []for(let n of nums){  if(n > 100){    newNums.push(n)  }}// 2.需求:将所有小于160的数字进行转化:全部*2let new2Nums = []for(let n of newNums){  new2Nums.push(n*2)}// 3.需求:将所有new2Nums数字相加,得到最终的记过let total = 0for(let n of new2Nums){  total +=n}console.log(total)
  • 高阶写法
const nums = [10,20,111,222,444,40,50]// 1.filter函数的使用let newNums = nums.filter(function(n){  return n<100})console.log(newNums)// 2.map函数的使用let new2Nums = newNums.map(function(n){  return n*2})console.log(new2Nums)// 3.reduce函数的使用// reduce作用对数组中所有的内容进行汇总let total = new2Nums.reduce(function(preValue,n){  return preValue + n;},0)console.log(total)// 第一次: revalue 0  n 20// 第二次: revalue 20 n 40// 第二次: revalue 60 n 80// 第二次: revalue 140 n 100// 240
  • 高阶综合写法
const nums = [10,20,111,222,444,40,50]// 综合let total = nums.filter(function(n){  return n<100}).map(function(n){  return n*2}).reduce(function(preValue,n){  return preValue + n;},0) //初始化console.log(total)//使用箭头函数进一步简化let total = nums.filter(n => n<100).map(n => n*2).reduce((pre,n) => pre+n)console.log(total)

3、组件化开发

一、什么是组件化开发

人面对复杂问题的处理方式:

任何一个人处理信息的逻辑能力都是有限的

所以,当面对一个非常复杂的问题时,我们不太可能一次性搞定一大堆的内容。

但是,我们人有一种天生的能力,就是将问题进行拆解。

如果将一个复杂的问题,拆分成很多个可以处理的小问题,再将其放在整体当中,你会发现大的问题也会迎刃而解。

组件化也是类似的思想:

如果我们将一个页面中所有的处理逻辑全部放在一起,处理起来就会变得非常复杂,而且不利于后续的管理以及扩展。

但如果,我们讲一个页面拆分成一个个小的功能块,每个功能块完成属于自己这部分独立的功能,那么之后整个页面的管理和维护就变得非常容易了。

我们将一个完整的页面分成很多个组件。

每个组件都用于实现页面的一个功能块。

而每一个组件又可以进行细分。

二、Vue组件化思想

组件化是Vue.js中的重要思想

它提供了一种抽象,让我们可以开发出一个个独立可复用的小组件来构造我们的应用。

任何的应用都会被抽象成一颗组件树。

组件化思想的应用:

有了组件化的思想,我们在之后的开发中就要充分的利用它。

尽可能的将页面拆分成一个个小的、可复用的组件。

这样让我们的代码更加方便组织和管理,并且扩展性也更强。

所以,组件是Vue开发中,非常重要的一个篇章,要认真学习。

三、注册组件的基本步骤

组件的使用分成三个步骤:

创建组件构造器

注册组件

使用组件。

我们来看看通过代码如何注册组件

查看运行结果:

和直接使用一个div看起来并没有什么区别。

但是我们可以设想,如果很多地方都要显示这样的信息,我们是不是就可以直接使用来完成呢?

四、注册组件步骤解析

这里的步骤都代表什么含义呢?

1.Vue.extend():

调用Vue.extend()创建的是一个组件构造器。

通常在创建组件构造器时,传入template代表我们自定义组件的模板。

该模板就是在使用到组件的地方,要显示的HTML代码。

事实上,这种写法在Vue2.x的文档中几乎已经看不到了,它会直接使用下面我们会讲到的语法糖,但是在很多资料还是会提到这种方式,而且这种方式是学习后面方式的基础。

2.Vue.component():

调用Vue.component()是将刚才的组件构造器注册为一个组件,并且给它起一个组件的标签名称。

所以需要传递两个参数:1、注册组件的标签名 2、组件构造器

3.组件必须挂载在某个Vue实例下,否则它不会生效。

我们来看下面我使用了三次

而第三次其实并没有生效:

第三步的解析

<div id="app">    <my-cpn></my-cpn></div><body>  <script src="../js/vue.js"></script>  <script>    //1.创建组件构造器对象    const cpnC = Vue.extend({      template: `        <div>          <h2>我是标题</h2>          <p>我是内容,红红火火恍恍惚惚</p>          <p>我是内容,红红火火恍恍惚惚</p>        </div>`    })    // 2.注册组件    Vue.component('my-cpn',cpnC)    const app = new Vue({      el: "#app",      data: {        message: "你好"      }    })  </script></body>

五、全局组件和局部组件

当我们通过调用Vue.component()注册组件时,组件的注册是全局的

这意味着该组件可以在任意Vue示例下使用。

如果我们注册的组件是挂载在某个实例中, 那么就是一个局部组件

<div id="app">    <cpn></cpn></div><div id="app2">  <cpn></cpn></div><body>  <script src="../js/vue.js"></script>  <script>    //1.创建组件构造器对象    const cpnC = Vue.extend({      template: `        <div>          <h2>我是标题</h2>          <p>我是内容,红红火火恍恍惚惚</p>          <p>我是内容,红红火火恍恍惚惚</p>        </div>`    })    // 2.注册组件(全局组件,意味着可以在多个Vue的实力下面使用)    Vue.component('my-cpn',cpnC)    const app = new Vue({      el: "#app",      data: {        message: "你好"      },      //在Vue实例内注册组件就是局部组件      components:{        //cpn使用组件时的标签名        cpn:cpnC      }    })        const app2 = new Vue({      el: "#app2",      data: {        message: "你好"      }    })  </script></body>

六、父子组件

父子组件错误用法:以子标签的形式在Vue实例中使用

  • 因为当子组件注册到父组件的components时, Vue会编译好父组件的模块
  • 该模板的内容已经决定了父组件将要渲染的HTML (相当于父组件中已经有了子组件中的内容了)
  • 是只能在父组件中被识别的。
  • 类似这种用法, 是会被浏览器忽略的。
<div id="app">	<cpn1></cpn1>  <cpn2></cpn2></div><body>	<script src="../js/vue.js"></script>	<script>    // 1.创建第一个组件构造器(子组件)    const cpnC1 = Vue.extend({      template:`      <div>      <h2>我是标题</h2>      <p>我是内容,红红火火恍恍惚惚</p>      </div>      `    })    // 2.创建第二个组件构造器(父组件)    const cpnC2 = Vue.extend({      template:`      <div>      <h2>我是标题</h2>      <p>我是内容,呵呵呵呵呵呵呵呵</p>      <cpn1></cpn1>      </div>      `,      components:{  //在父组件中注册子组件        cpn1:cpnC1      }    })    //  可以把Vue当成一个root组件		const app = new Vue({			el: "#app",			data: {				massage: "你好"			},      components:{        cpn2:cpnC2      }		})	</script></body>

七、组件注册语法糖

在上面注册组件的方式,可能会有些繁琐。

  • Vue为了简化这个过程,提供了注册的语法糖。
  • 主要是省去了调用Vue.extend()的步骤,而是可以直接使用一个对象来代替。

语法糖注册全局组件和局部组件:

<div id="app">  <cpn1></cpn1>  <cpn2></cpn2></div><body>  <script src="../js/vue.js"></script>  <script>    // 1.全局组件注册的语法糖    // 1.创建组件构造器    // const cpn1 = Vue.extend({    //   template:`    //   <div>    //   <h2>我是标题</h2>    //   <p>我是内容,红红火火恍恍惚惚</p>    //   </div>    //   `    // })    // 2.注册组件    Vue.component('cpn1', {      template: `      <div>      <h2>我是标题</h2>      <p>我是内容,红红火火恍恍惚惚</p>      </div>      `    })    // 注册局部组件的语法糖    const app = new Vue({      el: "#app",      data: {        massage: "你好"      },      components: {        'cpn2': {          template: `      <div>      <h2>我是标题</h2>      <p>我是内容,呵呵呵呵呵呵呵</p>      </div>      `        }      }    })  </script></body>

八、模板的分离写法

刚才,我们通过语法糖简化了Vue组件的注册过程,另外还有一个地方的写法比较麻烦,就是template模块写法。

如果我们能将其中的HTML分离出来写,然后挂载到对应的组件上,必然结构会变得非常清晰。

Vue提供了两种方案来定义HTML模块内容:

  • 使用

两万字Vue.js基础学习笔记的更多相关文章

  1. 两万字Vue.js基础学习笔记(二)

    Vue.js学习笔记(二) 4.模块化开发 ES6模块化的导入和导出 我们使用export指令导出了模块对外提供的接口,下面我们就可以通过import命令来加载对应的这个模块了 首先,我们需要在HTM ...

  2. handlebars.js基础学习笔记

    最近在帮学校做个课程网站,就有人推荐用jquery+ajax+handlebars做网站前端,刚接触发现挺高大上的,于是就把一些基础学习笔记记录下来啦. 1.引用文件: jquery.js文件下载:h ...

  3. Vue.js实战学习笔记(中)

    1.递归组件给组件设置name属性,组件就可以在它的模板内调用自己,但必须给一个条件来限制递归数量.<div id="app"> <child-component ...

  4. 从零开始学习Vue.js,学习笔记

    一.为什么学习vue.js methods 只有纯粹的数据逻辑,而不是去处理 DOM 事件细节. vue.js兼具angular.js和react的优点,并且剔除了他们的缺点 官网:http://cn ...

  5. vue.js初始学习笔记&vue-cli

    笔记一下: vue.js 安装,参考: http://www.cnblogs.com/wisewrong/p/6255817.html (vue-cli) http://www.cnblogs.com ...

  6. vue.js路由学习笔记

    <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title&g ...

  7. web前端——Vue.js基础学习

    近期项目的前端页面准备引入Vue.js,看了网上一些简介,及它和JQuery的对比,发现对于新入门的前端开发来说,Vue 其实也是比较适用的一个框架,其实用性不比JQuery差,感觉还挺有意思,于是研 ...

  8. vue.js路由学习笔记二

    <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title&g ...

  9. vue.js 源代码学习笔记 ----- 工具方法 lang

    /* @flow */ // Object.freeze 使得这个对象不能增加属性, 修改属性, 这样就保证了这个对象在任何时候都是空的 export const emptyObject = Obje ...

随机推荐

  1. BIO/NIO/ANO笔记

    一: netty服务器启动过程 serverBootstrap.bind(hostname, port)---> doBind(localAddress);--> 1.1: initAnd ...

  2. java后端知识点梳理——Spring

    开篇:感谢我是祖国的花朵,java3y,三太子敖丙等优秀博主!他们的文章为我学习java提供了莫大的帮助,膜拜大神! Spring的优点有哪些呢? Spring的依赖注入将对象之间的依赖关系交给了框架 ...

  3. 源码级别理解 Redis 持久化机制

    文章首发于公众号"蘑菇睡不着",欢迎来访~ 前言 大家都知道 Redis 是一个内存数据库,数据都存储在内存中,这也是 Redis 非常快的原因之一.虽然速度提上来了,但是如果数据 ...

  4. daily plan

    想了想自己留的坑有点多了,写个计划提醒自己 一些没做出来的题 csp-s模拟测试54 z csp-s模拟测试b层加餐 string 平衡树+并查集 因为某杰的**安排,没时间改了csp-s模拟测试47 ...

  5. Java知识复习(三)

    Set里的元素是不能重复的,那么用什么方法来区分重复与否呢? 是用==还是equals()? 它们有何区别?用contains来区分是否有重复的对象.还是都不用. 在比较时先调用hashCode方法, ...

  6. JMeter定时器种类+详细教程举例

    首先,我们先了解一下定时器的常见种类以及它的作用. 原文地址:https://www.cnblogs.com/istart/p/11184533.html 一.定时器种类+作用 上面是我截图的自己有道 ...

  7. Unity3D学习笔记1——绘制一个三角形

    目录 1. 绪论 2. 概述 3. 详论 3.1. 准备 3.2. 实现 3.3. 解析 3.3.1. 场景树对象 3.3.2. 绘制方法 4. 结果 1. 绪论 最近想学习一下Unity3d,无奈发 ...

  8. moment常用方法

    1.subtract方法,时间加减处理 console.log(moment().format("YYYY-MM-DD HH:mm:ss")); //当前时间 console.lo ...

  9. Java操作SQL数据库(JDBC)

    0.引入驱动jar包 使用jdbc进行具体操作前,需要引入相关数据库的jar包, 或者使用mave管理依赖 <!-- https://mvnrepository.com/artifact/mys ...

  10. JavaScript与服务端进行数据交互的方式

    XMLHttpRequest XHR是项古老的技术,不同的浏览器厂商对其实现方式不同,例如有些浏览器只支持onload事件处理器,有些只支持onreadystatechange事件处理器. 发送Get ...