准备
MVC&MVVM
- MVC
-
Model(模型)表示应用程序核心(如数据库)。
-
View(视图)显示效果(HTML页面)。
-
Controller(控制器)处理输入(业务逻辑)。
-
- MVVM
- 它本质上就是MVC 的改进版。MVVM 就是将其中的View 的状态和行为抽象化,让我们将视图 UI 和业务逻辑分开。当然这些事 ViewModel 已经帮我们做了,它可以取出 Model 的数据同时帮忙处理 View 中由于需要展示内容而涉及的业务逻辑。
-
低耦合。视图(View)可以独立于Model变化和修改,一个ViewModel可以绑定到不同的"View"上,当View变化的时候Model可以不变,当Model变化的时候View也可以不变。
-
可重用性。你可以把一些视图逻辑放在一个ViewModel里面,让很多view重用这段视图逻辑。
-
独立开发。开发人员可以专注于业务逻辑和数据的开发(ViewModel),设计人员可以专注于页面设计,使用Expression Blend可以很容易设计界面并生成xaml代码。
-
可测试。界面素来是比较难于测试的,而现在测试可以针对ViewModel来写。
安装环境
- 在搭建vue的开发环境之前,一定一定要先下载node.js,
- vue的运行是要依赖于node的npm的管理工具来实现,node可以在官网或者中文网里面下载,根据自己的电脑选择是32还是64 ,网址:link.
- 下载好node之后,打开docs管理工具,先看看node安装成功了没有,输入 node -v ,回车,会输出node的版本号,
- 全局安装脚手架:(1) npm install -g @vue/cli
(2) yarn global add @vue/cli - 如果版本过旧卸载:npm uninstall vue-cli -g
创建项目
vue create 项目名
( ) Babel
( ) TypeScript // 语法
( ) Progressive Web App (PWA) Support // PWA
( ) Router // 路由
(*) Vuex // store
( ) CSS Pre-processors // 预编译
( ) Linter / Formatter // 格式化代码
( ) Unit Testing
( ) E2E Testing
//提示: Babel, Router, Vuex, CSS Pre-processors, Linter 选中
- 使用图形化界面 vue ui 图形化数据
- yarn serve 启动项目
- yarn build 打包项目
(以上三个不可同时执行) - vscode 代码检测设置
// 文件 ~ 首选项 ~ 设置 ~ 工作区
{
"editor.formatOnSave": false,
"eslint.autoFixOnSave": true,
"eslint.validate": [
"javascript",{
"language": "vue",
"autoFix": true
},
"html",
"vue"
]
}
//vscode 加载插件 ESLint // 代码检测工具
ESLint规范,ESLint 是用来检查我们写的 JavaScript 代码是否满足指定规则的静态代码检查工具。通过用 ESLint 来检查一些规则,我们可以:
1.统一代码风格规则,如:代码缩进用几个空格;是否用驼峰命名法来命名变量和函数名等。
减少错误, 如:相等比较必须用 === ,变量在使用前必须被声明,在条件语句中不能使用赋值语句等。
2.提高代码质量,如:函数最多有多少条件分支;最多有几个参数,代码块最多能嵌套多少层等。
其他。如: 禁用 alert。这可以提高用户体验,因为 alert 框的外观不是那么好看,而且往往与网站的风格不搭,一般都会自定义 alert 框。
3.是都建立单元测试代码,可以不建立
- set up unit tests 单元测试
- setup e2e tests with nightwatch e2e测试
生命周期
beforeCreate( 创建前 )
在实例初始化之后,数据观测和事件配置之前被调用,此时组件的选项对象还未创建,el 和 data 并未初始化,因此无法访问methods, data, computed等上的方法和数据。
vue在beforecreate时期是获取不到data中的 数据的
但是通过一些方法可以实现在beforecreate时获取到data中的数据
暂时想到两种放发可以实现,vue在beforecreate时获得data中的数据
//1、异步获取即:通过 $this.$nextTick或者settimeout,这连dom都可以拿出来
beforeCreate() {
this.$nextTick(function() {
console.log(this.属性名);
})
}
//2、同步获取:在beforeCreate之前,所有的iptions都会先存到vm.$options中,
// 也就是说使用this.$options.data就行了
created ( 创建后 )
实例已经创建完成之后被调用,在这一步,实例已完成以下配置:数据观测、属性和方法的运算,watch/event事件回调,完成了data 数据的初始化,el没有。 然而,挂在阶段还没有开始, $el属性目前不可见,这是一个常用的生命周期,因为你可以调用methods中的方法,改变data中的数据,并且修改可以通过vue的响应式绑定体现在页面上,,获取computed中的计算属性等等
beforeMount
挂在开始之前被调用,相关的render函数首次被调用(虚拟DOM),实例已完成以下的配置: 编译模板,把data里面的数据和模板生成html,完成了el和data 初始化,注意此时还没有挂在html到页面上。
mounted
挂在完成,也就是模板中的HTML渲染到HTML页面中,此时一般可以做一些ajax操作,mounted只会执行一次。
beforeUpdate
在数据更新之前被调用,发生在虚拟DOM重新渲染和打补丁之前,可以在该钩子中进一步地更改状态,不会触发附加地重渲染过程
updated(更新后)
在由于数据更改导致地虚拟DOM重新渲染和打补丁只会调用,调用时,组件DOM已经更新,所以可以执行依赖于DOM的操作,然后在大多是情况下,应该避免在此期间更改状态,因为这可能会导致更新无限循环,该钩子在服务器端渲染期间不被调用
beforeDestroy(销毁前)
在实例销毁之前调用,实例仍然完全可用,
这一步还可以用this来获取实例,
一般在这一步做一些重置的操作,比如清除掉组件中的定时器 和 监听的dom事件
destroyed(销毁后)
在实例销毁之后调用,调用后,所以的事件监听器会被移出,所有的子实例也会被销毁,该钩子在服务器端渲染期间不被调用
html(template)—>js---->style三部分内容
语法糖
data:存储数据,可以进行简单运算
methods:存储方法
页面绑定动态数据用{{}}
v-bind
绑定属性简写就是一个冒号 如
data{
id:12
}
<p :id="id">123</>
v-html
动态绑定DOM 元素
data{
con:"<span>123</span>"
}
//html中 <p v-html="con"></p>
v-on
简写@
单击事件:v-on:click=“方法” @click=“方法”(简写)
双击事件:v-on:dblclick=“方法” @dblclick=“方法”(简写)
data:{
x:0,
y:0
}
updataXY(event){
console.log(event) //js鼠标事件默认的
this.x = event.offsetX;
this.y = event.offsetY;
}
//HTML渲染:
<div id="canvas" @mousemove="updataXY">
{{x}}-----{{y}}
</div>
阻止冒泡:
data:{
x:0,
y:0
}
updataXY(event){
console.log(event) //js鼠标事件默认的
this.x = event.offsetX;
this.y = event.offsetY;
}
updataStop(evevt){
event.stopPropagation();
}
HTML渲染:
方法一:
<div id="canvas" @mousemove="updataXY">
{{x}}-----{{y}}
<span @mousemove="updataStop">移到我这里不会改变xy坐标</span>
</div>
方法二:
<div id="canvas" @mousemove="updataXY">
{{x}}-----{{y}}
<span @mousemove.stop="">移到我这里不会改变xy坐标</span> //vue中加stop修饰符即可阻止冒泡
</div>
--------------------------------------------------
阻止默认行为:
<a href="http://www.baidu.com" @click.prevent="">百度</a>
--------------------------------------------------
键盘事件:
changeName(){
console.log("你正在输入名字")
}
<input type="text" @keyup="changeName">
<input type="text" @keyup.enter="changeName">
<input type="text" @keydown="changeName">
其他键盘事件类似,用法一致
数据双向绑定:
data:{
name:""
}
<input type="text" v-model="name" ref="name">
补充一个知识点:获取vue获取input的value的方法—>this.$refs.name.value;
计算属性:
data:{
a:0,
b:0,
age:10
}
methods:{
addA(){
console.log("add to a")
return this.a+this.age;
}
addB(){
console.log("add to B")
return this.b+this.age;
}
}
法一:用方法实现这个功能
<button @click="a++">Add to A</button>
<button @click="b++">Add to A</button>
<p>A-{{a}}</p>
<p>A-{{b}}</p>
<p>Age-A={{addA()}}</p>
<p>Age-B={{addB()}}</p>
法二:用计算属性实现
computed:{
addA(){
console.log("add to a")
return this.a+this.age;
}
addB(){
console.log("add to B")
return this.b+this.age;
}
}
<button @click="a++">Add to A</button>
<button @click="b++">Add to A</button>
<p>A-{{a}}</p>
<p>A-{{b}}</p>
<p>Age-A={{addA}}</p>
<p>Age-B={{addB}}</p>
其他
动态css
data:{
changeColor:false
}
<h1 @click="changeColor!=changeColor" :class="{changeColor:changeColor}">
<span>你好</span>
</h1>
<style>
.changeColor span{
background:#f2f1f1;
}
</style>
v-if指令(后面可以跟v-else-if v-else)
v-show指令、v-for指令数组遍历数组、对象
引入组件
import TabImg from '../components/TabImg.vue'
components: {
TabImg,
},
组件css作用域 scoped限定
组件预处理器
组件传值(父组件–>子组件(props)/子组件—>父组件(自定义事件))
需要用的数据放置父组件的data里面
假定在app.vue
data:{
list:[
{name:"bob",age:18}
{name:"wow",age:19}
{name:"pop",age:20}
]
}
<header><header>
<content :list="list"></content>
<footer><footer>
在content组件内props接收
法一: props[“list”]
法二(官方推荐):
props{
list:{
type:Array
required:true
},
}
法三:vuex状态管理仓库link.
传值:string、number、boolean (单个变)
传引用:array、object (整个变)
子—>父
changeTitle(){
this.$emit("titleChange","子到父传东西")
}
//父组件@titleChange="方法名($event)"
methods:{
//做的事情
方法名(形参){
//做什么事情
}
}
路由:(写法routes数组里面包着对象)
import 自定义名字 from "组件路径"
const router = new VueRouter ({
model:"history",
routes:[
{
pateh:"xxx",
meta:{单页面配置标题}, //---->该字段也可以校验路由
components:{组件} //---->该方法component: resolve => require(['组件路径'], resolve)路由懒加载(不用import组件了)
},
]
})
axios
axios 是一个基于Promise 用于浏览器和 nodejs 的 HTTP 客户端,本质上也是对原生XHR的封装,只不过它是Promise的实现版本,符合最新的ES规范,有以下特点:
- 从浏览器中创建 XMLHttpRequests
- 从 node.js 创建 http 请求
- 支持 Promise API
- 拦截请求和响应
- 转换请求数据和响应数据
- 取消请求
- 自动转换 JSON 数据
- 客户端支持防御 XSRF
作者:web小哥MrYang
组件传值
1、父传子
子组件的代码:
<template>
<div id="container">
{{msg}}
</div>
</template>
<script>
export default {
data() {
return {};
},
props:{
msg: String
}
};
</script>
父组件的代码:
<template>
<div id="container">
<input type="text" v-model="text" @change="dataChange">
<Child :msg="text"></Child>
</div>
</template>
<script>
import Child from "@/components/Child";
export default {
data() {
return {
text: "父组件的值"
};
},
methods: {
dataChange(data){
this.msg = data
}
},
components: {
Child
}
};
</script>
父传子的实现方式就是通过props属性,子组件通过props属性接收从父组件传过来的值,而父组件传值的时候使用 v-bind 将子组件中预留的变量名绑定为data里面的数据即可
2、子传父
子组件代码:
<template>
<div id="container">
<input type="text" v-model="msg">
<button @click="setData">传递到父组件</button>
</div>
</template>
<script>
export default {
data() {
return {
msg: "传递给父组件的值"
};
},
methods: {
setData() {
this.$emit("getData", this.msg);
}
}
};
</script>
父组件代码:
<template>
<div id="container">
<Child @getData="getData"></Child>
<p>{{msg}}</p>
</div>
</template>
<script>
import Child from "@/components/Child";
export default {
data() {
return {
msg: "父组件默认值"
};
},
methods: {
getData(data) {
this.msg = data;
}
},
components: {
Child
}
};
</script>
<style scoped>
</style>
子传父的实现
兄弟传参
链接: 兄弟传参.
vue打包原理
-
对于assets目录下的文件,会分类放入不同的文件夹下。
-
对于static目录下的文件,原封不动的复制到dist/stiatc下。
yarn&npm
对比.
vue&react&Angular区别
vue与angular的区别呢
-
vue简单小巧,运行速度都比angular快,
-
这两个绑定都可以用{{}};
-
vue的指令是v-xxx;angular的指令是ng-xxx;
-
vue的数据放在data这个对象中,angular数据绑定在$scrope上;
-
vue有组件化概念,angular没有。
vue与React的区别
-
都是用虚拟DOM;
-
都提供了响应式和组件化的视图组件;
-
注意力都集中保持在核心库;
-
都有配套的路由和负责处理全局状态管理的库;
-
React使用JSX渲染页面,vue使用简单的模板;
-
vue运行的速度更快。
组件化
因为现在移动端的兴起,前端页面的逻辑已经变得很重了,一个页面的代码超过5000行的场景渐渐增多,作为一个程序员我也很是苦恼,这个时候页面的维护便会很有问题,牵一发而动全身的事情会经常发生,为了解决这个问题,便出现了前端组件化,这个组件化就不是UI组件了,而是包含具体业务的业务组件。