vue 相关知识
前端知识体系
前端三要素
CSS层叠样式表是一门标记语言,并不是编程语言,不能自定义变量,引用等。导致它语法不够强大,如:无法嵌套书写,导致模块化开发需要书写很多重复的选择器,没有变量和合理的样式复用机制,使得逻辑上相关的属性值必须以字面量的形式重复输出,导致难以维护。
为了解决上述的问题,可以使用CSS预处理器工具,提供CSS缺失的样式层复用机制,减少代码冗余,提高样式代码的可维护性,提高开发效率。
CSS预处理器:
它是用一种专门的编程语言,进行Web样式设计,再通过编译器转化为CSS文件,以供项目使用。常用的CSS预处理器:
SASS
:基于Ruby,通过服务端处理,功能强大,解析效率高。但需要学习Ruby语言,上手难度较高
LESS
:基于Nodejs,通过客户端处理,使用简单,但解析效率低于SASS,但能够满足开发使用。
JavaScript框架
jQuery、Angular、React、Vue、Axios
UI框架
Ant-Design、ElementUI、iview、ice、Bootstrap、AmazeUI
javaScript构建工具
Babel、WebPack
vue
概述
vue (发音为 /vjuː/,类似 view) 是一款用于构建用户界面的 JavaScript 框架。它基于标准 HTML、CSS 和 JavaScript 构建,并提供了一套声明式的、组件化的编程模型,帮助程序员高效地开发用户界面。它的核心库只关注视图层。
MVVM模式
Model
:模型层,在这里表示JavaScript对象
View
:视图层,表示DOM(HTML操作的元素)
ViewModel
:连接视图和数据的中间键,Vue.js就是MVVM中的ViewModel层的实现者
在MVVM架构中不允许数据和视图直接通信,只能通过ViewModel来实现,而ViewModel就是定义一个Observer观察者。它能够观察到数据的变化,并对视图对应的内容进行更新,也能够监听到视图的变化并作出相应的"通知"。
MVV模式和MVC模式一样,主要的目的是分离视图(view)和模型(model)
主要有下面的好处:
低耦合
:视图(View)可以独立于Model变化和修改,一个ViewModel可以绑定到不同的View上,当View变化的时候Model可以不变,当Model变化的时候View也可以不变。
可复用
:可以把一些视图逻辑放在一个ViewModel中,让很多View重用
独立开发
:开发人员可以专注于业务逻辑和数据的开发(ViewModel),设计人员可以专注于页面设计和测试
第一个vue程序
使用工具:IDEA
vue 引用地址:
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
实例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<!--1、导入Vue.js-->
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
</head>
<body>
<!--view -->
<div id="app">
{{message}}
</div>
<!--2、创建Vue对象-->
<script>
var vm = new Vue({
//绑定元素
el:"#app",
// model
data:{
message:"Hello!"
}
});
</script>
</body>
</html>
vue组件
注册组件
**目标:**注册组件khan(Vue.component())
创建思路:
创建组件khan,由于由于Vue和组件是同级的,所以不能实现数据的传递,这时我们需要一个中间件来实现target绑定数据,组件中使用props来接收target数据。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<!--1、导入Vue.js-->
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
</head>
<body>
<!--view -->
<div id="app">
<!--组件,传递给组件中的值:props-->
<khan v-for="add in address" v-bind:target="add"></khan>
</div>
<!--2、创建Vue对象-->
<script>
<!-- 定义一个Vue组件component-->
Vue.component("khan",{
props:["target"],
template:"<li>{{target}}</li>"
})
var vm = new Vue({
//绑定元素
el:"#app",
// model
data:{
address:["洛杉矶", "巴厘岛", "印第安", "重庆"]
}
});
</script>
</body>
</html>
Axios异步通信
Axios是一个开源的可以用在浏览器端和NodeJS的异步通信框架, 它的作用就是实现Ajax异步通信。由于Vue.js是一个视图层框架,所以Vue.js并不包含Ajax的通信功能,使用Axios能够解决通信问题。
特点
- 从浏览器中创建XMLHttpRequests
- node.js创建http请求
- 支持Promise API[JS中链式编程]
- 拦截请求和响应数据
- 取消请求
- 自动转换JSON数据
- 客户端支持防御XSRF(跨域请求伪造)
中文文档:http://www.axios-js.com/zh-cn/docs/
示例
data.json
{
"name": "Alex",
"url": "https://blog.csdn.net/xry12354?type=blog",
"page": 1,
"isNonProfit": true,
"address": {
"street": "龙泉",
"provence": "haven",
"country": "亚力"
},
"links": [{
"name": "khan",
"url": "https://blog.csdn.net/xry12354?type=blog"
},
{
"name": "louis",
"url": "https://blog.csdn.net/xry12354?type=blog"
}]
}
demo03.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
<script type="text/javascript"></script>
</head>
<!--解决页面闪烁的问题-->
<style>
[v-cloak]{
display: none;
}
</style>
<body>
<div id="app" v-cloak>
<div>{{info.name}}</div>
<div>{{info.address.street}}</div>
<a v-bind:href="info.url">点击到达目的地</a>
</div>
<script>
var _this = this;
new Vue({
el:"#app",
data(){
return{
//请求的返回参数格式必须和json字符串一样
info:{
name:null,
url:null,
address:{
street:null,
provence: null,
country: null
}
}
}
},
// 钩子函数
mounted(){
const _this = this;
// axios.get("../resources/data.json").then(resp=>(this.info=resp.data));
axios.get("../resources/data.json").then(function(resp){
console.log(resp.data)
_this.info=resp.data;
console.log(_this.info);
})
}
});
</script>
</body>
</html>
计算属性(computed)
计算属性的重点突出在属性上,首先它是属性,其次这个属性有计算的能力,这里的计算是一个函数;简单的说,他就是一个能够将计算结果缓存起来的属性(将行为转化为静态的属性),可以将它想象为缓存,可以节省浏览器成本。即虚拟DOM。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
</head>
<body>
<div id="app">
<div>{{currentTime()}}</div>
<div>{{currentTimeA}}</div>
</div>
<script>
new Vue({
el:"#app",
data(){
return{
message:"Hello Vue!!"
}
},
methods:{
currentTime(){
return Date.now();//返回一个时间戳
}
},
//计算属性,但是有一个前提就是methods中的方法名和computed中的不能同名,重名之后只会调用methods中的方法。也可以使用调用属性的方法
computed:{
currentTimeA: function() {
return Date.now();
}
}
});
</script>
</body>
</html>
插槽(slot)
在Vue.js中我们使用<slot>元素作为承载分发内容的出口,可以应用在组合组件的场景中。插槽用于决定将所携带的内容,插入到指定的位置,使模板分块,具有模块化的特质和更大的重用性。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
<script type="text/javascript"></script>
</head>
<!--解决页面闪烁的问题-->
<style>
[v-cloak]{
display: none;
}
</style>
<body>
<div id="app" v-cloak>
<p>数据列表</p>
<!--如果使用v-for来遍历数据不好遍历的情况-->
<!-- <ul>-->
<!-- <li>Java</li>-->
<!-- <li>Linux</li>-->
<!-- <li>Html</li>-->
<!-- <li>Python</li>-->
<!-- </ul>-->
<todo>
<todo-title slot="todo-title" :title="title"></todo-title>
<todo-items slot="todo-items" v-for="it in todoItems" :item="it"></todo-items>
</todo>
</div>
<script>
//slot插槽
Vue.component("todo",{
// template: '<div>\
// <slot></slot>\
// <ul>\
// <slot></slot>\
// </ul>\
// </div>'
template: '<div>\
<slot name="todo-title"></slot>\
<ul>\
<slot name="todo-items"></slot>\
</ul>\
</div>'
});
Vue.component("todo-title", {
// template: '<div>标签</div>'
props:['title'],
template:'<div>{{title}}</div>'
});
Vue.component("todo-items", {
// template: '<li>java</li>'
props:['item'],
template:'<li>{{item}}</li>'
})
new Vue({
el:"#app",
data:{
title:'Londen',
todoItems:['khan', 'louis', 'Alex']
}
});
</script>
</body>
</html>
自定义事件内容分发
通过上面插槽实例中,删除操作要在组件中完成,即只能调用组件自身的方法,但是很多时候我们需要去调用Vue对象中的methods,这时就涉及到了参数传递与事件分发,Vue为我们提供了自定义事件的功能,能够帮助我们解决上述问题,使用this.$emit(“自定义事件名”,参数)。
javaScript:splice(start[, deleteCount[, item1[, item2[, ...]]]])
方法的参数是从数组 start 索引开始,删除 deleteCount 个元素,返回删除元素组成的数组。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
<script type="text/javascript"></script>
</head>
<body>
<div id="app">
<test>
<slot-title slot="slot-title" :title="head"></slot-title>
<slot-content slot="slot-content" v-for="(item, index) in content"
:content="item" :index="index" v-on:eli="eliminate(index)" :key="index"></slot-content>
</test>
</div>
<script>
Vue.component("test",{
template:'<div>' +
'<slot name="slot-title"></slot>' +
'<ul>' +
'<slot name="slot-content"></slot>' +
'</ul>' +
'</div>'
});
//准备在上面需要的数据,有两个插槽,也就是两份数据
Vue.component("slot-title",{
props:["title"],
template: "<p>{{title}}</p>"
});
Vue.component("slot-content",{
props:["content", "index"],
//只能绑定当前的组件的方法
template:'<li>{{index}}---{{content}} <button @click="remove">删除</button></li>',
methods:{
remove:function(index){
// alert("111")
//使用自定义, this.$emit()里面有两个参数,第一个是函数,第二个是要传递的参数
this.$emit('eli', index);
}
}
})
new Vue({
el:"#app",
data:{
head:"学而思",
content:["K","J","Z"],
},
methods: {
// eliminate:function (index){
// // alert("111")
// this.content.splice(index, 1);//一次删除一个元素
// console.log("元素" + this.content[index] + "删除成功!!")
// }
eliminate:function (index) {
this.content.splice(index, 1);//一次删除一个元素
console.log("元素" + this.content[index] + "删除成功!!")
}
}
})
</script>
</body>
</html>