什么是Vue
Vue.js 是一套构建用户界面的框架 只关注视图层 易于上手,还便于与第三方库或即有项目整合
MVC:(数据层,页面层,逻辑层)
-
MVVM模式:model-view-ViewModel
model:负责纯javascript对象表示
view:view负责显示
两者做到最大极限的分离
viewModel:负责将model数据同步到view显示出来,还负责把view的修改同步到model
Vue选项
var vm = new Vue({
el: "#app",//元素名字 列如:#id,.class 要控制的区域
data: {
//数据(需要注意的是,在组件中的data必须是函数 数据都需要return)
message: "hello",
name:'zz'
},
computed: {
// 在computed中,可以定义一些属性,这些属性叫做计算属性,计算属性的本质就是一个方法,只不过在使用这些计算属性的时候,是把 方法名称 直接当作属性来使用的;并不会把 计算属性 当做方法去调用
//* 注意1:计算属性在调用时候不要加(),直接把他当作一个属性去调用就好
//* 注意2:只要计算属性(function)内部所用到的任何data数据发生了变化,就会立即重新计算这个属性的值
// * 注意3:计算属性的求值结果,会被缓存起来,方便下次直接使用;如果 计算属性 方法中,data的任何数据没有发生改变,而你又在此调用,则返回的是缓存好的结果
"result":function(){
return this.name + this.message
//返回结果: hello zz
}
},
methods: {
//这里可以自定义方法
},
watch: {
//侦听器 当某个数据发生改变就会触发 让数据发生变更
//监听的方法一般都会有两个参数,newVal,oldval
//列如标签有一个 v-model='name'
'name':function(newVal,oldval){
//newVal:是新的数据 结果: zz
//oldVal:是旧的数据 结果: undefined
},
//典型案列
'$route.push':function(newVal,oldval){
console.log(newVal ------ oldval)
// 注册好了 跳转 登录页
//newVal:当前跳转到的页面 结果:登录页
//oldVal: 从上一个页面 跳转到当前页面的 页面 结果:注册页
}
// watch 最好用来监听非 DOM 元素的改变 列如:$route
}
});
-
总结:
watch,computed,methods之间的对比
1.
computed:
属性的结果会被缓存,除非依赖的响应式属性变化才会重新计算。主要当作属性来使用;2.
methods:
方法表示一个具体的操作,主要书写业务逻辑;-
watch:
一个对象,键是需要观察的表达式,值是对应回调函数。主要用来监听某些特定数据的变化,从来进行某些具体的业务逻辑操作;可以看做是methods
和computed
的结合体;
-
Vue v-指令
-
v-bind:(缩写:) 数据绑定
- 在使用==号以后 后面跟的就是一个js表达式
{{ }}:差值表达式 注意react里没有差值表达式一说而是jsx语法
v-on: (缩写@:)事件处理
v-for="(item, index) in array"(遍历 (元素,下标)) 要配合:key( String/Number )
v-model :双向数据绑定(只能运用到表单元素中...)
v-cloak :可以用来解决插值表达式闪烁问题
-
v-pre:表示该会跳过该标签及其子元素的编译
v-指令区别
-
v-show 和 v-if
v-if
v-else-if
v-else
v-show
一般来说,v-if有更高的切换消耗 v-show有更高的初始渲染消耗。因此如果频繁切换使用v-show较好,如果运行时条件不大可能改变 v-if较好
如果一个元素一直都不会显示出来 并操作他 v-if更好
v-if特点:每次都会重新删除或创建元素
v-show:只会切换diplay:none/block
-
v-html 和 v-text
v-html : 真正的HTML也可以是 标签
v-text : 只是一串字符串
Vue 修饰符
-
事件修饰符:
v-on:click.stop:阻止冒泡的
v-on:click.prevent:阻止默认行为
v-on:click.once :只会执行一次
v-on:click.capture:添加事件监听器时使用事件捕获模式
@click.self:只当事件在该元素本身(比如不是子元素) 触发时触发回调
-
self 与 stop的区别
self只取消当前事件本身的冒泡并不影响其他的冒泡
stop则是取消所有的冒泡
-
按键修饰符:
v-on:keyup.enter:按回车触发
分别还有:.tab,.delete,.esc, .space
自定义修饰符
`Vue.config.keyCodes.f2 =113` @Keyup.f2调用
-
修饰键:
@keyup.alt.13:同时按下 alt+回车
分别还有: .ctrl .alt .shift .meta
修饰键与修饰符不同 修饰键单独按并不会触发 需要按修饰键+修饰符才会触发
-
事件处理:
@touchstart:也是类似点击事件 但是相比click他没有延迟 而click有300毫秒的延迟所以 touchstart相对来说会先执行
@touchend:也比click快但是比start慢 也是点击事件
@touchmove:在end之前 start之后 还是比click快 鼠标移动事件
Vue使用Class样式
- 数组
<h1 :class="['red','thin']"> 这是一个样式运用方法 </h1>
- 数组中使用三元表达式
<h1 :class="['red','thin', flag? 'active' : 'isactive' ]"> 这是一个样式运用方法 </h1>
data :{
flag : true; //ture引用active, false则不用active
}
- 数组中嵌套对象
<h1 :class="['red','thin',{ 'active' : flag }]"> 这是一个样式运用方法 </h1>
data:{
flag : true; //ture引用active, false则不用active 类似三元表达式
}
- 直接使用对象
<h1 :class="{red:true,thin:true,active:false,isactive:false }"> 这是一个样式运用方法 </h1>
<h1 :class="obj"> 这是一个样式运用方法 </h1>
//直接传对象 且只有true的被使用 或者可以直接写一个对象
data:{
obj:{
red:true,
thin:true,
active:false,
isactive:false
}
}
Vue使用内联样式-style
- 直接在元素上通过 :style 的形式,书写样式对象
<h1 :style='{color:'red', 'font-size':'40px'}'> 这是一个内联样式的H1</h1>
- **将样式对象,定义到
Data
中,并直接引用到:style
中
data:{
handleObj:{
color:'red',
'font-size':'40px',
fontSize:40 // 两种写法罗峰写法 或者 字符串 直接数组则默认px
}
}
- **在
:style
中通过数组,应用多个data
上的样式对象
<h1 :style="[handleObj,handleObj2 ]"> 这是一个内联样式的H1</h1>
data:{
handleObj:{
color:'red',
'font-size':'40px',
fontSize:40 // 两种写法罗峰写法 或者 字符串 直接数组则默认px
},
handleObj2:{
backgroundColor:'#0f6',
background-color:'#0f6'
}
}
Vue 过滤器
//过滤器的格式
// \ 术语叫做 管道符
{{ name | isname('Dad+1') | test('Nb')}}
//过滤器的语法
isname: 过滤器的名字
Vue.filter("isname",function(name ,msg){
//replace 第一个参数也可以写正则
return name.replace( '弟弟','Dad') //只会改第一个弟弟
return name.replace(/弟弟/g,'Dad')//全改
return name.replace(/弟弟/g,msg)//第三种方法可以通过传参来更改
})
Vue.filter('test',function(name,msg){
return name + '====='
})
//定义私有过滤器
//私有的话 过滤器的名字变成方法名
var vm = new Vue({
data:{
name:'就是一个弟弟就是一个弟弟就是一个弟弟,'
},
filters:{
isname:function(name,msg){
//replace 第一个参数也可以写正则
return name.replace( '弟弟','Dad') //只会改第一个弟弟
return name.replace(/弟弟/g,'Dad')//全改
return name.replace(/弟弟/g,msg)//第三种方法可以通过传参来更改
}
}
})
过滤器调用的时候,采用的是就近原则,如果私有过滤器和全局过滤器一致了,这时候,会优先调用私有过滤器
自定义全局的指令
//第一个参数在调用时候,必须在指令前加上v- 前缀来进行调用
//第二个参数是一个对象,这个对象身上,有一些指令相关的函数,这些函数可以在特定的阶段,执行相关的操作
Vue.directive('focus',{
//每个函数中,第一个参数都是el,表示被绑定了指令的那个元素,这个el参数,是一个原生的Js对象
bind:function(el){
//每当指令绑定到元素上的时候,会立即执行这个bind函数, 只执行一次
el.focus() //focus 获取焦点 input lode原生方法 但是在这里使用时不行的
//在元素刚绑定了指令的时候,还没有插入到DOM中,这时候,调用focus方法没有作用
//因为一个元素,只有插入Dom之后,才能获取焦点
},
inserted:function(el){
//inserted 表示元素 插入到DOM中的时候,会执行inserted函数[触发一次]
//一般来说从内存(JavaScript)渲染到数据 也就是 从model 渲染到 view 就要执行的话用bind 列如:样式 而js的事件操作 需要等Dom生成完毕才能执行 最好放在 inserted里
},
updata:function(el){
//当vNode更新的时候,会执行updata,可能触发多次
}
})
`自定义 私有指令`
var vm = new Vue({
dirctives:{
focus:function(){
//之后操作和全局一样
},
focus: function(){
//如果想 bind 和 updata都重复操作 那么可以直接在function里写操作
//等同于 bind 和 updata
}
}
})
* Vue生命周期
-
什么是生命周期:
从Vue实列创建,运行,销毁,会伴着各种函数,这些统称为 生命周期
生命周期钩子:就是生命周期的别名
-
主要的生命周期函数分类:
-
创建期间的生命周期函数:
beforeCreate:实列刚在内存中被创建出来,此时,还没有初始化好 data 和 methods属性。
Created:实列已经在内存中创建OK,此时data和 methods已经创建OK,此时没有开始 编译模板
beforeMount:此时已经完成了编译的模板,但是还没有挂载到页面上
Mounted:此时,已经将编译好的模板,挂载到了页面指定的容器中显示了
-
运行期间的生命周期函数:
beforeUpdate:状态更新之前执行此函数,此时data中的状态值是最新的,但是界面上显示的数据还是旧的,因为此时还没有开始重新渲染Dom节点
Update:实列更新完毕之后调用此函数,此时 data 中的状态值 和 界面上显示的数据,都已经完成了更新,界面已经被重新渲染好了
-
销毁期间的生命周期函数:
beforeDestroy:实列销毁之前调用,在这一步,实列容然可用
Destroyed:Vue 实列销毁后调用,调用后,Vue实列指示的所有东西都会解绑,所有事件监听器会被移除,所有的子实列也会被销毁
-
* Ajax
Ajax的原理简单来说通过xmlHttpRequest 对象来想服务器发异步请求,从服务器获得数据,然后用JavaScript来操作DOM而更新页面。这其中最关键的一步就是从服务器获得请求数据。要清楚这个过程和原理,必须对XMLHttpquerst有所了解
XMLHttprequest 是 Ajax的核心控制,它是在IE5中首先引入的,是一种支持异步请求的技术,简单说,也就是JavaScript可以及时向服务器提出请求和处理响应,而不阻塞用户,打到无刷新的效果。
* JSONP的实现原理
由于游览器的安全限制,不允许AJAX访问 协议不同,域名不同,端口号不同的数据接口,游览器认为这种访问不安全
可以通过动态创建Script标签的src属性,指向数据接口的地址,因为script标签不存在跨域限制,这种数据数据获取方式,称作JSONP(*注意:JSONP的实现原理,知晓,JSONP只支持GET请求)
-
具体实现过程:
* 先在客户端定义一个回调方法,预定义对数据的操作; * 再把这个回调方法的名称,通过URL传参的形式,提交到服务器的数据接口; * 服务器数据接口组织好要发送给客户端的数据 ,再拿着客户端传递过来的回调方法名称,拼接出一个调用这个方法的字符串,发送给客户端去解析执行 * 客户端拿到服务器返回的字符串之后,当作Script脚本去解析执行,这样就能拿到JSON数据了
Axios
npm install --save --save-exact axios vue-axios
-
axios的特点有哪些?
Axios 是一个基于 promise 的 HTTP 库,支持promise所有的API
它可以拦截请求和响应
它可以转换请求数据和响应数据,并对响应回来的内容自动转换成 JSON类型的数据 安全性更高,客户端支持防御 XSRF
-
axios有哪些常用方法?
axios.get(url[, config]) //get请求用于列表和信息查询
axios.delete(url[, config]) //删除
axios.post(url[, data[, config]]) //post请求用于信息的添加
axios.put(url[, data[, config]]) //更新操作
-
说下你了解的axios相关配置属性?
url
是用于请求的服务器URLmethod
是创建请求时使用的方法,默认是getbaseURL
将自动加在url
前面,除非url
是一个绝对URL。它可以通过设置一个baseURL
便于为axios实例的方法传递相对URLtransformRequest
允许在向服务器发送前,修改请求数据,只能用在'PUT','POST'和'PATCH'这几个请求方法headers
是即将被发送的自定义请求头
// 添加请求拦截器
axios.interceptors.request.use(function (config) {
// 在发送请求之前做些什么
//Loading
Indicator.open({
text: '加载中...',
spinnerType: 'double-bounce'
});
return config;
}, function (error) {
// 对请求错误做些什么
return Promise.reject(error);
});
// 添加响应拦截器
axios.interceptors.response.use(function (response) {
// 对响应数据做点什么
//响应到数据以后 close 关闭Loading
Indicator.close();
if(res.data.res_code === 1){
return res.data.res_body
}
else{
Toast({
message: '提示:数据请求异常',
position: 'bottom',
duration: 3000
});
}
}, function (error) {
// 对响应错误做点什么
return Promise.reject(error);
});
// 请求数据
export const getHomeSwipe = ()=>{
return ajax.get('/api/swiperimgs')
}
定义Vue组件
什么是组件: 组件的出现,就是为了拆分Vue实列的代码量的,能够让我们以不同的组件,来划分不同的功能模块,将来我们需要什么样的功能,就可以
什么是模块化:
文件作用域
-
通信规则
加载 require
导出
模块规范:
模块作用域
-
使用 require 方法用来加载模块
-
作用:
执行被加载中的代码,得到被加载模块中的export 导出接口对象
-
-
使用 exports 接口对象来导出模块中的成员
-
作用
模块作用域:默认文件中所有的成员只在当前文件模块中有效
对于希望可以被其他模块访问的成员,我们就需要吧这些公开的成员都挂载到 export 接口对象中就可以了
-
模块化:是从代码逻辑的角度进行划分的;
组件化:是从UI界面的角度进行划分的;
全局组件定义的三种方法
- 使用Vue.extend 配合 Vue.component 方法:
var login = Vue.extend({
tamplate:` <h1> 登录 </h1>`
})
Vue.component('login',login)
- 直接使用Vue.component 方法:
Vue.component('register',{
template:`<h1> 注册 </h1>`
});
- 将模板字符串,定义到script标签种:
<script id="tmpl" type="x-tamplate">
<div> <a href='#' > 登录 </a> | <a href='#' > 注册 </a> </div>
</script>
- 创建私有组件:
var vm = new Vue({
components:{
login:{
template:·<h1>这是一个私有组件</h1>·
}
}
})
在使用组件的时候 组件名列如myCol 那么渲染就要使用 <my-col></my-col>渲染
组件中 只允许有一个根元素
组件中的 data 必须一个是方法,这个方法内必须return一个对象才行
组件切换除了 v-if 以外 还可以是用 :IS="组件名"
* Vue 父子组件通信
-
父组件通过props向子组件传值
- 父组件,可以引用子组件的时候,通过属性绑定(v-bind:)的形式,把需要传值给子组件的数据,以属性绑定的形式,传递到子组件的内部,供子组件使用
//HTML模板
<div id="app">
<col :parenMsg='msg'> </col>
</div>
var vm = new Vue({
el:'#app',
data:{
msg:'这是一个子组件所需要的值'
},
//子组件中,默然无法访问到 父组件中的 data 上的数据和 methods 中的方法
components:{
col:{
//* 注意:子组件中的 data 数据,并不是通过父组件传递过来的,而是子组件自身私有的,比如:子组件通过 Ajax。请求回来的数据,都可以放到 data 身上
`* 注意:在子组件中 data 数据时可读可写的,props绑定属性的参数是只读的`
data(){
return{
name:'zz',
age:23
}
},
//把父组件传过来的 parentMsg属性,现在props数组中定义一下,这样才能使用这个数据
//* 注意:组件中的所有 props中的数据,都是通过父组件传递给子组件的
props:["parentMsg"],
template:'<h1>收到了父组件的值了---{{parentMsg}}</h1>'
}
}
})
-
子组件通过调用事件向父组件传值
- 子组件通过事件 this.$emit('第一参数为父组件的方法',第二个是要穿过去的参数对象')
<div id='app'>
<!---父组件-->
<col @func="show"></col>
</div>
<!---子组件-->
<template id='tmp'>
<div>
<h1>这是子组件</h1>
<input type="button" value="触发父组件来传值" @click="childClick"/>
</div>
</template>
var vm = new Vue({
data:{
detail:{}
},
methods:{
show(data){
this.detail = data
}
},
components:{
col:{
template:'#tmp',
data(){
return{
msg:{
name:'zz',
age:23
}
}
},
methods:{
childClick(){
this.$emit('show',this.msg)
}
}
}
}
})
Vue ref获取Dom元素和组件组件引用
<div id='app'>
<Input type='button' value='获取元素' @click='getElement' ref='mybtn'>
<h3 id='tmp' ref='tmp'>获取成功的 innerHTML</h3>
<col ref='col'></col>
</app>
var vm = new Vue({
el:'#app',
data:{},
methods:{
getElement(){
this.$refs.tmp.innerHtml//获取ref名为tmp的元素
this.$refs.col.data// 组件上使用ref会吧整个组件vue实列存到ref 这样的话可以通过 $refs 来获取子组件里的data
}
},
components:{
col :{
template:"<h1> 登录注册 </h1>",
data:{
name:'zz'
},
methods:{
show(){
console.log('子组件的方法')
}
}
},
}
})
Vue动画
- 使用transition
!需求:点击按钮让h3显示再按隐藏
1. 使用 transition 元素,把需要把动画控制的元素,包裹起来(transition元素是 vue 官方提供)
2. 自定义两组样式,来控制 transition 内部的元素实现动画
/*v-enter 【这是一个时间点】 是进入之前,元素的起始状态,此时还没有开始进入*/
/*v-leave-to 【这是一个时间点】是动画离开之后,离开的终止状态,此时,元素动画已结束*/
v.enter,
v-leave-to{
opatity: 0;
},
v-enter-active,
v-leave-active{
.v-enter-active[入场动画的时间段],
.v-leace-active[离场时间的时间段]{
transition: all 0.4s ease
}
}
<transition>
<h3 v-show='flag'>这是一个会动的标签</h3>
</transition>
Vue-Router
什么是路由
后端路由: 对于普通的网站,所有的链接都是URL地址,所有的URL地址都对应服务器上对应的资源;
前端路由: 对于单页用程序来说,主要通过URL中的hash(#号)来实现不同页面之间的切换,同时 hash 中有一个特点:HTTP请求不会包含hash相关的内容;所有单页面程序中的页面跳转主要用hash实现;
在单页面程序中,这种通过hash改变来切换页面的方式,称作前端路由(区别于后端路由)
安装
- CDN安装
<script src="/path/to/vue.js"></script>
<script src="/path/to/vue-router.js"></script>
- Npm
npm install vue-router
- 如果在一个模块化工程中使用它,必须要通过 Vue.use() 明确地安装路由功能:
import Vue from 'vue'
import VueRouter from 'vue-router'
Vue.use(VueRouter)
- 构建开发版:
如果你想使用最新的开发版,就得从 GitHub 上直接 clone,然后自己 build 一个 vue-router
git clone https://github.com/vuejs/vue-router.git node_modules/vue-router
cd node_modules/vue-router
npm install
npm run build
vue-router中router
-
$route 表示(当前路由信息对象)
表示当前激活的路由的状态信息,包含了当前 URL 解析得到的信息,还有 URL 匹配到的 route records(路由记录)。路由信息对象:即$router会被注入每个组件中,可以利用它进行一些信息的获取。
-
$route.path
字符串,对应当前路由的路径,总是解析为绝对路径,如 "/foo/bar"。
-
$route.params
一个 key/value 对象,包含了 动态片段 和 全匹配片段,
如果没有路由参数,就是一个空对象。
-
$route.query
一个 key/value 对象,表示 URL 查询参数。
例如,对于路径 /foo?user=1,则有 $route.query.user == 1, 如果没有查询参数,则是个空对象。
-
$route.hash
当前路由的 hash 值 (不带 #) ,如果没有 hash 值,则为空字符串。锚点
-
$route.fullPath
完成解析后的 URL,包含查询参数和 hash 的完整路径。
-
$route.matched
数组,包含当前匹配的路径中所包含的所有片段所对应的配置参数对象。
-
$route.name
当前路径名字
-
$route.meta
路由元信息
-
route object 出现在多个地方
(1) 在组件内,即 this.$route
(2) 在 $route 观察者回调内 router.match(location) 的返回值
(3) 导航守卫的参数:
router.beforeEach((to, from, next) => {
// to 和 from 都是 路由信息对象
})
watch: {
$route(to, from) {
// to 和 from 都是 路由信息对象
}
}
$router对象
全局的路由实例,是router构造方法的实例。在 Vue 实例内部,你可以通过 $router 访问路由实例
const router = new Router({
routes: [
{
path: "/",
name: "首页",
redirect: '/home'
},
{
path: '/login',
name: 'Login',
component: Login
},
{ path: '*', component: NotFoundComponent }
],
linkActiveClass: "active-router",
linkExactActiveClass: "exact-router"
})
路由实列方法 push
// 字符串
this.$router.push('home')
// 对象
this.$router.push({ path: 'home' })
// 命名的路由
this.$router.push({ name: 'user', params: { userId: 123 }})
// 带查询参数,变成 /register?plan=123
this.$router.push({ path: 'register', query: { plan: '123' }})
push方法其实和<router-link :to="...">是等同的。注意:push方法的跳转会向 history 栈添加一个新的记录,当我们点击浏览器的返回按钮时可以看到之前的页面。
路由实列方法 go
// 页面路由跳转 前进或者后退
this.$router.go(-1) // 后退
路由实列方法 replace
//push方法会向 history 栈添加一个新的记录,而replace方法是替换当前的页面,
不会向 history 栈添加一个新的记录
<router-link to="/05" replace>05</router-link>
// 一般使用replace来做404页面
this.$router.replace('/')
使用
- CDN简单使用Vue-router
- Css
.myactive{
/*如果不想麻烦 也可以吧class名直接改为 router-link-active 但是不推荐*/
}
- HTML
<div id='#app'>
<!-- router-link 默认渲染为一个a 标签-->
<!-- tag是让 router-link 以什么标签进行渲染 但是都会绑定一个跳转的点击事件-->
<!--如果在路由中,使用 查询字符串,给路由传递参数,则不需要修改路由的 path 属性-->
<!--这种传参方式为 query传参方式 -->
<router-link to='/login?id=10&name='zz'' tag='button'>登录</router-link>
<template id='login'>
<!--mine-->
<router-link to='/login/mine' tag='div'>我的</router-link>
<router-view></router-view>
</template>
<router-link to='/register/12/zhao' tag='span'>注册</router-link>
<!--这是 vue-router 提供的元素,专门用来当做占位符的,将来,路由规则,匹配到的组件,就会展示到这个 router-view 中去-->
<router-view></router-view>
</div>
- JavaScript
let login = {
//在插值表达式中 this是可以省略掉的
template:'<h1> 登录组件-----{{ $route.query.name }} </h1>',
created(){
this.$route.query.id //调用到id
this.$route.query.name //调用到name
}
}
let register = {
template:'<h1> 注册组件-----{{ $route.query.name}}</h1>',
created(){
this.$route.query.id //调用到id
this.$route.query.name //调用到name
}
}
let mine = {
template:'<h1> 这是一个login的子组件</h1>',
}
// 创建一个路由对象,当导入vue-router包之后,在 window 全局对象中,就有了一个 路由的构造函数,叫做VueRouter
//在new 路由对象的时候,可以为构造函数,传递一个配置对象
var routerObj = new VueRouter({
//route 这个配置对象中的 route 表示【路由匹配规则】的意思
routes:{
// 路由匹配规则
//每个路由规则,都是一个对象,这个规则对象,身上有两个必须的属性
// 属性1: 是path,表示监听 那个路由的地址
//属性2: component,表示,如果路由是前面匹配到的 path ,则展示 component属性对应的那个组件
//注意:component 的属性值,必须是一个组件的模块对象,不能组件的应用名称
{path:'/',component:login;}//默认跳转页面
{path:'/',redirect:'.login'}//默认页第二种方法,重定向,强制性的显示
{ path:'/login',
component: login,
children:{
//子组件中不需要 / 如果加了/ 就说明你是要从根访问 在组件不加则是从父 /longin/mine 访问
{path:'mine', component:mine;}
}
}
{path:'register/:id/:name',component:register;}//第二种传参方法 path中设置 也叫params方式传参
},
linkActiveClass: 'myactive',//new VueRouter 的一个属性点击时执行这个样式
})
var vm = new Vue({
el:"#app",
data:{},
methods:{},
router: routerObj //将路由规则对象,注册vm实列上,用来监听 URL 地址的变化 ,然后展示对应的组件
})
vue-Router实现默认页多组件
<div id='#app'>
<!--router-view name 指定要渲染的组件名-->
<router-view name='header'></router-view>
<router-view name='left'></router-view>
<router-view name='main'></router-view>
</div>
//css仔细想 完成经典布局
let header = {
template:"<div class='header_css'>这是一个头部</div>"
}
let left= {
template:"<div class='left_css'>这是一个左侧</div>"
}
let main = {
template:"<div class='main_css'>这是一个主体</div>"
}
var router = new VueRouter({
routes:[
{
path:'/',
components:{ //需要注意的是 一个页面要个组件是 components
'default':header, //默认的
"left":left,
"main":main
}
}
]
})
滚动行为
使用前端路由,当切换到新路由时,想要页面滚动到顶部,或者时保持原先的滚动位置,就像重新加载页面那样,vue-router就能做到
ps:这个功能只在支持 history.pushState 的浏览器中可用
当创建一个 Router 实例,你可以提供一个 scrollBehavior 方法:
const router = new VueRouter({
routes: [...]
scrollBehavior(to,from,savedPosition){
// return 期望滚动到哪个的位置
}
})
scrollBehavior 方法接收 to 和 from 路由对象,第三个参数 savedPosition 当且仅当 popstate 导航(通过浏览器的 前进\后退 按钮触发)时才可用
路由懒加载
当打包构建应用时,javascript包会变得非常大、影响页面加载,如果我们能把不同路由对应得组件分割成不同得代码块,然后当路由访问的时候才在家对应组件,这样更加高效
结合Vue的异步组件和webpack的代码分割功能,轻松实现路由组件的懒加载。
首先,可以将异步组件定义为返回一个Promise的工厂函数
const Foo = () => Promise.resolve({// 组件定义对象})
第二,在webpack2中,我们可以使用动态 import语法来定义代码分块import('./Foo.vue')
ps: 如果使用的时babel,你将需要添加 sybtax-dynamic-import 插件,才能使Babel可以正确的解析语法
结合这两者,这就使如何定义一个能够被webpack自动代码分割的异步组件
const Foo = () => import('./Foo.vue')
在路由配置中什么都不需要改变,只需要像往常一样使用
Foo:const router = new VueRouter({
routes: [{
path: '/foo', component: Foo
}]
})
把组件按组分块
有时候我们想把某个路由下的所有组件都打包在同个异步块中,只需要使用命名 chunk,一个特殊的注释语法来提高chunk name(需要webpack>2.4)
const Foo = () => import(/* webpackChunkName: "group-foo" */ './Foo.vue')
webpack 会将任何一个异步模块与相同的块名称组合到相同的异步块中
nrm的安装使用
作用:提供一些最常用的npm包镜像地址,能够让我们快速切换安装包的服务器地址;
什么是镜像:原包刚一开始只是存在国外的npm服务器,但是由于网络原因,经常访问不到,这时候,我们有在国内,创建一个和官网完全一样的npm服务器,只不过,数据都是从人家那里拿过来的,使用方式完全一样;
1.运行npm i nrm -g
全局安装npm
包
2.使用npm ls
查看当前所有可用的镜像源地址以及当前所使用的镜像源地址;
3.使用nrm use npm
或 nrm use taobao
切换不同的镜像源地址
注意:nrm只是单纯的提供了几个常用的下载包URL地址,并能够让我们在这几个地址之间很方便的进行切换,但是,我们每次装包的时候,使用的 装包工具都是
npm
Webpack
-
在网页中会引用那些常见的静态资源:
-
js
- .js .jsx .conffe .ts(TypeScript)
-
css
- .css .less .sass(更新以后叫 scss 基本上和less 只是语法不同)
-
Images
- .jpg .png .git .bmp .svg .webp
-
字体文件(Fonts)
- .svg .ttf .eot .woff .woff2
-
模板文件
- .ejs .jade .vue【这是在webpack中定义组件的方式】
-
-
网页引入静态资源多了以后有什么问题??
网页加载速度慢,因为 我们要发起很多的二次请求;
要处理错综复杂的依赖关系
-
如何解决上述问题
合并,压缩,精灵图,图片Base64编码
可以使用requireJs 或 webpack解决各个包之间的复杂依赖关系
-
什么是webpack/gulp
webpack他是基于Node.js开发的模块化打包工具
gulp基于流的自动化构建工具,流,一个操作的输出结果作为另一个操作的输入
-
如何完美实现上述的2种方案
-
使用Gulp可以进行html,css,img的压缩打包,是自动化构建工具,可以将多个js文件或是css压缩成一个文件,并且可以压缩为一行,以此来减少文件体积,加快请求速度和减少请求次数;并且gulp有task定义处理事务,从而构建整体流程,它是基于流的自动化构建工具
-
优点:
小巧 灵活 方便去做一些灵活任务的处理
它能自动化地完成 前端代码的测试、检查、合并、压缩、格式化、浏览器自动刷新、部署文件生成,并监听文件在改动后重复指定的这些步骤
-
-
Webpack是前端构建工具,实现了模块化开发和文件处理。他的思想就是“万物皆为模块”,它能够将各个模块进行按需加载,不会导致加载了无用或冗余的代码。所以他还有个名字叫前端模块化打包工具
借助于webpack这个前端自动化构建工具,可以完美实现资源的合并,打包,压缩,混淆等诸多功能;
webpack打包的过程 见笔记
-
[图片上传失败...(image-3cca2e-1553654416703)]
-
webpack安装的两种方式:
运行
npm i webpack -g
全局安装webpack,这样就能在全局使用webpack的命令在项目跟目录中运行
npm i webapck --save-dev
安装到项目依赖中
- 初步使用webpck打包构建列表隔行变色案列
import $ form 'jquery'
$('#list li:even').css('backgroundColor','#0f6');
$('#list li:odd').css('backgroundColor','pink');
1. 运行`npm init`初始化项目,使用npm管理项目中的依赖包
2. 创建项目基本的目录结构
3. 使用`npm i jquery --save`(ES6写法)安装jquery类库(`const $ = require("jquery")第二种方法`)
4. 创建`main.js`并书写各行变色的代码逻辑:
5. 直接在页面上引用`main.js`会报错,因为游览器不认识`import`这种高级的js语法,需要使用webpack进行处理,webpack默认会把这种高级的语法转换为低级的游览器能识别的语法;
6. 运行`webpack 入口文件路径 输出文件路径`对`main.js`进行处理;
//webpack 3x 版本
webpack src/js/main.js dist/bundle.js
之后webpack 进入webapck笔记
什么是Vuex
概念:vuex是 vue 配套的公共数据管理工具,它有把一些共享的数据,保存到vuex中,方便整个程序中的任何组件直接获取或修改我们的公共数据;
Vuex是为了保存组件之间共享数据而诞生的,如果组件之间有要共享的数据,可以直接挂载到vuex中,而不必通过 父子组件之间传值了,如果组件的数据不需要共享,此时,这些不需要共享的私有数据,没有必要放到vuex中;
只有共享的数据,才有权利放到vuex中; 组件内部私有的数据,只要放到组件 data 中即可;
props 和 data 和 vuex的区别
Vuex 是一个全局的共享数据存储区域,就相当于一个数据的仓库
使用Vuex
import Vuex from 'vuex'
Vue.use(Vuex)
// 如果在模块化构建系统中,请确保在开头调用了 Vue.use(Vuex)
const store = new Vuex.Store({
state: {
// state 可以想象成 组件中的 data ,专门用来存储数据的
// 如果在 组件中,想要访问,store 中的数据,只能通过 this.$store.state.*** 来访问
count: 0
},
mutations: {
// 注意:如果要操作 stroe 中的 state 值,只能通过 调用 mutations 提供的方法,才能操作定义的数据,不推荐直接操作 state 中的数据,应为万一导致了数据的紊乱,不能快速定位到错误的原因,因为每个组件都有可能操作数据的方法;
// mutations 里的方法第一个参数固定是state
// 在组件中调用mutations中的方法,要使用 this.$store.commit('方法名')
// 传参方法 this.$store.commit('方法名','传参值'),注意mutations内部方法只能有2个参数 如果要传多个就传一个对象
increment (state,a) { //a 接收参数值
state.count++
},
getters: {
//注意:这里的getters,只负责对外提供数据,不负责修改数据,如果想要修改 state 中的数据,请去找 mutations
doneTodos: state => {
return '当前count值是:'+ state.count
}
//getters就相当于是 store 的计算属性, 只要 state 中的数据发生了变化,那么正好 getters 也引用了这个数据,那么就会立即触发 getters 来重新求值
}
}})