1. 组件的data为什么必须是函数?
组件中的 data 写成一个函数,数据以函数返回值形式定义,这样每复用一次组件,就会返回一份新的 data ,类似于给每个组件实例创建一个私有的数据空间,让各个组件实例维护各自的数据。而单纯的写成对象形式,就使得所有组件实例共用了一份data,就会造成一个组件的值发生改变,全部组件都会变的结果。
这样的好处就是每各个组件可以维护各自的数据,如果 data 是一个对象则会影响到其他组件。
2. 问 v-if 和 v-show 有什么区别?
相同点:v-if与v-show都可以动态控制dom元素显示隐藏
不同点:v-if隐藏是将dom元素整个删除,而v-show隐藏则是为该元素添加css--display:none,dom元素还在。
3. vue几种常用的指令
v-text:元素的innerText属性(不带标签)
v-html:元素的innerHTML属性(带标签)
v-bind:绑定属性
v-on:绑定事件,绑定的事件从methods中获取
事件修饰符
.stop:阻止冒泡,调用 event.stopPropagation()
.prevent:阻止默认事件,调用 event.preventDefault()
.capture:添加事件侦听器时使用事件捕获模式
v-model
作用:在表单元素上创建双向数据绑定
说明:监听用户的输入事件以更新数据
所谓的双向绑定,就是你在view视图层里面改变了值,vue里面对应的值也会改变。只能给具备value属性的元素进行双向数据绑定。
v-if 和 v-show
条件渲染
v-if:根据表达式的值的真假条件,销毁或重建DOM元素
v-show:根据表达式之真假值,切换元素的 display: block/none 属性
v-for
作用:基于源数据多次渲染元素或模板块,使用 v-for 的时候提供 key 属性,可以提高列表渲染的效率,提高页面的性能。
v-once 提升性能
说明:只渲染元素和组件一次。随后的重新渲染,元素/组件及其所有的子节点将被视为静态内容并跳过。这可以用于优化更新性能。
4. 对于Vue是一套渐进式框架的理解
Vue.js是一个渐进式框架,只需要具备基本的HTML/CSS/JavaScript基础就可以快速上手。在用Vue.js构建大型应用时推荐使用NPM安装,但是需要注意npm的版本需要大于3.0。
在通过npm安装项目后,我们需要对其目录进行解析:
(1) build:项目构建(webpack)相关代码;
(2) config:配置目录,包括端口号等。
(3) node_modules:npm加载的项目依赖模块
(4) src:这个目录当中的内容包含了我们基本上要做的事情,这里包含了几个文件:
(一)assets:存放图片
(二)components:存放组件文件
(三)App.vue:项目入口文件,组件也可以直接写在这里不适用components
(四)main.js:核心文件
(5) static:静态资源目录
(6) test:初始测试目录
(7) .xxxx:配置文件,包括git配置和语法配置等
(8) index.html:首页
(9) package.json:项目配置文件
(10) README.md:说明文档
Vue的mvvm框架给了前端一种思路:完全基于数据驱动,帮助你从繁杂的dom操作中解脱出来
使用Vue的过程就是定义MVVM各个组成部分过程的过程:
(1) 定义View
(2) 定义Model
(3) 创建一个Vue实例或“ViewModel”
在创建Vue实例的时候,需要传入选项对象,可以包含挂载元素、数据等。
Vue实例被创建前会经过初始化,然后在数据变化时更新DOM,在这个期间也会调用一些生命周期钩子,从而我们可以自定义逻辑。总共可以分为8个段:
(1) beforeCreate 初始化实例后 数据观测和事件配置之前调用
(2) created 实例创建完成后调用
(3) beforeMount 挂载开始前被用
(4) mounted el被新建vm.$el替换并挂在到实例上之后调用
(5) beforeUpdate 数据更新时调用
(6) updated 数据更改导致的DOM重新渲染后调用
(7) beforeDestory 实例被销毁前调用
(8) destoryed 实例销毁后调用
需要注意的是created和mounted的区别,created是实例已经创建但未挂载,所以一些dom操作要放在mounted中。
Vue组件的API来自props(允许外部环境传递数据给组件)、events(允许组件触发外部环境副作用)和slots(允许外部环境将额外的内容组合在组件中)三个部分,组件的data属性必须是函数。
渐进的理解:vue只是个轻量视图而已,只做自己该做的事,不做不该做的事。
5. vue中使用 v-for 时,绑定key的作用
可以提高列表渲染的效率,提升页面的性能。
6. v-for 与 v-if 的优先级
当 v-if 与 v-for 一起使用时,v-for 具有比 v-if 更高的优先级,这意味着 v-if 将分别重复运行于每个 v-for 循环中,所以,不推荐v-if和v-for同时使用。
7. axios 解决跨域问题
一、使用脚手架创建好项目
全局安装 vue-cli
npm install --global vue-cli
创建一个基于 webpack 模板的新项目
vue init webpack vue-demo
进入项目,安装依赖,启动项目
cd vue-demo
npm install
npm run dev
二、安装axios,并配置相应文件。这里跨域请求的接口来自豆瓣的api
安装 npm install axios --save
配置:
1、在 src/main.js 中引入使用
import axios from 'axios';
Vue.prototype.$axios=axios;
2、在 config/index.js 中的 的dev 添加以下代码,设置一下proxyTable;
proxyTable:{
'/api': {
target : 'https://movie.douban.com/', //设置你调用的接口域名和端口号.别忘了加http
changeOrigin : true, //允许跨域
pathRewrite : {
'^/api': ''
// '/'这里理解成用‘/api’代替target里面的地址,后面组件中我们掉接口时直接用api代替。比如我要调用'https://movie.douban.com/v2/movie/top250',直接写‘/api/v2/movie/top250’即可.
}
}
},
3、在 config/dev.env.js 中设置以下代码
module.exports = merge(prodEnv, {
NODE_ENV: '"development"', //开发环境
API_HOST: "/api/"
})
4、在 config/prod.env.js 中设置以下代码
module.exports = {
NODE_ENV: '"production"',//生产环境
API_HOST: '"https://movie.douban.com/"'
}
5、修改 src/components/HelloWorld.vue 文件
<template>
<div class="hello">
<h1>{{ msg }}</h1>
<ul>
<li v-for="item in movieArr">
<span>{{item.title}}</span>
</li>
</ul>
<button @click="sayOut">渲染</button>
</div>
</template>
<script>
import axios from 'axios';
export default {
name: 'HelloWorld',
data() {
return {
msg: '调用豆瓣api',
movieArr : []
}
},
methods:{
sayOut () {
this.$axios.get('/').then((res) => {
console.log(res)
if (res.status == 200){
console.log(res.data)
// this.movieArr = res.data.subjects
}
// 这里要强调一下这个 this 箭头函数指的是它的父级也就是vue实例 然后不用箭头函数的话 this是一个undefined,无法给movieArr来赋值。
})
}
}
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
h1, h2 {
font-weight: normal;
}
ul {
list-style-type: none;
padding: 0;
}
li {
display: inline-block;
margin: 0 10px;
}
</style>
到此 axios 跨域成功解决。
8. axios 封装http请求
- 在main.js 中引入
import axios from 'axios'
import {get, post, patch, put} from './config/http'
// 定义全局变量
Vue.prototype.$get=get;
Vue.prototype.$post=post;
Vue.prototype.$patch=patch;
Vue.prototype.$put=put;
2.src目录下创建config文件夹,config文件夹创建http.js
import axios from 'axios';
axios.defaults.timeout = 5000;
axios.defaults.baseURL ='';
//http request 拦截器
axios.interceptors.request.use(
config => {
// const token = getCookie('名称');注意使用的时候需要引入cookie方法,推荐js-cookie
config.data = JSON.stringify(config.data);
config.headers = {
'Content-Type':'application/json;charset=UTF-8' // 处理json
// 'Content-Type':'application/x-www-form-urlencoded' // 处理hash
}
// if(token){
// config.params = {'token':token}
// }
return config;
},
error => {
return Promise.reject(err);
}
);
//http response 拦截器
axios.interceptors.response.use(
response => {
if(response.data.errCode ==2){
router.push({
path:"/login",
querry:{redirect:router.currentRoute.fullPath}//从哪个页面跳转
})
}
return response;
},
error => {
return Promise.reject(error)
}
)
/**
* 封装get方法
* @param url
* @param data
* @returns {Promise}
*/
export function fetch(url,params={}){
return new Promise((resolve,reject) => {
axios.get(url,{
params:params
})
.then(response => {
resolve(response.data);
})
.catch(err => {
reject(err)
})
})
}
/**
* 封装post请求
* @param url
* @param data
* @returns {Promise}
*/
export function post(url,data = {}){
return new Promise((resolve,reject) => {
axios.post(url,data)
.then(response => {
resolve(response.data);
},err => {
reject(err)
})
})
}
/**
* 封装patch请求
* @param url
* @param data
* @returns {Promise}
*/
export function patch(url,data = {}){
return new Promise((resolve,reject) => {
axios.patch(url,data)
.then(response => {
resolve(response.data);
},err => {
reject(err)
})
})
}
/**
* 封装put请求
* @param url
* @param data
* @returns {Promise}
*/
export function put(url,data = {}){
return new Promise((resolve,reject) => {
axios.put(url,data)
.then(response => {
resolve(response.data);
},err => {
reject(err)
})
})
}
- 在项目的 config/index.js 解决跨域请求
proxyTable: {
'/apis': {
// target: 'http://39.105.189.51:8052',
target: 'http://api.edgvip.cn',
changeOrigin: true,
pathRewrite: {
'^/apis': ''
}
}
},
-
组件中引入使用
eg: 接口文档为下图
image.png
methods: {
login() {
this.$post('apis/api/user/login1',{mobilePhone: this.mobilePhone, password: this.password}).then((res) => {
// console.log(res)
if(res.rs == 1){
this.$toast(res.info);
this.$router.push('/home'); // 路由跳转
}else{
this.$toast(res.info);
}
})
},
},
此时,完成axios的封装。
9. vue 实现tab切换
其实就是路由的使用
- src下创建router文件夹,内部包含index.js
import Vue from 'vue'
import Router from 'vue-router'
import Home from '@/components/Home'
import News from '@/components/News'
Vue.use(Router)
export default new Router({
routes: [
{
path: '/',
component: Home
},
{
path: '/home',
name: 'Home',
component: Home
},
{
path: '/news',
name: 'News',
component: News
}
]
})
- 在main.js 中引入router
import router from './router'
new Vue({
el: '#app',
router,
components: { App },
template: '<App/>'
})
- 在App.vue中使用
<template>
<div id="app">
<img src="./assets/logo.png">
<div>
<router-link to="/home">主页</router-link>
<router-link to="/news">新闻</router-link>
<router-view></router-view>
</div>
</div>
</template>
<script>
export default {
name: 'App'
}
</script>
<style scoped>
</style>
10. 如何配置 vue 打包生成文件的路径?
- 将 config.js 文件下index.js中的assersPublishPath,改为‘./’
build: {
// Template for index.html
index: path.resolve(__dirname, '../dist/index.html'),
// Paths
assetsRoot: path.resolve(__dirname, '../dist'),
assetsSubDirectory: 'static',
// 将 build 中的 assetsPublicPath 改为 './', 修改dev,无效
assetsPublicPath: './',
/**
* Source Maps
*/
productionSourceMap: true,
// https://webpack.js.org/configuration/devtool/#production
devtool: '#source-map',
// Gzip off by default as many popular static hosts such as
// Surge or Netlify already gzip all static assets for you.
// Before setting to `true`, make sure to:
// npm install --save-dev compression-webpack-plugin
productionGzip: false,
productionGzipExtensions: ['js', 'css'],
// Run the build command with an extra argument to
// View the bundle analyzer report after build finishes:
// `npm run build --report`
// Set to `true` or `false` to always turn it on or off
bundleAnalyzerReport: process.env.npm_config_report
}
- 将build/utils.js 加入 publicPath: '../../'
// Extract CSS when that option is specified
// (which is the case during production build)
if (options.extract) {
return ExtractTextPlugin.extract({
use: loaders,
fallback: 'vue-style-loader',
// 在 utils.js 的此处加上下面代码,即可
publicPath: '../../'
})
} else {
return ['vue-style-loader'].concat(loaders)
}
11. vue如何适配移动端?
在 main.js 引入 rem.js
import './config/rem'
rem.js 代码如下:
window.onload = function() {
getRem(750, 100);
}
window.onresize = function() {
getRem(750, 100);
}
function getRem(pwidth, prem) {
var html = document.documentElement;
var oWidth = document.body.clientWidth || document.documentElement.clientWidth;
html.style.fontSize = oWidth/pwidth*prem + 'px';
}
12. vue如何优化首屏加载速度?
- 使用CDN资源,减小服务器带宽压力;
- 将静态js css放到其他地方(如OSS),减小服务器压力;
- 按需加载第三方UI资源;
- 服务端开启gzip,减小网络传输的流量大小;
- 按照页面或者组件分块懒加载
13. vue.js的两个核心思想
数据驱动 和 组件系统
14. vue数据的双向绑定
在vue.js里面只需要改变数据,Vue.js通过directives指令去操作DOM元素,当数据发生变化,会通知指令去修改对应的DOM,数据的变化驱动DOM的变化,DOM是数据的一种映射。vue.js还会对DOM做一些监听(DOM Listener),当我们修改视图的时候,vue.js监听到这些变化,从而改变数据。这样就形成了数据的双向绑定。
15. MVVM框架的理解
MVVM 由 Model、View、ViewModel 三部分构成,Model 代表数据层;View 代表视图层,它负责将数据模型转化成UI 展现出来;ViewModel 是一个同步View 和 Model的实例对象。
【model模型】指的是后端传递的数据。【view视图】指的是所看到的页面。【viewmodel视图模型】是mvvm模式的核心,它是连接view和model的桥梁。它有两个方向:一是将【模型】转化成【视图】,即将后端传递的数据转化成所看到的页面。实现的方式是:数据绑定。二是将【视图】转化成【模型】,即将所看到的页面转化成后端的数据。实现的方式是:DOM 事件监听。这两个方向都实现的,我们称之为数据的双向绑定。
在MVVM模式下,View 和 Model 之间并没有直接的联系,而是通过ViewModel进行交互,Model 和 ViewModel 之间的交互是双向的, 因此View 数据的变化会同步到Model中,而Model 数据的变化也会立即反应到View 上。
image.png
15. 自定义指令和自定义过滤器
自定义指令
自定义指令的参数有:
el: 指令所绑定的元素,可以用来直接操作 DOM 。
binding: 一个对象,包含以下属性:
name: 指令名,不包括 v- 前缀。
value: 指令的绑定值, 例如: v-my-directive="1 + 1", value 的值是 2。
oldValue: 指令绑定的前一个值,仅在 update 和 componentUpdated 钩子中可用。无论值是否改变都可用。
expression: 绑定值的字符串形式。 例如 v-my-directive="1 + 1" , expression 的值是 "1 + 1"。
arg: 传给指令的参数。例如 v-my-directive:foo, arg 的值是 "foo"。
modifiers: 一个包含修饰符的对象。 例如: v-my-directive.foo.bar, 修饰符对象 modifiers 的值是 { foo: true, bar: true }。
eg:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>自定义指令</title>
<script src="https://cdn.bootcss.com/vue/2.6.6/vue.min.js"></script>
</head>
<body>
<div id="app">
<div class="box" v-pos:red.left.top="true">自定义指令,背景色为红色,固定在左上角</div>
<div class="box" v-pos.right.bottom="true">自定义指令,固定在右下角</div>
</div>
</body>
<script>
var vm = new Vue({
el: '#app',
data: {
},
directives: {
pos (el, binding){
console.log(el, binding);
// 修饰符 .left.top
var position = binding.modifiers;
// position = {left: true, top: true}
// 绑定的参数 :red
var color = binding.arg;
if (binding.value){
el.style.position = 'fixed';
el.style.background = color;
for(let val in position){
el.style[val] = '10px'
}
}
}
}
})
</script>
</html>
自定义过滤器
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>自定义指令</title>
<script src="https://cdn.bootcss.com/vue/2.6.6/vue.min.js"></script>
</head>
<body>
<div id="app">
<div><span>{{length}}m</span>=<span>{{length | meter("cm")}}</span></div>
<div>{{price | myCurrency('$')}}</div>
</div>
</body>
<script>
var vm = new Vue({
el: '#app',
data: {
length: 1,
price: 120
},
filters: {
meter (val, unit){
console.log(val, unit);
return val*100 + unit
},
myCurrency(val, unit) {
console.log(val, unit);
return unit + val
}
}
})
</script>
</html>
16. vue-cli 工程常用的 npm 命令有哪些?
下载 node_modules 资源包的命令:
npm install
// 安装模块;
// -save-dev(-D) 是指将包信息添加到 package.json 里的 devDependencies节点,表示开发时依赖的包。
npm install 模块名 --save-dev(-D)
// -save(-S) 是指将包信息添加到 package.json 里的dependencies节点,表示发布时依赖的包。
npm install 模块名 --save(-S)
启动 vue-cli 开发环境的 npm命令:
npm run dev
vue-cli 生成 生产环境部署资源 的 npm命令:
npm run build
用于查看 vue-cli 生产环境部署资源文件大小的 npm命令:
npm run build --report
17. vue常用的修饰符
<!-- 阻止单击事件继续传播(阻止冒泡)-->
<div onclick="alert(2)">
<button class="btn" onclick="someEvents()">按钮</button>
</div>
<script>
function someEvents(event) {
alert(1);
var event = event || window.event;
event.stopPropagation();
}
</script>
<a v-on:click.stop="doThis"></a>
<!-- 提交事件不再重载页面 (默认事件) -->
// event.preventDefault(); //取消默认事件
<form v-on:submit.prevent="onSubmit"></form>
<!-- 修饰符可以串联 -->
<a v-on:click.stop.prevent="doThat"></a>
<!-- 只有修饰符 -->
<form v-on:submit.prevent></form>
<!-- 添加事件监听器时使用事件捕获模式 -->
<!-- 即元素自身触发的事件先在此处处理,然后才交由内部元素进行处理 -->
<div v-on:click.capture="doThis">...</div>
<!-- 只当在 event.target 是当前元素自身时触发处理函数 -->
<!-- 即事件不是从内部元素触发的 -->
<div v-on:click.self="doThat">...</div>
<!-- 在默认情况下,v-model 在每次 input 事件触发后将输入框的值与数据进行同步 。-->
<input v-model.lazy="msg" >
<!-- 自动将用户的输入值转为数值类型,可以给 v-model 添加 number 修饰符 -->
<input v-model.number="num" >
<!-- 自动过滤用户输入的首尾空格 -->
<input v-model.trim="msg" />
18. vue事件中如何使用event对象?
<div>
<button id="btn" @click="click">click me</button>
<button @click="click()">click you</button>
<button @click="click($event)">click us</button><br/>
</div>
<script>
var vm = new Vue({
el: '#app',
methods: {
click() {
// 获取当前 DOM 元素
var el = event.currentTarget;
// docuemnt.getElementById('btn') == event.currentTarget;
console.log(el.innerHTML);
}
}
})
</script>
// 三种写法
1. DOM 事件 click 上,不加(),methods 方法中 click,可加可不加 event;
2. DOM 事件 click 上,加(),methods 方法中 click,不能加 event;
3. DOM 事件 click 上,加($event),并传入 $event,methods 方法中 click,可加可不加 event;
19. nextTick的使用
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>nextTick</title>
<script src="https://cdn.bootcss.com/vue/2.6.6/vue.min.js"></script>
</head>
<body>
<div id="app">
<p ref="txt" id="p1" v-if="show">{{message}}</p>
<p>{{msg}}</p>
<button @click="getTxt">点击</button>
</div>
</body>
<script>
var vm = new Vue({
el: '#app',
data: {
show: true,
message: '原文本',
msg: ''
},
methods: {
getTxt () {
this.show = true;
// 箭头函数写法
this.$nextTick(() => {
console.log(this.$refs.txt); // <p id="p1">原文本</p>
console.log(document.getElementById('p1')); // <p id="p1">原文本</p>
this.msg = this.$refs.txt.innerHTML +' + '+ '新文本内容';
console.log('原文本内容:', this.$refs.txt.innerHTML);
})
// this异步绑定 .bind(this)
// this.$nextTick().then(function() {
// this.msg = this.$refs.txt.innerHTML +' + '+ '新文本内容';
// console.log('原始文本内容:', this.$refs.txt.innerHTML);
// }.bind(this));
}
}
})
</script>
</html>
解析:使用v-show进行显示隐藏,methods里面是直接可以获取到文本值,如果用v-if,是不能获取的文本值的。
this.$nextTick的作用是在下次dom更新循环完成之后进行调用
ref 被用来给元素或子组件注册引用信息。引用信息将会注册在父组件的 $refs 对象上。
元素上绑定 ref (eg: ref='txt') 属性,获取该元素使用 this.$refs.txt 即可。也可使用事件(event)获取当前元素(var el = event.currentTarget)。
20. vue中 keep-alive 组件的作用
<!-- App.vue -->
<template>
<div id="app">
<router-link to="/home">主页</router-link>
<router-link to="/news">新闻</router-link>
<keep-alive include="keep_alive">
<router-view v-if="$route.meta.keepAlive"></router-view>
</keep-alive>
<router-view v-if="!$route.meta.keepAlive"></router-view>
</div>
</template>
<script>
export default {
name: 'App',
data() {
return {
include: "keep_alive"
}
}
}
</script>
<!-- 哪个组件需要缓存 该组件 name 就需要绑定App.vue的 include 属性,并在 routes 上绑定 meta: { keepAlive: true } -->
<!-- // true表示需要使用缓存 false表示不需要被缓存 -->
<!-- Home.vue -->
<template>
<div id="home">
<input type="text" placeholder="" name="">
</div>
</template>
<script>
export default {
// 此时绑定的 name 是 App.vue 的 include 属性值
name: 'keep_alive',
data() {
return {}
}
}
</script>
<!-- News.vue -->
<template>
<div id="news">
<input placeholder="输入框"></input>
</div>
</template>
<script>
export default {
// 同 Home
name: 'keep_alive',
data() {
return {}
}
}
</script>
<style scoped>
</style>
<!-- router/index.js -->
<script>
import Vue from 'vue'
import Router from 'vue-router'
import Home from '@/components/Home'
import News from '@/components/News'
Vue.use(Router)
var routes = [
{
path: '/',
component: Home
},
{
path: '/home',
name: 'Home',
component: Home,
meta: {
keepAlive: true // true表示需要使用缓存 false表示不需要被缓存
}
},
{
path: '/news',
name: 'News',
component: News,
meta: {
keepAlive: true
}
}
]
export default new Router({routes})
</script>
说明:
(1) 在Home页面输入框输入“home”,然后通过路由跳转到News页面;
(2) 回到Home页面发现 input 之前输入的"home"依然保留,说明页面信息成功保存在内存中;
keep-alive的作用:keep-alive 是Vue的内置组件,能在组件切换过程中将状态保留在内存中,防止重复渲染DOM。
keep-alive的属性:
include: 字符串或正则表达式。只有匹配的组件会被缓存。
exclude: 字符串或正则表达式。任何匹配的组件都不会被缓存。
21. vue等单页面应用及其优缺点
优点:
Vue 的目标是通过尽可能简单的 API 实现响应的数据绑定和组合的视图组件,核心是一个响应的数据绑定系统。MVVM、数据驱动、组件化、轻量、简洁、高效、快速、模块友好。
1、具有桌面应用的即时性、网站的可移植性和可访问性。
2、用户体验好、快,内容的改变不需要重新加载整个页面。
3、基于上面一点,SPA相对对服务器压力小。
4、良好的前后端分离。SPA和RESTful架构一起使用,后端不再负责模板渲染、输出页面工作,web前端和各种移动终端地位对等,后端API通用化。
5、同一套后端程序代码,不用修改就可以用于Web界面、手机、平板等多种客户端;
缺点:
不支持低版本的浏览器,最低只支持到IE9;
不利于SEO的优化(如果要支持SEO,建议通过服务端来进行渲染组件);
第一次加载首页耗时相对长一些;
不可以使用浏览器的导航按钮,需自行实现前进、后退。
22. vue中子组件调用父组件的方法
Vue中子组件调用父组件的方法,这里有三种方法提供参考
第一种方法是直接在子组件中通过this.$parent.event来调用父组件的方法
<!-- App.vue -->
<template>
<div id="app">
<Child />
</div>
</template>
<script>
import Child from '@/components/Child'
export default {
name: 'App',
components: {
Child
},
methods: {
fatherMethod() {
console.log('测试');
}
}
</script>
<!-- Child.vue -->
<template>
<div id="child">
<button @click="childMethod()">点击</button>
</div>
</template>
<script>
export default {
name: 'child',
data() {
return {
msg: '子组件child'
}
},
methods: {
childMethod() {
this.$parent.fatherMethod()
}
}
}
</script>
第二种方法是在子组件里用$emit向父组件触发一个事件,父组件监听这个事件就行了。
<!-- App.vue -->
<template>
<div id="app">
<Child @fatherMethod="fatherMethod" />
</div>
</template>
<script>
import Child from '@/components/Child'
export default {
name: 'App',
components: {
Child
},
methods: {
fatherMethod() {
console.log('测试');
}
}
</script>
<!-- Child.vue -->
<template>
<div id="child">
<button @click="childMethod()">点击</button>
</div>
</template>
<script>
export default {
name: 'child',
data() {
return {
msg: '子组件child'
}
},
methods: {
childMethod() {
this.$emit('fatherMethod');
}
}
}
</script>
第三种是父组件把方法传入子组件中,在子组件里直接调用这个方法
<!-- App.vue -->
<template>
<div id="app">
<Child :fatherMethod="fatherMethod" />
</div>
</template>
<script>
import Child from '@/components/Child'
export default {
name: 'App',
components: {
Child
},
methods: {
fatherMethod() {
console.log('测试');
}
}
</script>
<!-- Child.vue -->
<template>
<div id="child">
<button @click="childMethod()">点击</button>
</div>
</template>
<script>
export default {
name: 'child',
data() {
return {
msg: '子组件child'
}
},
props: {
fatherMethod: Function,
default: null
},
methods: {
childMethod() {
if (this.fatherMethod){
this.fatherMethod();
}
}
}
}
</script>
23. package.json的文件解析
name:项目名称
version:项目版本号
description:描述信息,有助于搜索
scripts:支持的脚本,默认是一个空的 test
private:公有私有
keywords:关键字,有助于在人们使用 npm search 搜索时发现你的项目
author:作者信息
license:证书信息(默认是 MIT)
dependencies:在生产环境中需要用到的依赖
devDependencies:在开发环境中用到的依赖,上线打包后的代码是不存在的
engines:node和npm的版本要求
browserslist:浏览器要求
24. vue 全局变量和函数的使用
- 首先在src下创建global文件夹,创建global_data.js
const url = 'http://www.baicu.com'
const name = 'zhangsan'
// 暴露变量
export default {
url,
name
}
//或者
// module.exports = {
// url,
// name
// }
- 引用(局部引用,全局引用)
// 全局变量的局部全局引入
// App.vue引用 哪个页面需要哪个页面引入(局部)
import GLOBAL from '@/global/global_data'
export default {
name: 'App',
data() {
return {
url: GLOBAL.url,
}
}
}
// main.js 引入 (全局)
import globalData from '@/global/global_data'
// 挂载vue原型
Vue.prototype.GLOBAL = globalData
// App.vue 使用
export default {
name: 'App',
data() {
return {
url: this.GLOBAL.url,
}
}
}
// 全局函数的引入
// 第一种方法
// main.js 直接绑定
Vue.prototype.global_fun1 = function() {
return console.log('fun1');
}
// App.vue 页面输出
export default {
name: 'App',
mounted() {
this.global_fun1(); // 打印 fun1
}
}
// 第二种方法
// global/新建global_fun.js
import Vue from 'vue'
function fun11(params){
console.log(params);
}
export default {
Vue.prototype.global_fun11 = (params) => fun11(params);
}
// next main.js 引入
import globalFun from '@/global/global_fun'
Vue.use(globalFun);
// App.vue 使用
export default {
name: 'App',
mounted() {
this.global_fun11('zhangsan'); // 打印 zhangsan
}
}
25. vue弹出窗口之后禁止页面滑动
先阻止默认时间,然后给body添加overflow:hidden;
export default {
methods: {
stop() {
var stop = function(event) {
event.preventDefault();
}
document.body.style.overflow = 'hidden';
document.addEventListener('touchmove', stop, false); // 禁止页面滑动
}
move() {
var move = function(event) {
event.preventDefault();
};
document.body.style.overflow = ''; //出现滚动条
document.removeEventListener("touchmove", move, false); //开启页面滑动
}
}
}
26. v-for产生的列表,实现active的切换?
<template>
<ul>
<li v-for="(item, index) in movieArr" @click="curIndex = index" :class="{actived: index == curIndex}">
<span>{{item}}</span>
</li>
</ul>
</template>
<script>
export default {
name: 'App',
data() {
curIndex: 0,
movieArr: ['三国', '大人物', '无双']
}
}
</script>
<style>
.actived {
color: red;
}
</style>
27. vue实现路由懒加载
懒加载:也叫延迟加载,即在需要的时候进行加载,随用随载。
为什么需要使用懒加载?
像vue这种单页面应用,如果不应用懒加载,运用 webpack 打包后的文件将会异常的大,造成进入首页时,需要加载的内容过多,时间过长,会出现长时间的白屏,即使做了loading也是不利于用户体验,而运用懒加载则可以将页面进行划分,需要的时候加载页面,可以有效的分担首页所承担的加载压力,减少首页加载用时
不使用懒加载的路由配置:
import Vue from 'vue'
import Router from 'vue-router'
import HelloWorld from '@/components/HelloWorld'
import Home from '@/components/Home'
import News from '@/components/News'
Vue.use(Router)
export default new Router({
routes: [
{
path: '/',
component: Home
},
{
path: '/helloworld',
name: 'HelloWorld',
component: HelloWorld,
meta: {
keepAlive: true
}
},
{
path: '/home',
name: 'Home',
component: Home,
// 组件切换时,将状态保存在内存中,防止重复渲染
meta: {
keepAlive: true // true表示需要使用缓存 false表示不需要被缓存
}
},
{
path: '/news',
name: 'News',
component: News,
meta: {
keepAlive: true
}
}
]
})
使用懒加载的路由配置:
import Vue from 'vue'
import Router from 'vue-router'
import HelloWorld from '@/components/HelloWorld'
Vue.use(Router)
export default new Router({
routes: [
{
path: '/',
},
{
path: '/helloworld',
name: 'HelloWorld',
component: resolve => require(['@/components/HelloWorld'], resolve)
},
{
path: '/home',
name: 'Home',
component: resolve => require(['@/components/Home'], resolve),
children: [{
path: '/detail',
name: 'Detail',
component: resolve => require(['@/components/Detail'], resolve)
}],
meta: {
keepAlive: true
}
},
{
path: '/news',
name: 'News',
component: resolve => require(['@/components/News'], resolve),
meta: {
keepAlive: true
}
}
]
})
28. vue-router 的两种模式
hash 模式 和 history 模式
hash 模式:
hash 发生变化之后,url 都会被浏览器记录下来,所以你会发现浏览器的前进后退都可以用了,点击前进、后退,可以跳转页面。
hash模式的工作原理是onhashchange事件,可以在window监听hash的变化。
event 事件里边有两个属性newURL和oldURL。可以通过模拟改变 hash 的值,动态改变页面数据。
// 页面的URL:http://kuayu.lc/hash.html#pink,通过改变 hash 的颜色值,来改变 div 的颜色。
<div id="div1" style="height: 500px;width: 500px;margin: 0 auto"></div>
<script>
window.onhashchange = function(event){
let event = event || window.event;
let hash = location.hash.slice(1);
document.getElementById('div1').style.backgroundColor = hash
}
</script>
尽管浏览器没有向服务器发送请求,但页面状态已经和 url 关联起来了,这就是所谓的前端路由,单页应用的标配。
网易云音乐,百度网盘就采用了hash路由,看起来就是这个样子:
history模式:
把window.history 对象打印出来之后,可以看到里边提供的方法和记录长度(__ proto__ 原型链上)
console.log(window.history);
image.png
前进,后退,跳转操作方法:
history.go(-2); //后退2次
history.go(2); //前进2次
history.go(0); //刷新当前页面
history.back(); //后退
history.forward(); //前进
如果不想用 # 的 hash,我们可以用路由的 history 模式。
export default new VueRouter({
mode: 'history',
routes: [...]
})
当你使用 history 模式时,URL 就像正常的 url : http://localhost:8080/news
不过这种模式要玩好的话,还需要后台配置支持。因为我们的应用是个单页客户端应用,如果后台没有正确的配置,当用户在浏览器直接访问 http://localhost:8080/news1234 (没有路由,访问不到的情况) 就会返回 404,这就不好看了。
为了避免这种情况,你应该在 Vue 应用里面覆盖所有的路由情况,然后在给出一个 404 的组件页面。
export default {
mode: 'history',
routes: [
{path: '*', component: resolve => require(['@/components/NotFound'], resolve)}
]
}
29. $router 和 $route 的区别
$router 为 VueRouter 实例,想要导航到不同 URL,使用 $router.push 方法。
$route 为当前 router 跳转对象,里面可以获取 name 、 path 、 query 、 params、meta 等信息。
网友评论