Vue基础知识
1.对于MVVM的理解
MVVM就是Model-View -ViewModel的缩写,Model就是数据模型,View就是用户操作界面,View-Model就是业务逻辑层。当View需要什么数据时,ViewModel要提供这个数据,当View需要进行某个操作时,ViewMode需要相应,可以说它就是model for view 。MVVM 在使用中,利用双向绑定技术,使得Model变化时,ViewModel发生更改,ViewModel发生更改时,View发生更改。
2.组件中的传值
1.父传值给子:props / 状态管理器 / 中央控制总线 / solt
父组件在调用子组件的地方,添加一个自定义的属性,属性的值就是你要传递给子组件的数据,如果值是一个变量,那么需要使用到绑定属性,在子组件定义的地方,添加一个props选项接收数据
接收数据有3种方法:
props: ['tip'], //不校验数据的格式
props: { //校验数据的格式
tip: Number
}
props: {
tip: {
type: Number,//校验数据格式
default: 0 //默认值如果为数组或者对象,需要使用函数实现
/**
*type: Array,
*default: function (){
* return [1,2,3]
*}
*/
}
}
2.子传值给父
子组件的某一个事件内部,通过this.$emit('事件名',传递的值)
传递数据
子组件内写一个事件例如:<button @click="sendData">传值给父组件</button>
methods:{
sendData () {
this.$emit('get','hahah')
}
}
父组件在调用子组件的地方,绑定了子组件自定义的事件名,函数体不要加()
定义父组件的地方,实现函数体,函数体会带有默认的参数,参数值就是子组件传递的值
父组件内获取这个事件:<my-banner @get='getData'></my-banner>
methods: {
getData (str) {
console.log(str)
}
},
3.非父子组件间的传值
// 理解: 我们声明了一个bus的Vue实例,跟我们声明的app实例是同一级别的,bus实例相当于一个车,也就是第三方,方便数据交换的。相当于都在全局中
// bus实例中有2个方法bus.$on(),负责监听,bus.$emit()负责触发,
// 当index中的changIndex方法发生改变的,我们把这个改变告诉bus车,
//车收到改变的指令就会触发这个事件,将值发生更改,当this指向它的时候,值就改变了。达到传值的效果。
// 中央事件总线(new Vue()),一方负责监听bus.$on(),一方负责触发bus.$emit()
const bus = new Vue()
const Index = {
template: '#indexTem',
data () {
return {
index: 1
}
},
mounted () {
// 2、监听事件
bus.$on('changeIndex', (index) => { // 如果不用箭头函数 that = this
console.log(index)
// 4、后续业务逻辑
this.index = index
})
}
}
const Banner = {
template: '#bannerTem',
methods: {
getIndex (index) {
// 3、触发事件
bus.$emit('changeIndex', index)
}
}
}
*滚动文档视图或元素时触发事件
EventTarget事件 - scroll
滚动文档视图或元素时会触发scroll事件。
scrollFn () {
if (event.target.scrollTop > 150) { //当滚动的文档视图距离
this.flag = true
} else {
this.flag = false
}
}
},
3.编程式导航和声明式导航
编程式跳转:用于在js中处理逻辑后需要页面进行跳转
vue的路由我们可以看做是一个数组,每次添加一个页面可以看成是向数组中push一个地址,当点击返回时就是向数组中的上一个值查找。
编程式跳转其实就是调用: this.$router.push( )
在li
标签中加入点击函数@click="goDetail(item.id)"
<!-- 编程式跳转 -->
<li class="proitem" v-for="(item, index) of prolist" @click="goDetail(item.id)" :key="index">
<div class="itemimg">
<img :src="item.images.small" :alt="item.alt" />
</div>
<div class="iteminfo">
<h3>{{ item.title }} --- {{ item.rating.average }}</h3>
<div class="directors">
导演:<span v-for="(itm, idx) of item.directors" :key="idx">{{ itm.name }}/</span>
</div>
<div class="casts">
演员: <span v-for="(itm, idx) of item.casts" :key="idx">{{ itm.name }}/</span>
</div>
<Rating :rating="(item.rating.average / 2).toFixed(1)"/>
</div>
</li>
在export default中的methods中加入
goDetail(id) {
//this.$router.push( '/detail/' + id ) //string类型的参数
//this.$router.push( { name: 'detail', params: { id } } ) //object类型参数
this.$router.push( { path: '/detail/' + id } ) //object类型
声明式导航:用于直接渲染到页面中,
声明式跳转中的to参数怎么写,编程式跳转中参数就怎么写
<router-link tag="li" :to="{ name: 'detail', params: { id: item.id } }" class="proitem" v-for="(item, index) of prolist" :key="index">
</router-link>
4.slot内容分发-----插槽
插槽决定了组件中的内容显示还是不显示,如何显示。--------------提高组件复用性
<template>
<header class="header">
<ul>
<li @click="back">
<slot name="left"></slot>
</li>
<li>
<slot></slot>
</li>
<li>
<slot name="right"></slot>
</li>
</ul>
</header>
</template>
<Header>
<div class="searchBox">
<span class="iconfont icon-ai65"></span>
<span class="text">请输入您要搜索的内容</span>
</div>
<p slot="right">消息</p>
<p slot='left'>logo</p>
</Header>
路由别名:alias: '/ho', // 别名 --- 当你访问 /ho 时,其实和访问 /home是一致的
5.动态组件
动态组件让多个组件可以使用同一个挂载点,并动态切换。默认情况下切换时都是先销毁掉原来的组件,再创建新的组件
加入需要保留上一次的结果,避免组件的重新渲染,
可以使用
但是此时又有问题了,之前是全部都销毁了,现在是全部都缓存了
能不能只缓存需要的呢?
定义组件时添加name选项,keep-alive 添加include属性,值为name选项,需要缓存的写进去
keep-alive 会伴随有两个生命周期钩子函数 activated deactivated
activated () { // 激活 后台应用程序正在使用}
deactivated () { // 影藏 在后台应用中,但不是关闭了的(按了home键的)}
<div id="app">
<button @click="type = 'v-aaa'">A组件</button>
<button @click="type = 'v-bbb'">B组件</button>
<button @click="type = 'v-ccc'">C组件</button>
<keep-alive include="aaa,bbb">
<component :is="type"></component>
</keep-alive>
</div>
<keep-alive>
<!-- 如果路由设置了meta,并且keepAlive为true,避免组件的重新渲染 -->
<router-view v-if="$route.meta.keepAlive"></router-view>
</keep-alive>
<router-view v-if = "!$route.meta.keepAlive"></router-view>
在对应的路由位置加上
meta: {
keepAlive: true
}
6.axiso能够拦截请求和响应,自动转化json,客户端支持防XSRF攻击
1.使用axios先安装依赖
$ npm install axios -S
2.多请求并发,可以使用axios.all
function getUserAccount() {
return axios.get('/user/12345');
}
function getUserPermissions() {
return axios.get('/user/12345/permissions');
}
axios.all([getUserAccount(), getUserPermissions()])
.then(axios.spread(function (acct, perms) {
// 两个请求现在都执行完成
}));
3.axios.post请求跨域问题
请求中遇到跨域问题:(解决跨域问题,一是反向代理,而是后端设置。aixos不用写请求头)
最好的办法遇到跨域问题直接交给后端,后端解决跨域。
axios.post('/api/admins', {
username: this.form.username,
password: this.form.password
}).then(res => {
接口中app.js中加入如下代码:
app.all("*",function (req,res,next) {
res.header("Access-Control-Allow-Origin","*");
res.header("Access-Control-Allow-Headers", "X-Requested-With");
res.header("Access-Control-Allow-Methods","PUT,POST,GET,DELETE,OPTIONS");
res.header("X-Powered-By",' 3.2.1');
res.header("Content-Type", "application/json;charset=utf-8");
next();
});
4.封装axios,实现拦截请求和响应
import axios from 'axios';
// 开发环境(start) 生产环境(build) 测试环境(test)
// 如果运行的是 npm run start 则为真其余为假
const isDev = process.env.NODE_ENV === 'developement';
// 自定义配置axios
const ajax = axios.create({
// baseURL: idDev ? 'http://10.11.56.148:3000' : 'https://www.daxunxun.com'
baseURL: isDev ? 'https://www.daxunxun.com' : 'https://www.daxunxun.com',
timeout: 6 * 1000
})
// 添加请求拦截器
ajax.interceptors.request.use(function (config) {
// 在发送请求之前做些什么
// 设置请求头、设置loading动画
console.log('开始加载数据了')
return config;
}, function (error) {
// 对请求错误做些什么
console.log('没有请求到数据')
return Promise.reject(error);
});
// 添加响应拦截器
ajax.interceptors.response.use(function (response) {
// 对响应数据做点什么
console.log('接收到数据了')
return response;
}, function (error) {
// 对响应错误做点什么
console.log('数据接收错误')
return Promise.reject(error);
});
export default ajax;
7.vue设置反向代理
1.直接在config->index.js->proxyTable
proxyTable: {
'/api': {
target: 'http://10.11.56.96:4000', // 跨域地址
changeOrigin: true, // 是否跨域
// secure: false, // 是否使用https
pathRewrite: {
'^/api': ''
}
}
},
2.如果上面方法不行,就去跟目录下引入vue.config
8.首页引导页
动画与定位相关,定位与层级相关,层级与书写顺序相关,后来居上
9.一般在那些情况下使用到vuex
1.当项目中有一些数据需要共享的时候
2.当后端接口还没有写完的时候,我们把数据临时存到vuex中
Vue中遇到的坑
1.路由中路径加斜杆与不加斜杆的区别:
加斜杆表示的是绝对路径,加点表示当前目录下的路径
2.返回到原来页面的位置,页面没有刷新,当是我又需要在一定时间后刷新,怎么去做,比如新闻直播软件,看新闻时间超过一定时间后,首页面更新,不然短时间浏览不更新
3.$.route和this.$router区别
$.route表示当前路由,this.$router表示项目的所有路由数组
this.$router.back(),就是向这个路由数组中找上一个路由$.route
4.user-scable='no'不允许用户点击放大
5.watch侦听
watch侦听的是进入路由后侦听属性的改变,比如说user->user/login这样会侦听到路由的改变,但是如果user->home页面这样离开了user页面就不能侦听了,它可以侦听这个路由下的属性,和子路由的变化。而beforeRouteEnter侦听的是跳转到其他路由前的钩子函数。