Vue介绍
Vue是一个构建用户界面(UI)的JS库, 是一个构建数据驱动的渐进式框架,Vue.js 的目标是通过尽可能简单的 API 实现响应的数据绑定和组合的视图组件。基于MVVM (Model View VievModel)设计模式书写。 Vue只关注视图层,可以快速创建用户界面。
Vue特点
(1)体积小:
gzip压缩后33K,并且不依赖其他基础库。
(2)更高的运行效率:基于虚拟DOM,一种可以预先通过JS(在内存中)进行各种运算,把最终的DOM操作计算出来并优化的技术啊。由于这种对DOM操作的预处理操作,并没有真是操作DOM,所以叫做虚拟DOM。
(3)双向数据绑定
Vue项目环境搭建
Vue是一个 JavaScript 框架。它是一个以 JavaScript 编写的库。
Vue是以一个 JavaScript 文件形式发布的,可通过 script 标签添加到网页中:
(1)CDN 引入
<script src="https://cdn.bootcss.com/vue/2.3.3/vue.js"></script>
CDN:全称是Content Delivery Network,即内容分发网络。CDN的通俗理解就是网站加速,可以让客户端快速度访问资源。
(2)使用vue官方脚手架(vue-cli)
Vue CLI 是一个基于 Vue.js 进行快速开发的完整系统,是一个官方脚手架,可以帮助我们快速创建vue项目工程目录。
vue-cli安装&使用步骤
1、全局安装vue-cli
>> yarn global add @vue/cli
2、创建项目
>> vue create 项目名
3、进入项目目录,启动项目
>> yarn serve
项目目录详解
一级目录:
node_modules //>> 依赖的第三方模块
public //>> vue服务器静态文件目录,只有唯一的一个index.html
src //>> 我们的开发目录,最重要的目录,源文件(我们写的代码)目录
.gitignore //>> git忽略列表
babel.config.js //>> es6编译配置
package-lock.json //>> 包描述文件(记录更详细,记住当时的版本信息)
package.json //>> 包描述文件
README.md //>> 说明文档
二级目录:
src:
assets //>> 静态资源 styles images fonts
components //>> 组件,是.vue的文件,主要是公用的小组件
views //>> 页面级别的组件
App.vue //>> 整个应用的顶级组件.
main.js //>> 入口文件
组件
所谓组件,即封装起来的具有独立功能的UI部件
组件特点:可重用、可组合、易维护
单文件组件
一个 XXX.vue文件就是一个单文件组件,功能逻辑独立,由 template、script、style三部分组成。
注意:style标签上可以通过 lang =”less”选择预处理语言(有些需要安装对应的loader模块)。
style标签上可以通过 scoped,让样式私有化。
使用自定义组件
使用自定义组件分为三个步骤: 1.引入组件 (引入一个已经写好的xxx.vue组件)
2.注册组件 (在components里面注册)
3.使用组件 (通过标签名使用)
Mustach表达式
语法: {{ 表达式 }},{{}} 里面可以写变量也可以写 表达式 ,也可以简单的运算,注意: 表达式必须能输出唯一结果,不能写if else条件等其他JavaScript代码。可以写三目运算。
指令
指令是写在标签上的一种自定义属性,主要是把vue实例中的数据,输出到html中。
常用指令
v-text 和 v-html:
都可以把数据渲染到一对标签中间,但是v-text不能识别html标签,v-html可以解析html标签。
v-show和v-if:v-show通过控制css的display属性,来控制显示和隐藏,v-if删除或重建DOM。区别: 如果是频繁的切换显示隐藏,就是用v-show;v-if频繁操作dom,性能低。
作用: 控制页面内容显示隐藏(常见:v-show显示/隐藏切换频繁,v-if显示/隐藏切换不频繁,但对隐藏安全要求较高)。
v-if 和 v-else-if 和 v-else:这几个指令需要配合使用,逻辑和js中的条件判断语句一致,会从上往下,找到满足条件的第一个表达式,渲染该DOM.(指令元素间,必须紧密相间)
作用: 用于页面结构中的逻辑判断。(常见:根据场景的不同,制定不同的显示规则)
v-for 循环:循环数组和对象
循环数组:v-for=”(元素的值, 元素的索引) in 数组”
循环对象:v-for=”(元素的值, 键名,元素的索引) in 对象”
作用: 用于根据模板,批量生产显示内容。(常见:数据列表)
v-model: 只能使用于表单,让表单和数据双向绑定。
适用的标签:
input(输入框 单选框 多选框) select textarea
作用: 用于获取用户输入表单的值(常见:表单数据获取)
v-bind :给属性绑定动态数据
语法: <标签 v-bind:属性=”表达式” ></标签>
简写: <标签 :属性=”表达式” ></标签>
1)v-bind绑定style 语法: <标签 :style=”{ color: ‘red’, backgroundColor: ‘green’ }” ></标签>
<div id='app'>
<div :style="{color:red}">111</div>
</div>
<script src="https://cdn.bootcss.com/vue/2.3.3/vue.js"></script>
<script>
let app = new Vue({
el: '#app',
data: {
message: 'hello',
num:1,
red:"yellow"
}
})
2)v-bind绑定class:语法:<标签 :class=”{ 类名1: flag1, 类名2: flag2 }” ></标签> 注意:flag是true,就有这个类,是false,就没有这个类
<style>
.red{
color: red;
}
.yellow{
color: yellow;
}
</style>
</head>
<body>
<div id='app'>
<div :class="{red:flag,yellow:!flag}">111</div>
</div>
<script src="https://cdn.bootcss.com/vue/2.3.3/vue.js"></script>
<script>
let app = new Vue({
el: '#app',
data: {
flag:false
}
})
</script>
一些很少用的指令:
v-pre:不编译Mustache模板表达式,直接当成普通的字符串输出;
v-cloak:隐藏Mustache表达式,直到有数据后,才显示出来;
v-once:只渲染1次,后续数据改变,不会重新渲染。
事件处理
基础语法:
v-on: 事件名;@事件类型=”函数名”;
@事件类型=”函数名(参数)”
计算属性
计算属性computed也是vue的一个配置选项,写法和methods一样,把复杂的计算逻辑都写在计算属性函数中,返回结果,通过函数的名字,可以直接使用该函数的返回结果。
computed特点和methods的区别 :1.写法上一样,都是一个方法,但是computed必须返回一个结果。computed有依赖缓存,如果依赖的数据没有发生改变,会直接使用使用缓存的结果,不会重新计算,只有依赖的数据发生了改变才会重新计算,性能高!而methods每次都会重新计算执行一遍。
vue 组件属性命名冲突处理策略
props ==> methods ==> data ==> computed ==> watch
过滤器filters
过滤器filters写法和methods一样,主要是在数据输出到页面之前,进行显示格式处理。
过滤器写法和computed一模一样,有一些区别:
1.过滤器,函数会接收一个参数,函数必须有返回值,对传入数据进行处理
2.过滤器,无缓存机制,调用次数,取决于页面中有所多少过滤器
3.过滤器,被作为一个特殊方法处理.
<div id='app'>
<div >{{sex|changesex}}</div>
</div>
<script src="https://cdn.bootcss.com/vue/2.3.3/vue.js"></script>
<script>
let app = new Vue({
el: '#app',
data: {
sex:0
},
filters:{
changesex(sex){
if(sex){
return "男"
}else{
return "女"
}
}
}
})
侦听器Watch
侦听器watch写法和computed一样,主要是捕获指定数据的变化,进行相关的操作。
侦听器写法和computed一模一样,有一些区别:
1.侦听器,函数会接收两个参数(),内部可以根据新值进行处理,函数无需返回值,
2.侦听器,自定捕获数据的变化,并作出响应。变化一次,执行一次。
3.侦听器,被作为一个监听方法处理.
<div id='app'>
<div >{{sex}}</div>
</div>
<script src="https://cdn.bootcss.com/vue/2.3.3/vue.js"></script>
<script>
let app = new Vue({
el: '#app',
data: {
sex:0
},
created(){
setTimeout(()=>{
this.sex=1
},3000)
},
watch:{
sex(newval,oldval){
console.log("newval",newval); //1
console.log("oldval",oldval); //0
}
}
})
Vue生命周期
Vue生命周期总共分为4大阶段创建前/后、载入前/后、更新前/后、销毁前/后共8个方法。
创建前: :
在beforeCreate阶段,vue实例的挂载元素el和数据对象data都为undefined,还未初始化;
创建后 :
在created阶段,vue实例的数据data有了,el还没有。
*创建阶段:主要是处理数据(主要:对数据进行挟持,把data对象上的数据挂到了this实例上)!!
挂载前:
在beforeMount阶段,vue实例的$el和data都初始化了,但还没有挂载之前都是虚拟的dom阶段,data还未替换;
挂载后:
在mounted阶段,vue实例挂载完后,data成功渲染。
*挂载阶段:主要是合成数据和视图模板,先在内存完成虚拟dom解析,最后一次dom操作直接更新到页面。
更新前:
beforeUpdate,当data变化后,这时视图尚未改变,依旧可以获得改变前的DOM内容
更新后:
updated,当data变化后,页面视图已经更新完毕,可以获得最新的DOM信息
*更新阶段:主要是完成对视图的动态修改。
销毁前:
beforeDestroy,实例销毁之前调用。在这一步,实例仍然完全可用。这时data的改变不会再触发周期函数,说明此时vue实例已经结束了事件监听以及和dom的绑定,但是dom结构依然存在。
销毁后:
destroyed,Vue 实例销毁后调用。这时Vue 实例指示的所有东西都会解绑定,所有的事件监听器会被移除,所有的子实例也会被销毁。
*销毁阶段:主要是完成对组件的回收。
发送异步请求一般是在created阶段,mounted阶段操作dom,beforeDestroy阶段清除定时器。
前端路由Vue-router
前端路由定义了地址和组件的一一对应关系(一个url地址,对应一个页面级别的组件)
前端路由优点:
1.路由处理速度较快,不用每次都通过服务返回。
2.前端拥有更多的主动权。
缺点:
1.使用浏览器的前进,后退键的时候会重新发送请求,没有合理地利用缓存。
2.单页面无法记住之前滚动的位置,无法在前进,后退的时候记住滚动的位置。
在路由文件router.js里面,配置路由和组件的映射关系,每一个路由映射一个组件.
路由的配置有2种:
直接引入
import Home from './views/Home.vue'
const routes = [
{
path: '/home',
name: 'home',
component: Home
}]
按需加载
{
path: '/about',
name: 'about',
//路由级别代码分割
//这会为该路由生成一个单独的块(about.[hash].js)
//当访问路由时,延迟加载。
component: () => import(/* webpackChunkName: "about" */ './views/About.vue')
}
使用
在App.vue里面,添加一个路由出口,使用来挂载所有的路由组件。会根据当前路由动态渲染不同的页面组件
路由导航
Vue-router里面有内置的组件可以实现跳转,他会被渲染成一个a标签
路由嵌套
在某些场景中,页面只需要做局部更新。在路由中再定义子路由,叫做路由嵌套。内部使用children属性来定义。
var router = new VueRouter({
routes:[
{path:"/",component:index},
{path:"/product",component:product},
{path:"/about",component:about,
children: [
{path : "" , component :us},
{path : "company" , component :company},
]
}
]});
路由中的全局对象
$router-全局路由对象
this.$router.push(): 跳转到不同的url,但这个方法会向history栈添加一个记录,点击后退会返回到上一个页面。
this.$router.replace():替换当前路由,不会向history栈添加一个记录,无法通过history返回到上一个页面。
$route-获取当前页面路由信息
this.$route.path : 获取当前页面对应的路由地址
组件通信
(1)父组件传给子组件
1. 父组件使用v-bind绑定动态数据到子组件的标签上。
<子组件标签 :属性名=“动态数据”></子组件标签>
2. 子组件通过props接收。
export default {
props: [“属性名”]
}
3. props接收的对象写法/类型校验/默认值。
export default {
props: {
属性名:{
type: String, // 类型可以是Number/Object/Boolean/Array/Date/Funcion
default: ‘默认值’ // 对象或数组需要写函数。
//默认值为对象
default: () => ({})
//默认值为数组
default: () => ([])
}
}
}
(2)子组件传递给父组件
子组件通过 this.$emit() 把数据传递出去
this.$emit(“自定义事件”, 要传递出去的数据)
父组件通过在子组件标签上v-on绑定自定义事件接收数据
<子组件标签 @自定义事件=”函数名”></子组件标签>
methods: {
函数名( sonData ) {
// sonData就是子组件传递出来的数据。
}
}
(3)任意组件之间传递数据(跨级组件)
任意组件之间传递数据,需要通过一个空的vue实例,步骤如下:
1)在入口文件main.js中,创建一个空的vue实例,挂载在Vue的原型上
Vue.prototype.$bus = new Vue();
2)通过emit方法把数据传递出去。
this.$bus.$emit(‘自定义事件’, 要传递出去的数据)
3)在生命周期created中,通过$on监听自定义事件的方式,接收数据。
created ( ) {
this.$bus.$on(‘自定义事件’, function ( data ) {
// data就是从传递过来的数据
})}
slot插槽
插槽就是在子组件中预留位置(插槽),父组件在使用子组件标签的时候,可以把内容插入进去。
(1)默认slot:一个没有名字的插槽,就是默认插槽
子组件
<!-- 默认插槽: name=default不写 -->
<slot>默认header</slot>
<子组件>
<!-- 这里写的所有内容 都会被插入默认插槽中 -->
</子组件>
(2)具名slot:一个具有名字的插槽,就是具名插槽
子组件
<slot name="header">默认header</slot>
<slot name="main">默认main</slot>
<slot name="footer">默认footer</slot>
父组件
<子组件>
<!-- 具名插槽: 找到slot的值对应的这个名字的插槽,把内容插入 -->
<h1 slot="header">Header</h1>
<h1 slot="main">main</h1>
<h1 slot="footer">footer</h1>
</子组件>
(3)作用域slot
子组件中的数据,通过v-bind绑定到插槽上:
<slot :num="num" :msg="msg" name="main">默认main</slot>
父组件中,通过作用域插槽使用数据:
<h1 slot="main" slot-scope="scope">main main mian: {{ scope.msg }} === {{ scope.num }}</h1>
v-slot
注意:
1.v-slot的缩写是#。
2.需要使用template包裹
v-slot是2.6.x新增的指令,用于取代以上三种写法。
<Layout>
<template #header>
<h1>Header</h1>
</template>
<template #main="scope">
<h1>Main</h1>
{{ scope }}
{{ scope.num }}
{{ scope.msg }}
</template>
<template #footer>
<h1>Footer</h1>
</template>
</Layout>