目录
数据代理
vue中的数据代理:通过一个对象去对另一个对象属进行操作。
实现原理是通过es6中的Object对象的defineProperties方法实现的。
Object.defineProperty(obj, prop, desc)
-
obj 需要定义属性的当前对象
-
prop 当前需要定义的属性名
-
desc 属性描述符
在defineProperties中其中desc是一个对象;里面有很多的配置项
-
value:设置属性的值
-
enumerable:控制属性是否可以枚举;默认是false
-
writeable:控制属性可以是否被修改;默认是false
-
configurable:控制属性是否可以被删除;默认是false
-
get()函数:当有人读取对象是时,get函数就会被调用
-
set()函数:当有人修改对象时,set函数就会被调用
所以说vue中使存在数据代理的,如果没存在的话,data中的数据修改之后,页面不会进行响应式的改变的。这就是vue里面数据代理的好处。
事件处理
事件、修饰符、键盘事件
-
点击事件:v-on:click="" -----> 可以简写为: @click=""
-
修饰符:(可以连着写)
-
.prevent: 阻止默认行为(常用)
-
.stop:阻止事件冒泡(常用)
-
.once:事件只触发一次(常用)
-
.capture:事件的捕获模式
-
.self:只有event.target是当前操作的元素是才触发事件
-
passive: 事件的默认行为立即执行,无需等待事件回调执行完毕
<h1 @click="say2"> <span @click.stop="say1">aaa</span> </h1>
-
-
滚动事件:
-
@scroll 是元素滚动就会触发事件
-
@wheel是鼠标滚动就会触发事件
-
-
键盘事件:
-
@keydown.enter:表示当按下键盘enter键的时候触发事件
-
@keyup
-
获取键盘的编码,e.keyCode
-
获取键盘的名字:e.key
-
按键别名:
-
回车---enter
-
删除---delete
-
退出---esc
-
空格---space
-
换行---tab
-
上-----up
-
下----down
-
左----left
-
右----right
<input type="text" @keydown.enter="getMsg" v-model="msg">
-
-
系统修饰键用法特殊:ctrl、alt、shift、win
-
配合keyup使用:按下修饰键的同时,再按下其他键,随后释放其他键,事件才被触发。
-
配合keydown使用:正常触发事件。
-
-
Vue的methods
在vue中方法可以拿到event对象,也就是点击的事件;
event.target:获取点击的对象。
注意:如果你需要传递自己的参数,并且需要使用事件对象,那么必须在函数那些个占位符$event
<button @click="fn1"> 点击 </button>
<button @click="fn2(666,$event)"> 点击 </button>
<script>
const vm = new Vue({
el: '#app',
methods: {
fn1(event){
console(event.target.innerHTML)
},
fn2(a, event){
console(a,event)
}
}
})
</script>
表单绑定(获取数据)
获取表单输入的值
<div id="app">
<input type="text" v-model="msg">
<br><br>
{{msg}}
<hr>
<input type="checkbox" v-model="check"> 记住用户名
<br><br>
{{check}}
<hr>
<h2>您的兴趣爱好</h2>
<input type="checkbox" v-model="Arrbox" value="vue">vue
<input type="checkbox" v-model="Arrbox" value="react">react
<input type="checkbox" v-model="Arrbox" value="小程序">小程序
<br><br>
{{Arrbox}}
<hr>
<h2>单选按钮</h2>
<input type="radio" value="男" name="sex" v-model="sex"> 男
<input type="radio" value="女" name="sex" v-model="sex"> 女
<br><br>
{{sex}}
<hr>
<select name="" id="" v-model="option">
<option value="岳麓区">岳麓区</option>
<option value="天心区">天心区</option>
<option value="芙蓉区">芙蓉区</option>
</select>
{{option}}
</div>
<script>
var vm = new Vue({
el:"#app",
data:{
msg:"",
check:true,
//多选绑定数组
Arrbox:[],
sex:'',
option:'岳麓区'
}
})
</script>
表单修饰符
-
lazy:修饰符,懒惰的
-
number:显示输入的东西为数字类型的
-
trim:去除首位空格
<input type="text" v-model.lazy="uname"> //反应更慢一点
<input type="number" v-model.number="uage"> //限制输入的类型为数字型的
<input type="text" v-model.trim="num"> //去除首位空格
过滤器filters
相当于对数据进行格式化处理的。(在vue3中已经被废除)
<p> {{uname | capitalize}} // uname:是data中的数据 // capitalize:是处理uname数据的函数 </p>
计算属性
就是使用computed配置项
我们在使用计算属性的配置对象的时候,如果是简单的获取数据只需要直接写方法就行,但是如果需要修改计算属性里面的方法时候,就需要get()和set()方法了。
监视属性
watch,监视属性的改变。
<script type="text/javascript"> const vm = new Vue({ el: '#app', data: { weather: true }, methods:{ change(){ this.weather = !this.weather } }, computed:{ ishot(){ return this.weather ? '凉爽':'炎热' } }, watch:{ weather:{ handler(newV,oldV){ if(newV == true){ console.log("之前的天气为炎热,现在的天气为凉爽"); }else{ console.log("之前的天气为凉爽,现在的天气为炎热"); } } } } }) </script>监视属性里面的配置项:
handler(){} 当检测的属性发生变化的时候,函数就会被调用
immediate: false 初始化的时候就执行handler一次。默认值为false
deep:false。默认为false开启深度检测 ,一般使用的是如果侦听的是一个对象里面属性的变化的话,这个时候就需要开启深度侦听了。
注意:如果是侦听一个对象的子属性的话,就需要包裹一层单引号
watch:{ 'ifo.uname'(newval){ console.log(newval) } }
绑定class样式
字符串形式, 直接在标签里面绑定样式:class
数组形式,通过把class类名放在数组里面,绑定这个数据 。:class="arrClass"
对象形式,通过对象绑定类名,对象里面的类名用true和false决定
axios
-
axios.get()
-
axios.post()
-
axios.put()
-
axios.delete()
axios是一个专注于网络请求的库。
axios的基本使用
axios({
method:"",
url:"",
//url的查询参数
params:{},
//提交数据的时候给的参数
data:{}
}).then(function(){
})
axios({
method:"GET",
params:{
id:"001"
},
url:"http://localhost:3000/students"
}).then(function(res){
console.log(res.data);
})
使用axios在返回数据回来的会给我们包裹一层壳
{
config:{},
data:{真实数据},
headers:{},
status:xxx,
statusText:''
}
axios的简单使用 axios.get() axios.post()
axios.get("url", {
//get传递的数据
params:{}
})
axios.post("url",{
//post提交数据
name:"张三",
age:20
})
Vue-cli创建页面
vue-cli是Vue.js开发的标准工具。它简化了程序员基于webpack创建工程化的Vue项目的过程。
1| vue i @vue/cli -g 2| vue -V //检测vue-cli安装完成 3| vue create 项目名称 4| npm run servevue-cli项目的解析
1| assets文件夹:存放项目中用到的静态资源文件,例如: css样式表、图片资源 2| components文件夹: 程序员封装的、可复用的组件,都要放到components目录下 3| main.js是项目的入口文件。整个项目的运行,要先执行main.js 4| App.vue是项目的根组件。
Vue组件的引入
<div>
<h1>App Vue 根组件</h1>
<hr>
<Left></Left>
<Right></Right>
</div>
</template>
<script>
import Left from '@/components/Left.vue'
import Right from '@/components/Right.vue'
export default {
components:{
Left,
Right
}
};
</script>
四个步骤:
-
创建组件
-
在需要使用的组件中导入,
import Left from '@/components/Left.vue'
-
注册组件通过js当中的component的部分
-
使用组件
全局组件的注册
私有组件的注册,只有是引用了该组件才可以使用。当没有引入该组件则不可以使用。但是当我们注册的组件是全局组件
那么每个组件不管有没有引用注册该组件,都能使用该组件
。
注册全局组件步骤:(注意组件自己不要使用自己)
-
创建组件。
-
在main.js入口文件中,导入被创建好的全局组件。
-
通过
Vue.conponent('为组件起的名字', 组件名字)
方法,可以注册全局组件。 -
在需要使用的组件中,直接写全局组件的名称。
-
// 全局组件的引入 import All from '@/components/All.vue' Vue.component("MyAll", All)
组件style标签
每个组件都有自己的script标签和style标签。当我们在给组件设置样式的时候,其他组件也有相同的标签的时候,样式会影响其他组件的样式,所以我们一般会给当前组件style标签加上scoped
。
<style lang="less" scoped>
h1 {
margin: 0;
font-size: 15px;
color: #fff;
}
</style>
但是如果我们设置一个组件中的引入组件,引入组件需要个别设置样式那就需要增加 /deep/
<style lang="less" scoped>
div {
flex-grow: 1;
background-color: pink;
padding: 20px;
}
/deep/ button {
background-color: orange;
}
</style>
ref属性
ref获取DOM元素
在每个vue实例中都有$refs对象,里面存储着对应的DOM元素或组件的应用.默认情况下,组件的$refs指向一个空的对象
<template>
<div id="app">
<h1 ref="title">我是一个标题</h1>
<button @click="showTitle">点击我获取标题</button>
</div>
</template>
<script>
export default {
methods:{
showTitle(){
console.log(this.$refs.title);
}
}
}
</script>
注意:当ref在标签里面有相同的属性值的情况,会以最后一个为主。
使用方式:
-
打标识:<h1 ref="xxx">我是一个标题</h1>或者 <School ref="xxx"></School>
-
获取:this.$refs.xxx
ref不仅仅可以获取DOM元素还可以获取组件实例.
组件之间的传值
父传子(props)
父传子:采用的是props
//父组件-组件的使用者 <template> <div> <h1>left</h1> <hr> <MyAll :init="18"></MyAll> </div> </template> //子组件-组件的封装者 <template> <div> {{init || 0}} </div> </template> <script> export default { props: ['init'], } </script>
props的使用注意点:props只读,不建议修改。如果需要使用props的值,我们可以把这个props的值赋给其他的值。
<template> <div> <h1>All组件</h1> <br> count的值为: {{count}} <br><br> <button @click="count++">+1</button> </div> </template> <script> export default { props: ['init'], data() { return { count: this.init || 0, }; }, }props的几种使用方式:
props的数组方式:直接用数组。
props: ['name', 'age', 'sex']props的对象写法:限制接受过来数据的类型,如果传过来的数据不是对应的数据,就会报错。
props: { name: String, age: Number, sex: String }props对象的详细写法:针对每个属性都有自己的配置项。
props: { name:{ type: String, required: true }, age: { type: Number, default: 40 }, sex: { type:String, require: true } }type:表示传入数据的类型
required:表示该传入的数据是必须要传的值
default:表示不传入值,有默认的值。
一般required和default不会同时出现
注意:父传子通过props传入过来的值,最好是不要直接修改props的值,如果需要修改,应当利用一个变量接收props,再去修改那个变量。
子传父
子组件向父组件传递数据要通过自定义事件。
子组件通过$emit this.$emit("sendMsg", this.msg)
兄弟组件的传值
通过事件车去实现兄弟组件之间的传值
main.js import Vue from 'vue' import App from './App.vue' Vue.config.productionTip = false new Vue({ render: h => h(App ), beforeCreate() { Vue.prototype.$bus = this }, }).$mount('#app')
哥哥组件
<template> <div> <div class="contain"> <h1>自己的姓名:{{sonName}}</h1> <h3>我的父亲是:{{fname}} </h3> <h4>弟弟的名字:{{litterBrather}} </h4> <button @click="send">点击告诉父亲我的姓名</button> </div> </div> </template> <script> export default { props:['fname', 'getSon'], data() { return { sonName: '唐三', litterBrather:'' } }, methods: { send(){ this.getSon(this.sonName) }, }, mounted(){ // 绑定事件 this.$bus.$on('getBratherName',(name)=>{ // console.log('我是哥哥,收到了弟弟的名字', name); this.litterBrather = name }) } } </script> <style scoped> * { box-sizing: border-box; } .contain { width: 400px; background-color: pink; border-radius: 20px; overflow: hidden; padding: 20px; } button { padding: 10px; border: 5px solid skyblue; border-radius: 20px; background-color: #fff; } </style>
弟弟组件
<template> <div> <div class="contain"> <h1>自己的姓名:{{sonName}}</h1> <button @click="sendTwoName">把自己的名字给父亲</button> <button @click="unbind">解绑事件</button> <button @click="sendBratherName">把自己的名字告诉哥哥</button> </div> </div> </template> <script> export default { data() { return { sonName: '小三' } }, methods: { sendTwoName(){ this.$emit('cha', this.sonName); }, unbind(){ // 解绑一个自定义事件 this.$off('cha'); // 解绑多个自定义事件 // this.$off(['cha', 'demo']); // 所有的自定义事件全部解绑 // this.$off(); }, sendBratherName(){ this.$bus.$emit('getBratherName', this.sonName); } }, mounted(){ } } </script> <style scoped> * { box-sizing: border-box; } .contain { width: 400px; background-color: salmon; border-radius: 20px; overflow: hidden; padding: 20px; margin: 20px 0; } button { padding: 10px; border: 5px solid skyblue; border-radius: 20px; background-color: #fff; display: block; margin: 20px 0 ; } </style>
组件的生命周期
beforeCreate:组件的props/data/methods尚未被创建,都处于不可用状态。(初始化事件)
create d:组件的props/data/methods都已经创建好,都处于可用状态。但是组件的模板结构(DOM)尚未生成。(发送ajax请求拿数据)
beforeMount:将要把内存中编译好的HTML结构渲染到浏览器中,此时浏览器中还没有当前组件的DOM结构。
mounted:已经把内存中的HTML结构,成功渲染到浏览器之中了。此时浏览器中已然包含了当前组件的DOM结构。
beforeUpdate:当数据发生改变的时候就会触发。数据是最新的但是拿到的DOM结构中的数据是旧的。
updated: DOM结构和data的数据都已更新同步。(最新的DOM结构)。
beforeDestroy:将要销毁,但是还没销毁。组件还处在工作状态。
destroyed:组件已经被销毁,组件在浏览器中对应的DOM结构已经被完全移除。
$nextTick()
每个组件身上都有$nextTick()里面接收一个回调函数。
主要的作用就是延迟执行$nextTick中的代码,待页面的DOM元素渲染完成再去执行其中的代码。
简单来说:等组件的DOM更新完成之后,再执行回调函数,从而保证回调函数可以操作最新的DOM元素。
this,$nextTic(()=>{ this.$refs.iptRef.focus() })
动态组件
动态组件:动态的切换组件的显示与隐藏
<components is="Left"></components> //标签是占位符的意思,is属性是将哪个组件渲染在此 //<components></components> 是 vue 的内置标签,作用:组件的占位符。简单实现组件的动态切换:
<template> <div id="app"> <h1>App</h1> <hr> <button @click="whichComponent = 'Left'">展示Left组件</button> <button @click="whichComponent = 'Right'">展示Right组件</button> <br><br> <div class="contain"> <components :is="whichComponent"></components> </div> </div> </template> <script> import Left from '@/components/Left.vue' import Right from '@/components/Right.vue'; export default { components: { Left, Right }, data() { return { whichComponent: 'Left', }; }, } </script>
有些时候我们在切换组件的时候之前组件的数据依然能够保存,这个时候就是需要使用我们的
keep-alive
去保持组件的状态<template> <div id="app"> <h1>App</h1> <hr> <button @click="whichComponent = 'Left'">展示Left组件</button> <button @click="whichComponent = 'Right'">展示Right组件</button> <br><br> <div class="contain"> <keep-alive> <components :is="whichComponent"></components> </keep-alive> </div> </div> </template>
<keep-alive></keep-alive>原理:
使用keep-alive标签可以使组件在被切换的时候不被销毁而是被缓存,这样就不会销毁组件的数据了。
keep-alive对应的生命周期函数
当组件被缓存时,会自动触发组件的deactivated生命周期函数。
当组件被激活时,会自动触发组件的activated生命周期函数。
keep-alive标签的
include
属性主要是设置哪些组件需要缓存的。include的属性值是包含哪些需要缓存的组件。
<keep-alive include="Left,Right"> <components :is="whichComponent"></components> </keep-alive>keep-alive标签的
exclude
属性排除哪些组件不需要缓存的。
注意!!
include和exclude不能同时使用。
组件的name选项
当我们给组件一个name属性之后,组件在调试工具中显示的就是name的属性值。就相当于组件的名字就是name的属性值。
插槽
插槽(Slot) 是vue为组件的封装者提供的能力。允许开发者在封装组件时,把不确定的、希望由用户指定的部分定义为插槽。
v-slot简写形式--#
<template #p> <p> Lorem ipsum dolor sit amet consectetur adipisicing elit. Debitis,vel. </p> </template>
slot标签的name默认值为default。
slot标签可以传递值(作用域插槽)
<slot name="p" msg="aaaa"></slot> <Left> <template v-slot:p="obj"> <p> Lorem ipsum dolor sit amet consectetur adipisicing elit. Debitis, vel. <span>{{obj.msg}}</span> </p> </template> <img slot="img" src="@/assets/logo.png" width="100" /> </Left>
私有自定义指令
自定义指令:
私有自定义指令
全局自定义指令
私有自定义指令使用方法:
在js中增加
directives
配置项.给自定义指令取名字.
给标签使用自定义指令
<template> <div id="right"> <h1>right---{{ reduce }}</h1> <p v-color="tetxColor">啊啊啊 {{reduce}} </p> <p v-color="c">啊啊啊 {{reduce}} </p> <button @click="c = 'skyblue'">改变颜色</button> <p v-color="blue">测试</p> </div> </template> <script> export default { data() { return { reduce: 100, tetxColor:'blue', c:'orange' }; }, // 私有自定义指令 directives: { // 自定义指令的名字 color:{ // 当使用到自定指令的时候,就会立即执行bind方法,其中接收一个参数为只用自定义组件的DOM结构 // el为使用指令的DOM结构(形参随意就行) // 自定义指令可以传递参数,bind中第二个参数就是来接收参数的(对象) bind(el,binding){ console.log(el); el.style.color = binding.value }, update(el, binding) { el.style.color = binding.value; }, } }, }; </script>
bind()函数的缺点:当指令第一次被绑定到元素上的时候,会立即触发bind 函数.
只能触发一次
这个时候就可以就需要用到我们自定义指令中的update方法了
自定义指令的简写
<template> <div id="right"> <h1>right---{{ reduce }}</h1> <p v-color="tetxColor">啊啊啊 {{ reduce }}</p> <p v-color="c">啊啊啊 {{ reduce }}</p> <button @click="c = 'skyblue'">改变颜色</button> <button @click="reduce--">-</button> </div> </template> <script> export default { data() { return { reduce: 100, tetxColor: "blue", c: "orange", }; }, // 私有自定义指令 directives: { color(el,binding){ el.style.color = binding.value; } }, }; </script
全局自定义指令
//直接在main.js中定义全局自定义指令 Vue.directive('backgroundColor', function(el,binding){ el.style.background = binding.value })自定义指令一般来说是全局的自定义指令
全局导入axios
直接在main.js中导入axios,把axios直接挂在在Vue的原型身上这样的话,全局都可以直接使用axios不需要再去导入了.
import Vue from 'vue' import App from './App.vue' import axios from 'axios' Vue.config.productionTip = false // 直接把axios挂载在原型身上,那么每个组件的实例对象都能访问到axios // 不过一般来说我们取名字的话都习惯性的取 $http 而不是axios // Vue.prototype.axios = axios Vue.prototype.$http = axios new Vue({ render: h => h(App) }).$mount('#app')
axios默认请求路径设置
在我们发起axios请求的时候,可能多个组件都需要使用发起请求,那么这个时候请求路径要写多次,万一还需要修改的话,就不利于后期维护,所以我们可以在发起axios请求的时候,设置axios的默认请求路径
但是我们把axios直接挂载在原型上有一个缺点:
不利于axios API的复用
路由
路由:对应关系的组件 类似于a链接。
-
用户点击了页面上的路由链接
-
导致了URL地址栏中的Hash值发生了变化
-
前端路由监听了到Hash地址的变化
-
前端路由把当前Hash地址对应的组件渲染都浏览器中
安装路由:
npm i vue-router@3.5.2 -S
安装配置完Vue之后,可以直接使用<router-view></router-view>,这个标签是用来占位路由的展示区域的
<router-link to="/home">首页</router-link>
<router-link to="/movie">电影</router-link>
<router-link to="/about">关于</router-link>
<hr>
<router-view></router-view>
路由高亮显示
//使用router-link-active类名 //我们也可以自己自定义名字,就只需要给router-link标签增加一个active-class类名就成.
.router-link-active {
color: pink;
}
<ul>
<li><router-link active-class="cha" to="/films">电影</router-link></li>
<li><router-link active-class="cha" to="/cinemas">影院</router-link></li>
<li><router-link active-class="cha" to="/center">我的</router-link></li>
</ul>
<style>
.cha {
color: pink;
}
</style>
// tag属性 将touter-link标签(a标签),设置为其他的你需要的标签 <router-link active-class="cha" tag="li" to="/films">电影</router-link> 表示a标签转成li标签(但是tag属性在vue4中会被移除,)
路由配置
import Vue from 'vue'
import VueRouter from 'vue-router'
// 导入需要展示的组件
import Home from '@/components/routers/HomeDemo.vue'
import Movie from '@/components/routers/MovieDemo.vue'
import About from '@/components/routers/AboutDemo.vue'
Vue.use(VueRouter)
const router = new VueRouter({
// routes 是一个数组用来定义hash地址与组件的对应关系
routes: [
{
path: '/',
component: Home
},
{
path: '/home',
component: Home
},
{
path: '/movie',
component: Movie
},
{
path: '/about',
component: About
}
]
})
export default router
路由的重定向
重新制定路由的跳转位置
routes: [
{
path: '/',
redirect: Home
},
]
嵌套路由
import Vue from 'vue'
import VueRouter from 'vue-router'
// 导入需要展示的组件
import About from '@/components/routers/AboutDemo.vue'
// 子路由
import Tab1 from '@/components/routers/tabs/TabDemo1.vue'
import Tab2 from '@/components/routers/tabs/TabDemo2.vue'
Vue.use(VueRouter)
const router = new VueRouter({
// routes 是一个数组用来定义hash地址与组件的对应关系
routes: [
{
path: '/about',
component: About,
children: [
{
path: 'tab1',
component: Tab1
},
{
path: 'tab2',
component: Tab2
}
]
}
]
})
export default router
<template>
<div class="about">
<h1>About</h1>
<router-link to="/about/tab1">tab_1</router-link>
<router-link to="/about/tab2">tab_2</router-link>
<hr>
<router-view></router-view>
</div>
</template>
子路由的重定向
{
path: '/about',
component: About,
redirect: '/about/tab1',
children: [
{
path: 'tab1',
component: Tab1
},
{
path: 'tab2',
component: Tab2
}
]
}
或者
{
path: '/about',
component: About,
redirect: '/about/tab1',
children: [
{
path: '',
component: Tab1
},
{
path: 'tab2',
component: Tab2
}
]
}
//默认子路由:如果children 数组中,某个路由规则的path 值为空字符串,则这条路由规则,叫做“默认子路由”
用默认子路由的话,组件的路径就需要改正
<template>
<div class="about">
<h1>About</h1>
<router-link to="/about">tab_1</router-link>
<router-link to="/about/tab2">tab_2</router-link>
<hr>
<router-view></router-view>
</div>
</template>
编程式路由
-
$router.push('/films') 有历史记录
-
$router.replace('/films') 没有历史记录
动态路由
动态路由指的是:把Hash地址中可变的部分定义为参数项,从而提高路由规则的复用性。 在vue-router中使用英文的冒号(:) 来定义路由的参数项。示例代码如下
{ path: '/movie/:mid', component: Movie },
这样的传递参数组件可以通过$route去拿到这个参数
或者可以直接开启props传递参数
命名路由
在路由规则中,可以给路由增加name属性,表示路由具有名字.那么我们以后进行路由跳转的话,不仅可以使用path进行跳转name同样也是可以进行跳转的.
methods: {
toDetail(id){
// 通过路径跳转
// this.$router.push(`/detail/${id}`)
//通过name跳转
this.$router.push({
name: 'chaDetail',
params: {
id
}
})
}
}
{
name: 'chaDetail', // 命名路由
path: '/detail/:id',
component: Detail
},
路由模式
路由模式:
-
hash模式(带#号)
-
history模式(不带#号)
具体操作,只需要在路由匹配规则中设置
const router = new VueRouter({
mode: 'history',
routes
})
注意:history要想更完美,还需要后台配置支持。因为我们的应用是个单页客户端应用,如果后台没有正确的配置,当用户在浏览器直接访问
http://oursite.com/user/id就会返回404,这就不好看了。
#
全局路由设置
全局路由设置,只需要在路由配置中index.js
中配置就没问题了。
router.beforeEach((to, from, next) => {
if(to.meta.isJudge){
console.log('请先登录');
}else {
next()
}
})
局部路由设置
只需要在路由配置中,路由模块所需要的
路由懒加载
当我们写项目的时候路由组件太多,如果我们使用平常的直接在路由配置中
导入组件,那么大量的路由组件在服务器一加载的时候就会被使用,这样用户在使用的时候就会出现页面卡顿的情况,这样的话用户体验感就是不太好,所以我们就需要使用路由的懒加载.
路由的懒加载
跟我们平常导入路由组件不一样.
{
path: '/cinemas',
component: ()=>import("@/views/Cinemas.vue")
},
mixin混入
复用组件内容
当不同组件之间某些功能是一样的情况,这样的话,就可以把一样的内容(方法)单独拿出来,然后用混入的方法去使用,增加代码的复用性。
组件的局部混用
单独一个组件的混入
mixin.js
export const mixin = {
methods:{
getName(){
console.log(this.name);
}
}
}
school.vue
<script>
import {mixin} from '../mixin'
export default {
data() {
return {
msg: '学校信息',
name: '长沙学院',
address: '长沙',
}
},
mixins: [mixin]
}
</script>
混合里面如果混入里面的数据和本身数据发生冲突的时候,以自己为主,但是生命钩子函数的时候就是两者都会使用到
组件的全局混入
每个组件的混入
如果需要写的混入代码每个组件都需要混入进去的话,那么直接在main.js中引入混入,那么全部的组件都会混入这些内容。
import Vue from 'vue'
import App from './App.vue'
// 混入
import {a} from './mixin'
Vue.mixin(a)
Vue.config.productionTip = false
new Vue({
render: h => h(App),
}).$mount('#app')
vue中的插件
插件用来增强vue
插件的本质是一个对象,里面要包含着install方法,其中可以获取参数Vue。
Vue动画
使用transition标签
vue中的动画,是自己写好css的动画,然后通过vue中的 transition标签来控制。
通过css书写关键帧来实现。
<template>
<div>
<h1>动画</h1>
<button @click="isShow = !isShow">显示/隐藏</button>
<transition name="cha" appear>
<h2 v-show="isShow">Fighting!!</h2>
</transition>
</div>
</template>
<script>
export default {
data() {
return {
isShow: true
}
},
}
</script>
<style scoped>
h2 {
width: 400px;
height: 50px;
background-color: rgb(209, 117, 209);
text-align: center;
line-height: 50px;
}
/* 来的时候实现的动画 */
.cha-enter-active {
animation: move .5s linear;
}
/* 去的时候实现的动画 */
.cha-leave-active {
animation: move .5s linear reverse;
}
@keyframes move {
from {
transform: translateX(-100%);
}
to {
transform: translateX(0);
}
}
</style>
transition里面的配置项:
name:控制动画类名,默认是v-开头,如果你通过name设置了之后,那么就会以你设置的开头 cha-
appear: 一运行就有动画的展示。默认是false
利用过渡实现动画
<template>
<div>
<h1>动画</h1>
<button @click="isShow = !isShow">显示/隐藏</button>
<transition name="cha" appear>
<h2 v-show="isShow">Fighting!!</h2>
</transition>
</div>
</template>
<script>
export default {
data() {
return {
isShow: true,
};
},
};
</script>
<style scoped>
h2 {
width: 400px;
height: 50px;
background-color: rgb(209, 117, 209);
text-align: center;
line-height: 50px;
}
.cha-enter-active {
transition: 1s;
}
.cha-leave-active {
transition: 1s;
}
.cha-enter {
transform: translateX(-100%);
}
.cha-enter-to {
transform: translateX(0);
}
.cha-leave {
transform: translateX(0);
}
.cha-leave-to {
transform: translateX(-100%);
}
</style>
配置代理(一)
解决跨域问题
当vue里面去请求数据的时候,请求的数据的地址和本机地址不是一个地址,就会出现跨域,就获取不到数据。
在vue.config.js里面配置代理
vue.config.js
const { defineConfig } = require('@vue/cli-service')
module.exports = defineConfig({
transpileDependencies: true,
lintOnSave: false,
devServer: {
// 告诉代理服务器,待会把请求转发给谁
proxy: 'http://localhost:5000'
}
})
请求的vue
<template>
<div>
<h1>发送axios请求</h1>
<button @click="getStudent">请求学生信息</button>
</div>
</template>
<script>
import axios from 'axios'
export default {
data() {
return {
}
},
methods: {
getStudent(){
axios.get('http://localhost:8080/user').then(
res=>{
console.log('请求成功',res.data);
},
err=>{
console.log('sorry,请求失败',err.message);
}
)
}
}
}
</script>
配置代理(二)
代理一的缺点(•́へ•́╬)
只适合配置一个代理,当有多个服务器需要请求的话,代理一就没有办法实现了。
不能控制请求的地址是否走代理。当本地资源有这个文件的名字时,就会优先请求本地的资源
完整的配置代理
vue.config.js
const { defineConfig } = require('@vue/cli-service')
module.exports = defineConfig({
transpileDependencies: true,
lintOnSave: false,
devServer: {
proxy: {
'/api': {
//转发给接口
target: 'http://localhost:5000',
pathRewrite:{'^/api': ''}
}
}
}
})
请求的vue
<template>
<div>
<h1>发送axios请求</h1>
<button @click="getStudent">请求学生信息</button>
</div>
</template>
<script>
import axios from 'axios'
export default {
data() {
return {
}
},
methods: {
getStudent(){
//朝自己发请求
axios.get('http://localhost:8080/api/user').then(
res=>{
console.log('请求成功',res.data);
},
err=>{
console.log('sorry,请求失败',err.message);
}
)
}
}
}
</script>
为了解决请求的地址是否走代理,就是在配置代理的时候设置前缀,但是有了前缀,我们请求的地址就会不一样。
这个时候我们就需要在配置代理中设置 pathRewrite这个配置项。重写路径。
插槽
在组件标签里面写内容
插槽的使用:通过slot
标签的使用来设置插槽。
默认插槽
app.vue
<template>
<h1>vue中的插槽</h1>
<div class="main">
<Slot title="美食" :list="foods">
<img src="https://cdn.cnbj1.fds.api.mi-img.com/mi-mall/b8259e8fb355acf168c66f75d375c6af.jpg?thumb=1&w=250&h=250&f=webp&q=90" alt="">
</Slot>
<Slot title="游戏" :list="games"></Slot>
<Slot title="电影" :list="films"></Slot>
</div>
</template>
slot.vue
<template>
<div>
<div class="box1">
<h2>{{ title }}分类</h2>
<slot>
<ul>
<li v-for="(item, index) in list" :key="index">{{ item }}</li>
</ul>
</slot>
</div>
</div>
</template>
使用插槽slot标签,讲所需要插槽的代码写在组件标签中,然后在所需要的结构中通过
slot
标签来挖坑放代码。如果不写slot标签的话,那么在组件标签里面写的代码是显示不出的。
slot
标签里面还可以写内容,当组件标签没有写结构内容的时候,就会显示slot标签里面的内容;反之传了内容就会显示传入的结构。
具名插槽
具有名字的插槽
当要去使用多个插槽的时候那么就需要给插槽命名;通过
slot
标签中的name
属性给插槽命名。
app.vue
<template>
<div class="all">
<h1>vue中的插槽</h1>
<div class="main">
<Slot title="美食" :list="foods">
<img slot="top" src="https://cdn.cnbj1.fds.api.mi-img.com/mi-mall/b8259e8fb355acf168c66f75d375c6af.jpg?thumb=1&w=250&h=250&f=webp&q=90" alt="">
<a href="" slot="botton">底部</a>
</Slot>
<Slot title="游戏">
<ul slot="top">
<li v-for="(g, index) in games" :key="index">{{ g }}</li>
</ul>
</Slot>
<Slot title="电影">
<template v-slot:top>
<ul>
<li v-for="(f, index) in films" :key="index">{{ f }}</li>
</ul>
</template>
</Slot>
</div>
</div>
</template>
slot.vue
<template>
<div>
<div class="box1">
<h2>{{ title }}分类</h2>
<slot name="top"></slot>
<slot name="bottom"></slot>
</div>
</div>
</template>
当使用
template
标签的时候可以把slot="top"
换成v-slot:top
这个是template
标签的特别的使用。
作用域插槽
.....
betterScroll
主要完成的功能需要包含Better-Scroll实现页面中拖动滚动、拉动属性等功能
new BetterScroll('.box', { // 加上滚动条 scrollbar: { fade: true } })
vant组件库
常用于移动化开发。
Vuex
专门在Vue中实现集中式状态(数据)管理的一个Vue插件,对vue应用中多个组件的共享状态进行集中式的管理(读/写),也是一种组件间通信的方式,且适用于任意组件间的通信。
数据的集中式管理.
<script> import {mapState} from 'vuex' export default { data() { return { n: 1, }; }, computed: { /* ...mapState({ he: 'sum', age: 'age', gender:'gender' }) */ ...mapState(['sum','age','gender']) }, methods: { add() { this.$store.commit('Add', this.n) }, reduce() { this.$store.commit('Reduce', this.n) } }, mounted() { var a = mapState(['he','age']) console.log(a); } } </script>