SoC:关注度分离原则
Vue只关注视图层
HTML+CSS+JS: 视图:给用户看 刷新后台数据
尤雨溪 发布于2014年2月;
网络通信:axios
页面跳转:vue-router
状态管理:vuex
前段三要素 HTML结构+CSS(表现)+JavaScript(行为)
CSS预处理器
CSS 预处理器定义了一种新的语言,其基本思想是,用一种专门的编程语言,为CSS增加了一些编程的特性,将CSS作为目标生成文件,然后开发者就只要使用这种语言进行CSS的编码工作。转化成通俗易懂的话来说就是“用一种专门的编程语言,进行Web 页面样式设计,再通过编译器转化为正常的CSS文件,以供项目使用”。
常用的CSS预处理器有哪些
虚拟Dom:利用内存;
计算属性–>Vue特色
JavaScript框架
jQuery:大家熟知的JavaScript 框架,优点是简化了DOM操作,缺点是DOM操作太频繁,影响前端性能;在前端眼里使用它仅仅是为了兼容IE6、7、8;
Angular: Google 收购的前端框架,由一群Java程序员开发,其特点是将后台的 MVC模式搬到了前端并增加了模块化开发的理念,与微软合作,采用TypeScript语法开发;对后台程序员友好,对前端程序员不太友好;最大的缺点是版本迭代不合理(如:1代->2代,除了名字,基本就是两个东西;截止发表博客时已推出了 Angular6)
React: Facebook出品,一款高性能的」JS前端框架;特点是提出了新概念【虚拟DOM】用于减少真实DOM操作,在内存中模拟DOM 操作,有效的提升了前端渲染效率;缺点是使用复杂,因为需要额外学习—门【sX】语言;
vue :
一款渐进式JavaScript框架,所谓渐进式就是逐步实现新特性的意思,如实现模块化开发、路由、状态管理等新特性。其特点是综合了Angular(模块化)和React(虚拟 DOM)的优点;
Axios:
前端通信框架;因为 vue的边界很明确,就是为了处理DOM,所以并不具备通信能力,此时就需要额外使用一个通信框架与服务器交互;当然也可以直接选择使用jQuery 提供的AJAX通信功能;
后台开发
前端为主的MV*时代
此处的MV*模式如下:
为了降低前端开发复杂度,涌现了大量的前端框架,比如: Angu ls 、 React , Vue.js 、EmberJs等,这些框架总的原则是先按类型分层,比如Templates、Controllers、Models,然后再在层内做切分,如下图:
MVVM组成部分
【说明】IDEA可以安装Vue 的插件!
注意:Vue 不支持 IE8及以下版本,因为Vue使用了IE8无法模拟的ECMAScript5特性。但它支持所有兼容ECMAScript 5 的浏览器。
MVVM (Model-View-ViewModel)是一种软件架构设计模式,由微软WPF(用于替代WinForm,以前就是用这个技术开发桌面应用程序的)和Silverlight(类似于Java Applet,简单点说就是在浏览器上运行的 WPF)的架构师Ken Cooper和Ted Peters开发,是一种简化用户界面的事件驱动编程方式。由John Gossman(同样也是 WPF和Silverlight的架构师)于2005年在他的博客上发表。
MVVM源自于经典的MVC (Model-View-Controller)模式。MVVM的核心是ViewModel层,负责转换Model中的数据对象来让数据变得更容易管理和使用,其作用如下:
MVVM已经相当成熟了,主要运用但不仅仅在网络应用程序开发中。当下流行的MVVM框架有vue.js , Angulars等。
MVVM模式和MVC模式一样,主要目的是分离视图(View)和模型(Model),有几大好处
MVVM组成部分
开发版本
CDN:
第一个Vue程序
<div id="app">
{{message}}
div>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.min.js">script>
<script>
var vm = new Vue({
el:"#app",
//Model:数据
data:{
message:"hello,vue"
}
});
script>
<div id="app">
{{message}}
div>
缩写v-bind:title==:title
<span v-bind:title="message">
嘿嘿
span>
你看到的v-bind等被称为指令。指令带有前缀v-,以表示它们是Vue提供的特殊特性。可能你已经猜到了,它们会在渲染的DOM上应用特殊的响应式行为。在这里,该指令的意思是:“将这个元索节点的title特性和Vue 实例的message 属性保持—致”。
如果你再次打开浏览器的JavaScript 控制台,输入app.message = ‘新消息’,就会再一次看到这个绑定了title 特性的HTML已经进行了更新。
<div id="app">
<h1 v-if="ok">trueh1>//ok为真
<h1 v-else>Falseh1>
div>
<div id="app">
<h1 v-if="type==='A'">Ah1>
<h1 v-else-if="type==='B'">Bh1>
<h1 v-else>Ch1>
div>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.min.js">script>
<script>
var vm = new Vue({
el:"#app",
data: {
type: "A"
}
});
script>
<div id="app"> //index 下标
<li v-for="(item,index) in items">
{{item.message}}---{{index}}
li>
div>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.min.js">script>
<script>
var vm = new Vue({
el:"#app",
//Model:数据
data:{
items: [
{message: "狂神说Java"},
{message: "狂神说前端"},
{message: "狂神说运维"},
]
}
});
script>
v-on:事件=
缩写 v-on:事件= == @事件
<div id="app">
<button v-on:click="sayHi">Click mebutton>
div>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.min.js">script>
<script>
var vm = new Vue({
el:"#app",
//Model:数据
data:{
message: "狂神说Java"
},
methods:{ //方法必须写在Vue的methods对象中
sayHi: function () {
alert(this.message);
}
}
});
script>
Vue.js是一个MVVM框架,即数据双向绑定,即当数据发生变化的时候,视图也就发生变化,当视图发生变化的时候,数据也会跟着同步变化。这也算是 Vue.js 的精髓之处了。
值得注意的是,我们所说的数据双向绑定,一定是对于UI控件来说的,非UI控件不会涉及到数据双向绑定。单向数据绑定是使用状态管理工具的前提。如果我们使用vuex,那么数据流也是单项的,这时就会和双向数据绑定有冲突。
在vue.js中,如果使用vuex,实际上数据还是单向的,之所以说是数据双向绑定,这是用的UI控件来说,对于我们处理表单,Vue.js的双向数据绑定用起来就特别舒服了。即两者并不互斥,在全局性数据流使用单项,方便跟踪;局部性数据流使用双向,简单易操作。
你可以用v-model指令在表单,
及
元素上创建双向数据绑定。它会根据控件类型自动选取正确的方法来更新元索。尽管有些神奇,但v-model本质上不过是语法糖。它负责监听用户的输入事件以更新数据,并对一些极端场景进行―些特殊处理。
注意: v-model 会忽略所有表单元素的value,checked、selected特性的初始值而总是将Vue 实例的数据作为数据来源。你应该通过JavaScript在组件的data选项中声明初始值!
输入框
<div id="app">
输入框<input type="text" v-model="message">{{message}}
div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js">script>
<script>
var vm = new Vue({
el:"#app",
//Model:数据
data:{
message:""
}
});
script>
单选框
<input type="radio" value="男" v-model="sex">男
<input type="radio" value="女" v-model="sex">女
<p>
选中了谁:{{sex}}
p>
多选框
爱好:
<input type="checkbox" name="vehicle" value="Bike" v-model="loves">吃饭
<input type="checkbox" name="vehicle" value="Car1" v-model="loves">睡觉
<input type="checkbox" name="vehicle" value="Car2" v-model="loves">打豆豆
<input type="checkbox" name="vehicle" value="Car3" v-model="loves">旅游
<p>
<li v-for="love in loves">{{love}}li>
p>
下拉框
下拉框:
<select v-model="selected">
<option value="" disabled>--请选择--option>
<option>Aoption>
<option>Boption>
<option>Coption>
select>
<span>value:{{selected}}span>
注意:如果v-model表达式的初始值未能匹配任何选项,元素将被渲染为“未选中”状态。在 iOS 中,这会使用户无法选择第一个选项。因为这样的情况下,iOS不会触发change事件。因此,更推荐像上面这样提供—个值为空的禁用选项。
组件是可复用的 vue 实例,说白了就是一组可以重复使用的模板,跟JSTL的自定义标签、Thymeleaf的 th:fragment等框架有着异曲同工之妙。通常一个应用会以一棵嵌套的组件树的形式来组织:
<div id="app">
<shijie>shijie>
div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js">script>
<script>
//定义一个Vue组件component
Vue.component("shijie",{
template:'wuhuhahei >'
});
script>
<div id="app">
<shijie v-for="item in items" v-bind:qin="item">shijie>
div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js">script>
<script>
Vue.component("shijie",{
props:['qin'],
template:'{{qin}} >'
});
var vm = new Vue({
el:"#app",
//Model:数据
data:{
items:["Java","Linux","前端"]
}
});
script>
说明
Axios是一个开源的可以用在浏览器端和Nodes 的异步通信框架,她的主要作用就是实现 AJAX异步通信,其功能特点如下:
GitHub: https://github.com/axios/axios
中文文档:http://www.axios-js.com/
由于Vue.js 是一个视图层框架并且作者(尤雨溪)严格准守SoC(关注度分离原则),所以Vue.js并不包含AJAX的通信功能,为了解决通信问题,作者单独发了一个名为vue- resource的插件,不过在进入2.0版本以后停止了对该插件的维护并推荐了Axios框架。少用jQuery,因为它操作Dom太频繁!
官方文档:https://cn.vuejs.org/v2/guide/instance.html#生命周期图示
Vue 实例有一个完整的生命周期,也就是从开始创建、初始化数据、编译模板、挂载DOM、渲染→更新→渲染、卸载等一系列过程,我们称这是Vue 的生命周期。通俗说就是Vue 实例从创建到销毁的过程,就是生命周期。
在Vue的整个生命周期中,它提供了一系列的事件,可以让我们在事件触发时注册JS方法,可以让我们用自己注册的JS方法控制整个大局,在这些事件响应方法中的this直接指向的是Vue 的实例。
<div id="vue">
<div>{{info.name}}div>
<div>{{info.address.city}}div>
div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js">script>
<script src="http://unpkg.com/axios/dist/axios.min.js">script>
<script type="text/javascript">
var vm = new Vue({
el:'#vue',
//data: 属性
//data()函数
data(){
return{
//请求的返回参数格式,必须和json字符串一样 可以不写
info:{
name: null,
address: {
street:null,
city:null,
country:null
}
}
}
},
mounted(){ //钩子函数 链式编程 => ES6新特性 response变量
axios.get('../data.json').then(response=>(this.info=response.data))
}
})
script>
{
"name" :"狂神说Java" ,
"url" :"https: //blog.kuangstudy.com",
"page" : 1,
"isNonProfit" : true,
"address" : {
"street" :"含光门",
"city" :"陕西西安",
"country" : "中国"
},
"links" : [
{
"name" : "bilibili",
"url" : "https://space.bilibili.com/95256449"
},
{
"name" : "狂神说java",
"url" : "https://blog.kuangstudy.com"
},
{
"name" : "百度",
"url" : "https://www.baidu.com/"
}
]
}
如果网速慢,而该标签内容是变量没有请求响应回来的时候,页面上先不显示该标签(vue给该标签加了css样式),当响应回来的时候改标签默认将css样式去除。此指令可以解决使用插值表达式页面闪烁问题
将该指令加在html标签中时,可以在该文件中加style属性为display:none,例子如下:
<style>
[v-clock]{
display: none;
}
style>
<div>{{info.name}}div>
<div>{{info.address.city}}div>
计算属性的重点突出在属性两个字上(属性是名词),首先它是个属性其次这个属性有计算的能力(计算是动词),这里的计算就是个函数;简单点说,它就是一个能够将计算结果缓存起来的属性〔将行为转化成了静养态的属性),仅此而已;可以想象为缓存!
<div id="vue" v-clock>
<p>{{currentTime1()}}p>
<p>{{currentTime2}}p>
div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js">script>
<script src="http://unpkg.com/axios/dist/axios.min.js">script>
<script type="text/javascript">
var vm = new Vue({
el:'#vue',
data:{
message: "hello,ShiYu"
},
methods:{
currentTime1:function () {
return Date.now(); //返回一个时间戳
}
},
computed: { //计算属性 methods computed 重名之后,只会调用methods方法
currentTime2: function () {
this.message;//这个值被刷新的时候,currentTime2会被重新复制
return Date.now();//返回一个时间戳
}
}
});
script>
结论:
调用方法时,每次都需要进行计算,既然有计算过程则必定产生系统开销,那如果这个结果是不经常变化的呢?此时就可以考虑将这个结果缓存起来,采用计算属性可以很方便的低到这一点,计算属性的主要特性就是为了将不经常变化的计算结果进行缓存,以节约我们的系统开销;
<div id="app">
<todo>
<todo-title slot="todo-title" :title="title">todo-title>
<todo-items slot="todo-items" v-for="item in todoItems" :item="item">todo-items>
todo>
div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js">script>
<script>
//slot:插槽
Vue.component("todo",{
template: '\
\
\
\
\
'
});
Vue.component("todo-title",{
props: ['title'],
template: '{{title}}>'
});
Vue.component("todo-items",{
props: ['item'],
template: '{{item}}>'
});
var vm = new Vue({
el:"#app",
//Model:数据
data:{
title: "秦老师系列课程",
todoItems: ['狂神说Java','狂神说前端','狂神说Linux']
}
});
script>
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kCg2wEby-1619279901171)(Vue.assets/image-20201212111943023.png)]
<div id="app">
<todo>
<todo-title slot="todo-title" :title="title">todo-title>
<todo-items slot="todo-items" v-for="(item,index) in todoItems" :item="item"
v-bind:index="index" v-on:remove="removeItems" :key="index">todo-items>
todo>
div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js">script>
<script>
//slot:插槽
Vue.component("todo",{
template: '\
\
\
\
\
'
});
Vue.component("todo-title",{
props: ['title'],
template: '{{title}}'
});
Vue.component("todo-items",{
props: ['item','index'],
//只能绑定当前主键的方法
template: '{{index}}---{{item}} ',
methods: {
remove: function (index) {
//this.$emit 自定义事件分发
this.$emit('remove',index);
}
}
});
var vm = new Vue({
el:"#app",
//Model:数据
data:{
title: "秦老师系列课程",
todoItems: ['狂神说Java','狂神说前端','狂神说Linux']
},
methods: {
removeItems: function (index) {
console.log("删除了"+this.todoItems[index] + "OK");
this.todoItems.splice(index,1); //一次删除一个元素
}
}
});
script>
其实不只是vue,react中在执行列表渲染时也会要求给每个组件添加上key这个属性。
要解释key的作用,不得不先介绍一下虚拟DOM的Diff算法了。
我们知道,vue和react都实现了一套虚拟DOM,使我们可以不直接操作DOM元素,只操作数据便可以重新渲染页面。而隐藏在背后的原理便是其高效的Diff算法。
vue和react的虚拟DOM的Diff算法大致相同,其核心是基于两个简单的假设:
1. 两个相同的组件产生类似的DOM结构,不同的组件产生不同的DOM结构。
2. 同一层级的一组节点,他们可以通过唯一的id进行区分。
基于以上这两点假设,使得虚拟DOM的Diff算法的复杂度从O(n^3)降到了O(n)。
这里我们借用React’s diff algorithm中的一张图来简单说明一下:
当页面的数据发生变化时,Diff算法只会比较同一层级的节点:
如果节点类型不同,直接干掉前面的节点,再创建并插入新的节点,不会再比较这个节点以后的子节点了。
如果节点类型相同,则会重新设置该节点的属性,从而实现节点的更新。
当某一层有很多相同的节点时,也就是列表节点时,Diff算法的更新过程默认情况下也是遵循以上原则。
比如一下这个情况:
我们希望可以在B和C之间加一个F,Diff算法默认执行起来是这样的:
即把C更新成F,D更新成C,E更新成D,最后再插入E,是不是很没有效率?
所以我们需要使用key来给每个节点做一个唯一标识,Diff算法就可以正确的识别此节点,找到正确的位置区插入新的节点。
所以一句话,**key的作用主要是为了高效的更新虚拟DOM**。另外vue中在使用相同标签名元素的过渡切换时,也会使用到key属性,其目的也是为了让vue可以区分它们,
否则vue只会替换其内部属性而不会触发过渡效果。
链接:https://www.jianshu.com/p/0044532e4a93
核心︰数据驱动,组件化
优点∶借鉴了AngulaJS的模块化开发和React 的虚拟Dom,虚拟Dom就是把Dom操作放到内存中执行;
常用的属性:. v-if
v-else-if
v-else
v-for
v-on绑定事件,简写@. v-model 数据双向绑定
v-bind 给组件绑定参数,简写:
组件化:
遵循SoC关注度分离原则,Vue是纯粹的视图框架,并不包含,比如Ajax之类的通信功能,为了解决通信问题,我们需要使用Axios框架做异步通信;
Vue的开发都是要基于NodeJS,实际开发采用vue-cli脚手架开发,vue-router路由,vuex做状态管理; Vue UI,界面我们一般使用ElementUI(饿了么出品),或者ICE(阿里巴巴出品!)来快速搭建前端项目~
vue-cli官方提供的一个脚手架,用于快速生成一个vue的项目模板;
预先定好的目录结构及基础代码,就好比咱们在创建Maven项目时可以选择创建一个骨架项目,这个骨架项目就是脚手架,我们的开发更加的快速;
主要的功能:
Node.js:http://nodejs.cn/download
安装就无脑下一步就好,安装在自己的环境目录下
Git:https://git-scm.com/downloads
镜像:https://npm.taobao.org/mirrors/git-for-windows/
确认node.js安装成功
这个npm就是一个软件包安装工具,和linux下的apt软件安装差不多
这样子的话,下载会快很多
# -g 就是全局安装
npm install cnpm -g
# 或使用如下语句解决npm速度慢的问题 --registr=https://registry.npm.taobao.org 需要在安装的时候加上 每次都需要
bom install --registr=https://registry.npm.taobao.org
安装的过程有点慢~,耐心等待!虽然安装了cnpm,尽量少用,会出现下载完不能使用的问题
安装的位置C:\Users\86177\AppData\Roaming\npm
cnpm install vue-cli -g
# 测试是否安装成功
# 查看可以基于那些模板创建vue应用程序,通常选择webpack
vue list
创建一个Vue项目,随便创建一个目录
创建一个基于webpack模板vue应用程序
# 这里的myvue是项目名称,根据需求取名 去所要创建的目录下输入命令
vue init webpack myvue
一路选择no即可;
说明
cd myvue
npm install
npm run dev
ctrl+c停止
本质上,webpack是一个现代JavaScript应用程序的静态模块打包器(module bundler)。当webpack 处理应用程序时,它会递归地构建一个依赖关系图(dependency graph),其中包含应用程序需要的每个模块,然后将所有这些模块打包成一个或多个bundle.
Webpack 是当下最热门的前端资源模块化管理和打包工具,它可以将许多松散耦合的模块按照依赖和规则打包成符合生产环境部署的前端资源。还可以将按需加载的模块进行代码分离,等到实际需要时再异步加载。通过loader转换,任何形式的资源都可以当做模块,比如CommonsJS、AMD、ES6、cSs、JSON、CoffeeScript、 LESS等;
伴随着移动互联网的大潮,当今越来越多的网站已经从网页模式进化到了WebApp模式。它们运行在现代浏览器里,使用HTML5、CSS3、ES6等新的技术来开发丰富的功能,网页已经不仅仅是完成浏览器的基本需求; WebApp通常是一个SPA (单页面应用),每一个视图通过异步的方式加载,这导致页面初始化和使用过程中会加载越来越多的JS代码,这给前端的开发流程和资源组织带来了巨大挑战。
前端开发和其他开发工作的主要区别,首先是前端基于多语言、多层次的编码和组织工作,其次前端产品的交付是基于浏览器的,这些资源是通过增量加载的方式运行到浏览器端,如何在开发环境组织好这些碎片化的代码和资源,并且保证他们在浏览器端快速、优雅的加载和更新,就需要一个模块化系统,这个理想中的模块化系统是前端工程师多年来一直探索的难题。
WebPack是一款模块加载器兼打包工具,它能把各种资源,如JS、JSX、ES6、SASS、LESS.图片等都作为模块来处理和使用。可以想象成吧es6的代码打包成es5的。
#打包工具
npm install webpack -g
#客户端
npm install webpack-cli -g
测试安装成功:
webpack -v
webpack-cli -v
创建webpack.config.js配置文件
module.exports = {
entry:"",
output:{
path:"",
filename:""
},
module:{
loaders:[
{test:/\.js$/,loader:""}
]
},
plugins:{},
resolve:{},
watch:true
}
直接运行webpack命令打包
创建项目
创建一个名为modules的目录,用于放置JS模块等资源文件
在modules下创建模块文件,如hello.js,用于编写JS模块相关代码
//暴露一个方法:sayHi
exports.sayHi = function(){
document.write("HelloWebPack");
}
在modules下创建一个名为main.js的入口文件,用于打包时设置entry属性
// require导入一个模块,就可以调用这个模块中的方法了
var hello = require("./hello");
hello.sayHi( ) ;
在项目目录下创建webpack.config.js 配置文件,使用webpack 命令打包
webpack -watch //热部署 实时监听改变
Vue Router是 Vue.js官方的路由管理器。它和Vue.js 的核心深度集成,让构建单页面应用变得易如反掌。包含的功能有:
npm install vue-routr --save-dev
hash:路径带#符号,如http://localhost/#/login
history:路径不带# 符号,如http://localhost/login
通过mode设置
export default new Router({
mode:'history',
})
我们采用实战教学模式并结合ElementuI
组件库,将所需知识点应用到实际中,以最快速度带领大家掌握Vue的使用;
注意:命令行都需要使用管理员模式运行
1、穿件一个名为hello-vue的工程 vue init webpack hello-vue
2、 安转依赖,需要安装vue-router、element-ui、sass-loader、node-sass四个插件
#进入工程目录
cd hello-vue
#安装 vue-router
npm install vue-router --save-dev
#交装element- ui
npm i element-ui -s
#安装依赖
npm install
#安装SASS 加载器
cnpm install sass-loader node-sass --save-dev
#启动测试
npm run dev
3、Npm命令解释:
具体代码在hello-vue
1、name+params
个人信息
router 的 index.js 里面接收参数
path: '/user/profile/:id',
显示
{{$route.params.id}}
个人信息
2、props
个人信息
router 的 index.js 里面接收参数
path: '/user/profile/:id',
显示
{{id}}
个人信息
回到首页
{
path: '/goHome',
redirect: '/main'
},
//使用 vue-router 路由到指定页面,该方式称之为编程式导航
this.$router.push("/main");
所有的钩子函数在上面Axios异步通信下的图中
beforeRouteEnter :在进入路由前执行
beforeRouteLeave :在离开路由前执行
参数说明
to:路由将要跳转的路径信息
from:路径跳转前的路径信息
next:路由的控制参数
next()跳入下一个页面
next(’/path’)改变路由的跳转方向,使其跳到另一个路由. next(false)返回原来的页面
next((vm)=>{})仅在beforeRouteEnter 中可用,vm是组件实例
1、 安装Axios cnpm install axios -s 还是要少用cnpm
2、main.js引用Axios
import axios from 'axios'
import VueAxios from 'vue-axios'
Vue.use(VueAxios, axios) // 这里顺序错了会报错 不明白为什么