也多是由于接触vue时间也不长,常常落入不知名的‘坑’中,对于我这个菜鸟来讲,每次‘落坑’无疑是一场不小的灾难。前两天有个朋友在问我,在使用
vue
中有没有遇到一些很难解决的问题,一下我也只能说出一两个,正所谓‘光说不练,假把式’,因此索性就抽时间总结一下我在项目中遇到的vue
的问题,也贴出了效果图片,这样看起来也比较清晰。有写的不对的地方,在您时间还容许的状况下,还劳烦你们告诉我哦,我也好尽早修改,以避免给看文章的其余同仁带来没必要要的麻烦!(当前版本:"vue@2.5.3") -------------------在此谢过!-----------css
说到vue的实战,不得不说vue
项目建立,那么关于vue cli
项目搭建,我在以前的文章中有专门写过,可参考个人第一篇文章: vue cli 框架搭建html
每一个Vue实例在被建立以前都要通过一系列的初始化过程,这个过程就是vue的生命周期前端
方法名 | 状态 | 含义 |
---|---|---|
beforeCreate | creating | 所有实例建立以前,获取不到props 和data中的数据 |
created | creating | 实例建立成功,能够拿到data中的数据 |
beforeMount | mounting | 此时data里面的数据和模板已生成html |
mounted | mounting | 挂载结束,模版中的 data 数据直接显示出来了,此时通常能够作一些ajax操做 |
beforeUpdate | updating | 当 data 数据发生变化调用,发生在虚拟 DOM 从新渲染和打补丁以前 |
updated | updating | 数据更改致使的虚拟 DOM 从新渲染和打补丁 |
beforeDestroy | destroying | 在 vue 实例销毁以前调用,此时实例任然可用,通常在这一步作一些重置的操做,好比清除掉组件中的定时器 和 监听的dom事件 |
destroyed | destroying | 在 vue 实例销毁以后调用,vue 实例指示的全部东西都会解绑定,全部的事件监听器会被移除,全部的子实例也会被销毁 |
⚠️注意:vue
若是在created
阶段的发送ajax
请求,此时页面视图未出现,若是请求信息过多,页面会长时间处于白屏状态,请求建议放在mounted
阶段,固然mounted
不会承诺全部的子组件也都一块儿被挂载。若是你但愿等到整个视图都渲染 完毕再发生请求,能够用 vm.$nextTick
。webpack
子组件完成挂载后,父组件才会挂载,销毁父组件时,先将子组件销毁后才会销毁父组件ios
参考地址web
加载渲染过程:ajax
父beforeCreate -》父created -》父beforeMount-》子beforeCreate -》子created-》子beforeMount-》子 mounted-》父mouted
复制代码
子组件更新过程:正则表达式
父beforeUpdate -》子 beforeUpdate -》子 update -》父update
复制代码
父组件更新过程:vue-router
父beforeUpdate -》父update
复制代码
销毁过程:
父beforeDestroy -》子beforeDestroy -》子 destroy -》父 destroy
复制代码
分享:自用的vue模版
<template>
<div>
</div>
</template>
<script>
export default {
props:{},
data() {
return {}
},
computed:{},
components: {},
created(){},
mounted() {},
methods: {},
watch: {},
destroyed(){},
}
</script>
<style scoped lang="less">
</style>
复制代码
css
的多种方式。在
vue
的每一个组件中,能够自定义css
和js
,那么若是只但愿当前的css
只在当前页面生效,能够在style
的标签这样书写,这样当前页面的全部css
样式,除当前组件,不会在其余组件生效而且不会影响到其余组件页面渲染。
<style scoped> </style>
复制代码
若是你引入来sass到vue项目中,那么只需在当前组件添加lang属性便可:
sass $
<style scoped lang="scss"> </style>
复制代码
亦你的项目引入的不是sass
,是less
,也是一样更改lang
属性便可:
less @:
<style scoped lang="less"> </style>
复制代码
动态传入style
值的几种方式:
1.正常class
样式:
<template>
<div>
<p class="fs20">1.正常class样式: 2018年8月27日</p>
</div>
<template>
<style>
.fs20 {
font-size: 20px
}
</style>
复制代码
页面展示:
对于多个"../../../"查找引入文件时,能够先跳到最外层,即src层开始查找
关于引入外部的less文件或者img图片:
~@/xxx/...
复制代码
@/xxx/...
复制代码
2.根据data
中的className
对应的class
,可用于动态切换class
:
<template>
<div>
<p :class="className">2.动态切换class的值</p>
</div>
<template>
<script>
export default {
data() {
return {
className: "classA"
}
},
components: {},
mounted() {},
methods: {},
watch: {}
}
</script>
<style>
.classA {
color: yellowgreen
}
</style>
复制代码
页面展现:
3.给当前的class
添加判断:当isOk
为true
时添加class
,为false
时不添加:
<template>
<div>
<p :class="{colorRed:isOk}">
3.添加判断:当isOk为true是添加class,为false时不添加
</p>
<Checkbox v-model="isOk">Checkbox</Checkbox>
</div>
<template>
<script>
export default {
data() {
return {
isOk: true,
}
},
components: {},
mounted() {},
methods: {},
watch: {}
}
</script>
<style>
.colorRed {
color: red
}
</style>
复制代码
页面展现:
4.以数组的方式,一次添加多个class
:
<template>
<div>
<p :class="[classC,classD]">4.以数组的方式,一次添加多个class</p>
</div>
<template>
<script>
export default {
data() {
return {
classC: "classC",
classD: "classD"
}
},
components: {},
mounted() {},
methods: {},
watch: {}
}
</script>
<style>
.classC {
font-size: 16px;
font-weight: 600;
}
.classD {
color: blue
}
</style>
复制代码
页面展现:
5.使用三元运算符判断切换class
样式,当isOk
为true
时用的是classA
,当为false
的时候用的是classB
:
<template>
<div>
<p :class="isOk?classA:classB">5.使用三元运算符判断切换class样式</p>
</div>
<template>
<script>
export default {
data() {
return {
isOk: true,
classA: "classA",
classB: "classB"
}
},
components: {},
mounted() {},
methods: {},
watch: {}
}
</script>
<style>
.classA {
color: yellowgreen
}
.classB {
color: green
}
</style>
复制代码
页面展现:
6.绑定动态的style
的样式:
<template>
<div>
<p :style="{color:color,fontSize:font}">6.绑定style的样式</p>
</div>
<template>
<script>
export default {
data() {
return {
color: "red",
font: "18px",
}
},
components: {},
mounted() {},
methods: {},
watch: {}
}
</script>
<style>
</style>
复制代码
页面展现:
7.给style
绑定对象:
<template>
<div>
<p :style="styleObject">7.给style 绑定对象</p>
</div>
<template>
<script>
export default {
data() {
return {
styleObject:{
color:"pink",
fontWeight:"600"
}
},
components: {},
mounted() {},
methods: {},
watch: {}
}
</script>
<style>
</style>
复制代码
页面展示:
img
的src
赋值的问题在
vue
中的循环是使用v-for
来实现的,在标签中注入v-for
,在接下来使用到的地方就能够直接使用。
<template>
<div v-for="item in cityList">
<div>城市名称:{{item.title}}</div>
<div>城市ID:{{item.id}}</div>
<div>城市图片:<img src={{item.img}}></div> //这行是报错的
</div>
</template>
<script>
export default:{
data(){
return:{
cityList:[{
title:'北京',
id:001,
img:'static/logo.png'
},
{
title:'上海',
id:002,
img:'static/logo.png'
}]
}
}
}
</script>
复制代码
报错以下:(这里意思是在“src”属性插值将致使404请求。使用v-bind:src
简写为:src
代替)
[HMR] bundle has 1 errors
client.js?d90c:161 ./~/_vue-loader@12.2.2@vue-loader/lib/template-compiler?{"id":"data-v-60d18b79","hasScoped":true,"transformToRequire":{"video":"src","source":"src","img":"src","image":"xlink:href"}}!./~/_vue-loader@12.2.2@vue-loader/lib/selector.js?type=template&index=0!./src/components/vuetest.vue
(Emitted value instead of an instance of Error)
Error compiling template:
<div>
<h1>vue测试页面</h1>
<div v-for="item in cityList">
<div>城市名称:{{item.title}}</div>
<div>城市ID:{{item.id}}</div>
<div>城市图片:<img src="https://user-gold-cdn.xitu.io/2017/11/26/15ff7324b8313b05"></div>
</div>
</div>
- src="https://user-gold-cdn.xitu.io/2017/11/26/15ff7324b8313b05": Interpolation inside attributes has been removed. Use v-bind or the colon shorthand instead. For example, instead of <div id="{{ val }}">, use <div :id="val">.
@ ./src/components/vuetest.vue 10:2-340
@ ./src/router/index.js
@ ./src/main.js
@ multi ./build/dev-client ./src/main.js
复制代码
由于vue官网在介绍v-bind时,不能够再使用{{}},例如href
的两种使用:
<template>
<div>
<a :href='msg'>获取动态数据</a>
<a href='http://www.baidu.com'>百度</a>
</div>
</template>
<script>
export default:{
data(){
return:{
msg:'http://www.baidu.com'
}
}
}
</script>
复制代码
正确代码以下:
<template>
<div v-for="item in cityList">
<div>城市名称:{{item.title}}</div>
<div>城市ID:{{item.id}}</div>
<div>城市图片:<img :src='item.img'></div>
</div>
</template>
<script>
export default:{
data(){
return:{
cityList:[{
title:'北京',
id:001,
img:'static/logo.png'
},
{
title:'上海',
id:002,
img:'static/logo.png'
}]
}
}
}
</script>
复制代码
v-if
和v-show
的区别在vue中有两种隐藏元素的方式,那就是
v-if
和v-show
,可是二者有什么区别呢?何时用v-if
,何时用v-show
呢?
当v-if
和v-show
两个值都为true
时的渲染结果,都正常渲染
v-if
和v-show
的值都为假值时:页面没有渲染,v-if
未渲染dom
元素,v-show
渲染成功,但被添加了style
为display:none
。
vue
中如何操做DOM
元素。咱们都知道vue框架中咱们通常操做的都是数据,那么假如咱们要操做dom元素使用什么方法呢?下面就来介绍一下!
假若有如下元素,咱们要获取这个h2元素的文本,须要给此元素添加ref属性,并赋予名字。
<h2 ref='foo'>我是ref的值</h2>
复制代码
接下来就可使用这个方法获取到它的文本(注意是this.$refs
不是this.$ref
):
console.log(this.$refs.foo.innerHTML') 复制代码
h2
中的文本呢? this.$refs.foo.innerHTML='我是新值 复制代码
这样就能够和之前同样,轻松的操做dom元素了,可是vue仍是以操做数据为核心,因此建议尽可能少的使用以上方法。
router-link
中的tag
属性。在
vue
路由的router-link标签中有一个属性tag
,是我今天在查阅资料时发现的,感受比较有意思,推荐给你们。
那么咱们就给<router-link to='/about'>
的标签上添加上tag
属性,并赋值:
<router-link to='/fenceCenter' >中心点</router-link>
<router-link to='/vuetest'tag='li'>vue测试</router-link>
复制代码
那么咱们看看它和咱们正常渲染的有什么不一样
是否是很神奇呢? tag
除了能够赋值li
,还能够赋值成你想要的全部的标签哦! p,span,h1,div
....均可以哦!快去动手试试吧!!
router
在咱们的实际业务中,有时须要在某一组件内,点击一个按钮或者是点击一个连接切换跳转到其余组件,也就是跳转路由,咱们能够试试下面的方法:
//直接跳转
this.$router.push('/map')
//条件容许时跳转
if(this.data){
this.$router.push('/map')
}
复制代码
注意:
router
须要挂在到vue
实例上,这样才能够获取到this.$router
,并且push
后面的括号中的路由地址,也须要在vue
的router
中有注册,最后,在('')中填写你须要跳转的路由便可完成跳转。
上面刚刚有讲到路由router
,接下来再讲一个和router
相关的方法go
,这个方法是用做前进后退导航来使用的,有时实际业务须要咱们添加一个返回上一页面的功能,那么咱们就能够用go
来实现。当为‘-1’时就能够后退到上一个路由页面。
this.$router.go('-1')
复制代码
vue是一个单页面应用,那么就会涉及到组件的问题,例如
A
页面为一个主页面,A1,A2,A3
为3个子页面,但A1,A2,A3
页面的内容分别比较复杂,须要单页面来编辑,这时咱们就须要把A1,A2,A3
写成3个组件,而后所有加载A的主页面上;又或有这样的状况,当子页面的复用率比较高时,一样能够采起使用组件的方式来实现。总之,你能够把你想实现的写成组件,这样第一方便修改,第二页面干净整洁,第三;让别人看起来一目了然。 下面咱们就看看,组件究竟是怎么实现吧!!!
A页面:
<template>
<div>
<h2 style="color:red">我是主页面</h2>
<content><content> //我是添加的组件
</div>
</template>
<script>
import content from './content' //找到组件的位置,引入
export default {
name: "",
data() {
return {
}
},
components:{
content //将组件写入模板内才可生效,当有多个组件,看用逗号分开
},
mounted() {
},
methods: {}
}
</script>
<style scoped>
</style>
复制代码
A页面的子页面(content组件页面): 组件页面就是普通页面,固然组件页面的事件也是会带到主页面的。
<template>
<div @click="foo()">我是组件页面</div>
</template>
<script>
export default {
name: "",
data() {
return {
}
},
mounted() {
},
methods: {
foo(){
alert("我是好人")
}
}
}
</script>
<style scoped>
</style>
复制代码
这时咱们来看一下效果:
这样你想要的效果就有了哦!
那么还须要注意一点:若是你的组件名字是驼峰式写法,那么按照如下方式修改:
<template>
<div>我是主页面<content-f> </content-f> //这里要这样写</div>
</template>
<script>
import contentF from './contentF' //找到组件的位置 引入
export default {
name: "",
data() {
return {
}
},
components:{
contentF //将组件写入模板内才可生效,当有多个组件,看用逗号分开
},
mounted() {
},
methods: {}
}
</script>
<style scoped>
</style>
复制代码
vue
中观察者watch
的用法在
vue
的官网是这么介绍的:把它命名为 观察者模式 虽然计算属性在大多数状况下更合适,但有时也须要一个自定义的watcher
。这是为何vue
经过watch
。 选项提供一个更通用的方法,来响应数据的变化。当你想要在数据变化响应时,执行异步操做或开销较大的操做,这是颇有用的。 通俗点讲,就是在vue
中有一个watch
,它能够监听你的数据是否发生变化,一旦发生变化,能够进行某些操做,那么咱们就来试试:
<template>
<div>
<button @click="foo()">点击按钮</button>
<div>{{value}}</div>
</div>
</template>
<script>
export default {
name: "",
data() {
return {
value:1,
}
},
mounted() {},
watch:{
value:function(val,oldval){
console.log(val,oldval)
}
},
methods: {
foo() {
this.value=5
}
}
}
</script>
<style scoped>
</style>
复制代码
咱们点击一下,看一下结果:当value
被改变时,会在后台打印出当前的值和改变前的值:
但当咱们再次重复上一次的动做时,并不会再次打印结果,那是由于value值改变成5后,再次点击,仍是一样的值,value的值并无再次发生变化。
在watch
里面有一个deep
的参数,能够监听object
中属性的变化。(咱们上面使用的是number
,而一样使用上面的方法,并不能监听到对象的属性值的变化) 下面咱们来使用deep
来检测一下对象属性:
<template>
<div>
<button @click="foo()">点击按钮</button>
<div>{{value}}</div>
</div>
</template>
<script>
export default {
name: "",
data() {
return {
value:{
a:1,b:2
}
}
},
mounted() {},
watch:{
value:{
handler(val,oldVal){
console.log("lalala",val,oldVal)
} ,
deep: true,
immediate: true
}
},
methods: {
foo() {
this.value.a=5;
this.value.b=6;
}
}
}
</script>
<style scoped>
</style>
复制代码
assets
和 static
的区别,静态资源到底该放哪里?在咱们搭建好的
vue-cli
的项目中会自动给咱们建两个文件夹来存放咱们的数据,图片之类的资产,这两个分别是assets
和static
两个,那么咱们怎么来区分这两个文件夹呢?在经过直译咱们了解到assets
的中文意思为资产,而static
的中文意思为静态的,静止的;
缘由以下:
assets
目录中的文件会被webpack
处理解析为模块依赖,只支持相对路径形式。
static/
目录下的文件并不会被webpack
处理:它们会直接被复制到最终的打包目录(默认是dist/static
)下。
下面来一段代码,来现身说法:
<template>
<div class="hello">
<div v-for="item in cityList" :key="item.id">
<div >{{item.title}}</div>
<div>城市图片:<img :src="item.img"></div>
</div>
</div>
</template>
<script>
export default {
name: 'HelloWorld',
data() {
return {
cityList: [{
title: '北京',
id: "001",
img:"../assets/logo.png" //这行是不被识别的
},
{
title: '上海',
id: "002",
img: "static/logo.png" //这个能够被正确显示
}
]
}
}
}
</script>
复制代码
页面展现效果以下:
那么咱们看看在不写在js
中的图片引入是否也会出现问题呢?
<template>
<div class="hello">
<img src="../assets/logo.png" alt="logo">
<img src="static/logo.png" alt="logo">
</div>
</template>
<script>
export default {
name: 'HelloWorld',
data() {
return {
}
}
}
</script>
复制代码
来看一下页面的反应:
效果证明,咱们在html中的引入方式是不会受到影响的。 那若是咱们必需要在js
中使用assets
中的图片,该怎么写呢?
<template>
<div class="hello">
<div v-for="item in cityList" :key="item.id">
<div >{{item.title}}</div>
<div>城市图片:<img :src="item.img"></div>
</div>
</div>
</template>
<script>
export default {
name: 'HelloWorld',
data() {
return {
cityList: [{
title: '北京',
id: "001",
img:require("../assets/logo.png") //使用require()的方式引入便可
},
{
title: '上海',
id: "002",
img: "static/logo.png"
}
]
}
}
}
</script>
复制代码
好啦,接下来就是见证奇迹的时刻了!!
综上所述,总结为如下两点:
1.任何放在 static
中文件须要以绝对路径的形式引用:/static/imgurl
。
2.static
放不会变更的文件,assets
放可能会变更的文件。
参考:juejin.im/post/59be4d… OBKoro1
vue-cli在执行 npm run build 打包后,
接下来让咱们打开cofig
文件夹的index.js
,找到build
这个对象,将
assetsPublicPath: '/'
复制代码
这个路径地址改为
assetsPublicPath: './',
复制代码
从新执行命令,从新打包,再打开index.htnl,页面便可显示:
assetsPublicPath属性做用是指定编译发布的根目录,'/'指的是项目的根目录 ,'./'指的是当前目录。当咱们打包后,index和static是放在dist目录下,而static是和index是平级的,因此不该该在根目录查找文件。
参考:juejin.im/post/59ca4b… OBKoro1
在vue-cli自带的脚手架的路由是以下这样写的:
import Vue from 'vue'
import Router from 'vue-router'
import bus from '../bus'
import HelloWorld from '@/components/HelloWorld'
Vue.use(Router)
export default new Route({
routes: [
{
path: '/',
name: 'HelloWorld',
component: HelloWorld
},
]
});
复制代码
使用的是import 的方式引入进来的,那么咱们须要使用异步的方式,该怎么写呢?
import Vue from 'vue'
import Router from 'vue-router'
import bus from '../bus'
Vue.use(Router)
var router = new Router({
routes: [
{
path: '/',
name: 'HelloWorld',
component: (resolve) => require(['@/components/HelloWorld'], resolve),
},
{
path: '/login',
name: 'login',
component: (resolve) => require(['@/login'], resolve),
}
]
});
bus.router = router
export default router
复制代码
第二种方式:
const Index = () => import( '@/views/index')
const routers = [
{
path: '/',
name: 'index',
component: Index
}
]
复制代码
在vue中除了能够写组件,还可使用自定义指令来实现某些特殊的操做,下面就拿一个相似官方的获取input焦点的“基本款”的栗子🌰来演示。 我有个习惯,就是把相同的东西归类,因此,我先去建了一个文件夹来存放个人指令,以下图:
详细代码以下: 在这里定义并导出个人自定义指令,指令里包含我想实现的操做。(当前是一个获取焦点的示例)
export const focus = (el) => {
el.focus()
}
复制代码
在使用的页面,首先将指令文件引入,而后配置到directive中,在须要使用到标签内添加,注意指令前需添加:”v-“,以下所示: 个人指令name为focus,在标签内写成 “v-focuss”:
<template>
<div>
<input type="text" v-focus>
</div>
</template>
<script>
import { focus } from "../../directives/index"
export default {
name: "",
data() {
return {}
},
directives: {focus}, //自定义指令
components: {},
mounted() {},
methods: {}
}
</script>
<style scoped>
</style>
复制代码
今日在掘金闲逛,看到vue的偏门操做,分享给你们: juejin.im/post/5adc99…
vue的自定义指令直接操做dom较方便:
先看
directives/index
页面 :
接下来看一下调用页面:
最后咱们来看一下页面:
再升级!添加参数的自定义指令
页面的数据也能够写成一个变量,使用变量来控制样式:
下面是自定义指令的生命周期(咱们能够在指令的生命周期中作咱们想处理的事件): 1.bind
:只调用一次,指令第一次绑定到元素时调用,用这个钩子函数能够定义一个绑定时执行一次的初始化动做。 2.inserted
:被绑定元素插入父节点时调用(父节点存在便可调用,没必要存在于document
中)。 3.update
:被绑定于元素所在的模板更新时调用,而不管绑定值是否变化。经过比较更新先后的绑定值,能够忽略没必要要的模板更新。 4.componentUpdated
:被绑定元素所在模板完成一次更新周期时调用。 5.unbind
:只调用一次,指令与元素解绑时调用
好啦!大功告成,小伙伴们,动手试试吧!
今日在项目完成后,进行打包测试,本地开发好好的,但打包后发现登陆页面到背景图片拿不到,可是其余logo小图片是能够正常显示,因而就很郁闷,第一反应,想着应该是图片太大了,未被压缩,而后,就找到了以下位置:
想着把limit的范围放大,但是那若是还有更大的图片呢?这并非个优雅的办法。因而想到了万能到度娘,就有了以下解决方法: my.oschina.net/u/1778998/b… css引入图片再打包后,style-loader没法设置本身的publicPath,因此只要改变style-loader中的publicPath便可,在build/util.js文件中ExtractTextPlugin的css路径,手动添加publicPath参数。
添加后,再执行一次build,图片就能够正常显示。
在咱们的项目中应该会有不少情景,标签内的内容是不须要编译的,但是咱们的代码并不知道,vue提供了一个能够直接跳过编译的指令,供咱们添加在纯静态标签上。
<div v-pre> 直接跳过不须要编译的标签,加快编译效率</div>
复制代码
还有一种情形,在页面有用到{{}}赋值时,有时咱们页面阻塞或加载跟不上、频繁刷新时,可能会显示未赋值的{{}},等拿到值后才能更新出来,这样给用户一种很不友好的体验,一样vue也帮咱们想到了,vue提供了一个能够等待编译结束,才会显示标签内容到指令.
<div v-cloak> {{message}}直接结束编译,避免出现闪烁花括号,配合css样式书写</div>
//配合css 样式完成
<style scoped>
[v-cloak]{display: none;}
</style>
复制代码
vue有本身自带的过滤器供咱们使用,那咱们如何来写一个自定义过滤器呢?下面跟我一块儿操做吧!
先去建立一个filter文件夹,来存放你的过滤器,并在文件中写出你想执行的过滤器的方法
OBKoro1 的《你或许不知道的Vue的这些小技巧》很实用,推荐给你们!
咱们都知道vuex是用来实现vue各个组件数据传输功能的,不区分父子组件,全局便可调用,让咱们的工程有了一个总的title,下来就让试试: 先来建一个store,用来存放咱们的初始化状态,以及更改的方法:
接下来让咱们引入必备的依赖,以及相应的默认导出: ![]()
import Vue from 'vue';
import Vuex from 'vuex';
import { state as userState, actions as userActions, mutations as userMutations } from './stores.js';
Vue.use(Vuex);
const state = Object.assign({}, userState);
const mutations = Object.assign({}, userMutations);
const actions = Object.assign({}, userActions);
export default new Vuex.Store({
state,
mutations,
actions
});
复制代码
最后让咱们来写一下定义的初始值以及须要改变的方法:
import {appRouter} from '../assets/data/menu';
// 初始值
export const state = {
data: "0",
menuList: appRouter,
pageTitle:'初始值'
}
//如何改变 setData方法名
export const mutations = {
setData(state, val) {
state.data = val
},
changePage(state,val){
state.pageTitle = val
}
}
//实现改变
export const actions = {
setData(contex, val) {
contex.commit("setData", val)
},
changePage(contex,val){
contex.commit("changePage", val)
}
}
复制代码
使用页面,直接调用便可,不用其余依赖:
// 获取全局变量
console.log( this.$store.state.pageTitle) // 初始值
// 更改全局变量
this.$store.commit('changePage', '门店管理')
复制代码
以下图状况:
咱们须要在点击操做列的详情进入下一个页面,那么咱们是须要拿到此行的id 值,而且请求数据,而后再去渲染页面,那么咱们如何经过路由来实现参数的传递呢? 借鉴
第一种:经过path,query 来传参,参数会在地址栏中显示
// 传参
<div>
<router-link tag="a" :to="{path:'detail',query:{id:1}}" >详情</router-link>
</div>
复制代码
// 接收参数
<script>
export default{
mounted (){
const id = this.$route.query.id; //能够拿到从列表页传过来的id
}
}
</script>
复制代码
第二种:经过name,param 来传参,参数不会在地址栏中显示
// 传参
<div>
<router-link tag="a" :to="{name:'detail',params:{id:1}}" >详情</router-link>
</div>
复制代码
// 接收参数
<script>
export default{
mounted (){
const id = this.$route.params.id; //能够拿到从列表页传过来的id
}
}
</script>
复制代码
**⚠️注意:取参数时用的是this.$route
,而不是this.$router
。
上面两个大同小异,接下来咱们试试传动态的参数:
// 传参
<div>
<router-link tag="a" :to="{name:'detail',params:{id:val}}" >详情</router-link>
</div>
复制代码
// 接收参数
<script>
export default{
data () {
val:1212
},
mounted () {
const val = this.$route.params.val; //能够拿到从列表页传过来的val值
}
}
</script>
复制代码
继续升级,接下来咱们试试,传多个动态参数,每一个key用逗号分割便可:
// 传参
<div>
<router-link tag="a" :to="{name:'detail',params:{id:id,name:name,age:age}}" >详情</router-link>
</div>
复制代码
// 接收参数
<script>
export default{
data () {
id:1212,
name:"张小一",
age:10
},
mounted () {
const id = this.$route.params.id; //能够拿到从列表页传过来的id值
const name = this.$route.params.name; //能够拿到从列表页传过来的name值
const age = this.$route.params.age; //能够拿到从列表页传过来的age值
}
}
</script>
复制代码
再升级,咱们接下来传一个数组改如何操做
// 传参
<div>
<router-link tag="a" :to="{name:'detail',params:{list:[1,2,3,4]}}">详情</router-link>
</div>
复制代码
// 接收参数
<script>
export default{
data () {
arr:
},
mounted () {
const list = this.$route.params.list; //能够拿到从列表页传过来的list数组
}
}
</script>
复制代码
!!!⚠️注意:通常状况下不建议使用路由传过多的参数
某天有看到一篇大佬的文章,讲述的是跳转页面后,原页面计时器仍然在执行的问题,正好本身也有写国一个实时的钟表的demo,因而就实验了一番:
页面以下:
在每次进入页面后调用了setTimeout,每秒去更新时间,为了验证切换路由后,是否还会调用计时器,我在计时器后面加了一个打印数值来观察,以下:
...
...
...
this.inif.oSecond = seconds;
this.inif.seconds = seconds * 6;
this.inif.minute = minutes * 6 + seconds * (6 / 60);
this.inif.hour = (hours - 12) * 30 + minutes * (360 / 12 / 60);
//调用计时器
this.timer = setTimeout(this.time, 1000)
//打印参考值
console.log(this.inif.seconds)
复制代码
能够看到后台的打印状况:
如今咱们切换路由去往其余的页面,看看计时器是否中止:
实际证实,它并无中止,计时器依然在执行。这样是很是消耗性能的。接下来咱们来看看,大神是怎么解决的:
第一种解决方案:
在beforeDestroy
生命周期内进行清除:
beforeDestroy() {
clearInterval(this.timer);
this.timer = null;
}
复制代码
鉴于上面的方法,大神给出解释:咱们的代码独立于清理代码,此种操做使得咱们比较难于程序化的清理咱们创建的全部东西。
第二种解决方案:
经过$once
来监听定时器,在beforeDestroy
钩子能够被清除
...
...
...
this.timer = setTimeout(this.time, 1000)
this.$once('hook:beforeDestroy', () => {
clearInterval(this.timer);
})
复制代码
两种解决方案均可以将咱们的问题解决,相对来讲第二种较优雅!!! 借鉴于 chinaBerg 大神
dist
文件夹的js
里面会有不少.map
文件项目打包后,代码都是通过压缩加密的,若是运行时报错,输出的错误信息没法准确得知是哪里的代码报错。而生成的
.map
后缀的文件,就能够像没有加密的代码同样,能够准肯定位到错误的位置,能够经过设置来不生成该类文件,由于咱们在生成环境是不须要.map
文件的,因此能够在打包时不用生成这些文件。
解决方案:
在config/index.js文件中,设置productionSourceMap: false,就能够不生成.map文件
vue
的url
路径,发生变化时刷新页面此需求是因为项目中一个列表中详情点击后须要从新请求当前列的
id
,从新绘制当前页面,以下:
this.$router.push({
path: '/crowdmanage/crowddetails',
query: {
name: 'detail',
id: 17
}
});
复制代码
点击后url
确实发生了变化,但vue并无检测到,也就是url
变化了,页面并无从新去请求??????究竟是什么状况????---(此时第一感受是:个人跳转方式哪里出现了问题吗?为何vue 检测不到呢?或者我要换成原生的跳转??.....) 去咨询了团队的前端小哥哥,小哥哥给出了如下方式解决:---》》》》
因为个人页面组件里面嵌套了小的组件,因此我须要在跳转到的.vue
的页面添加:
watch: {
$route(to, from) {
this.initData();
}
}
复制代码
this.initData()
是全部的请求信息,当url发生变化后,watch
就能够监听到,而后从新去请求数据。啦啦啦啦啦 解决了。。。。。感谢小哥哥!!!
此时场景为:当一个组件里面有3块内容,并且这三块内容每次展现都只展现一个
tab
,不会同时展示,以下图:
index
文件里。
首先,咱们先建一个主
index
文件,用于包裹三个子文件,再建三个子的.vue
文件,这四个文件并列便可。
index.vue
主文件内容以下(如下tabs
来自UI
组件iview
):
<template>
<div>
<Tabs size="small" @on-click="tabChange" v-model="tabContent">
<TabPane v-for="(item,index) in tabList" :key="index" :label="item.label" :name="item.name"></TabPane>
</Tabs>
<--用:is的方式绑定动态变量,变量改变,随之显示的组件切换-->
<component :is="tabView"></component>
</div>
</template>
<script>
//引入三个子组件
import A from "./A"
import B from "./B"
import C from "./C"
export default {
data() {
return {
tabContent:"",
tabView: "",
tabList: [{
name: "a",
label: "标签a"
},
{
name: "b",
label: "标签b"
},
{
name: "c",
label: "标签c"
}
],
}
},
// 注册组件
components: {
A, // 标签a
B, // 标签b
C, // 标签c
},
mounted() {
this.tabChange(name)
},
methods: {
//切换tab事件
tabChange(name) {
this.tabView="A";
this.tabContent = name || "a";
if (name === "a") {
this.tabView = A;
} else if (name === "b") {
this.tabView = B
}else if (name === "c") {
this.tabView = C
}
},
},
watch: {}
}
</script>
<style scoped lang="less">
</style>
复制代码
子组件的A.vue
的文件内容以下:
<template>
<!-- 第一个tab页的内容 -->
<div>
我是标签a的内容
</div>
</template>
<script>
export default {
data() {
return {
}
},
props: {},
components: {},
mounted() {},
methods: {},
watch: {}
}
</script>
<style scoped lang="less">
</style>
复制代码
其余几个子文件也如同A文件同样,这样点击不一样的tab
就会请求不一样的.vue
文件。
keep-alive
缓存动态组件,以及它的参数,主要用于保留组件状态或避免从新渲染。
<keep-alive>
包裹动态组件时,会缓存不活动的组件实例,而不是销毁它们。
Props
:
include
- 字符串或正则表达式。只有名称匹配的组件会被缓存。exclude
- 字符串或正则表达式。任何名称匹配的组件都不会被缓存。max
- 数字。最多能够缓存多少组件实例。<!-- 基本 -->
<keep-alive>
<component :is="view"></component>
</keep-alive>
<!-- 多个条件判断的子组件 -->
<keep-alive>
<comp-a v-if="a > 1"></comp-a>
<comp-b v-else></comp-b>
</keep-alive>
<!-- 和 `<transition>` 一块儿使用 -->
<transition>
<keep-alive>
<component :is="view"></component>
</keep-alive>
</transition>
复制代码
注意,``是用在其一个直属的子组件被开关的情形。若是你在其中有 `v-for` 则不会工做。若是有上述的多个条件性的子元素,`` 要求同时只有一个子元素被渲染。
include
和 exclude
属性容许组件有条件地缓存。两者均可以用逗号分隔字符串、正则表达式或一个数组来表示:<!-- 逗号分隔字符串 -->
<keep-alive include="a,b">
<component :is="view"></component>
</keep-alive>
<!-- 正则表达式 (使用 `v-bind`) -->
<keep-alive :include="/a|b/">
<component :is="view"></component>
</keep-alive>
<!-- 数组 (使用 `v-bind`) -->
<keep-alive :include="['a', 'b']">
<component :is="view"></component>
</keep-alive>
复制代码
max
最多能够缓存多少组件实例。一旦这个数字达到了,在新实例被建立以前,已缓存组件中最久没有被访问的实例会被销毁掉。<keep-alive :max="10">
<component :is="view"></component>
</keep-alive>
复制代码
props
首先来写一个父子组件传参的例子🌰: 父组件内容:
<template>
<div>
下面是引入的组件:
<template-a :isItem="item"><template-a/>
</div>
</template>
<script>
import templateA from "./templateA"
export default {
data () {
return {
item:"000"
}
},
components: {
templateA
},
methods: {
},
mounted () {
}
}
</script>
<style>
</style>
复制代码
子组件内容:
<template>
<div>
我是templateA 组件,这是从父组件传过来的参数: {{isItem}}
</div>
</template>
<script>
export default {
data () {
return {
}
},
props:{
isItem:{
type:String,
default:""
}
},
components: {
},
methods: {
},
mounted () {
}
}
</script>
<style>
</style>
复制代码
给props
配置多个类型
例若有时咱们在传递参数的时候,不肯定拿到是什么类型,有多是
Number
有多是String
,此时咱们就可给props
的默认类型时添加一个数组,以下:
props:{
data: {
type: [String, Number],
default: ''
},
}
复制代码
这样在拿到参数的时候,不管是string
仍是number
都不会由于类型错误而报错,加大了传参的容错率。 详细参考
props
执行的比data
早,因此在data中能够拿到props
中的传值。computed
在咱们的平常编码中,每每会遇到不少须要判断的条件、计算数据或者控制权限等,以下:
条件判断: AA&&BB&&cc ;
计算数据: A+B-C-D 、 message.split('').reverse().join('');
控制权限: A === B || B===C ;
复制代码
以上的内容咱们能够在标签或者模版
{{}}
中进行判断,计算,但若是逻辑较多,或者条件较复杂,这样还在标签或者模版上进行操做的话,咱们的代码就看起来会很难理解,并且很冗余,这时,咱们能够把这些复杂的逻辑判断放到computed
中进行计算,返给模版一个变量便可:
<template>
<div id="example">
<p>未计算前的值: "{{ message }}"</p>
<p>计算完毕返回的值: "{{ reversedMessage }}"</p>
</div>
</template>
<script>
export default {
data () {
return {
message: 'Hello',
}
},
computed: {
// 计算属性的 getter 在这里面进行一系列的计算,最后return出一个结果给模版
reversedMessage: function () {
// `this` 指向 vm 实例
return this.message.split('').reverse().join('*')
}
},
components: {
},
methods: {
},
mounted () {
}
}
</script>
<style>
</style>
复制代码
页面展现效果以下:
计算属性是基于它们的依赖进行缓存的。只在相关依赖发生改变时它们才会从新求值。这就意味着只要
message
尚未发生改变,屡次访问reversedMessage
计算属性会当即返回以前的计算结果,而没必要再次执行函数。
参考:vue-computed
bus
关于组件和组件之间的参数传递(非父子),
vue
推荐使用bus
来进行传递,可进行上行、下行、平行、斜行各类传递,下面咱们就来用bus来验证。 首先须要先将它建立出来,能够放在公用的工具js
中,最后统一引入到全局mian.js
中或者直接在mian
中均可以,根据你状况建立并引入就行:
import Vue from "vue";
export default new Vue()
复制代码
此时就能够直接用了,下面让咱们来传个参数试试:
A页面:
<template>
<div id="example">
<Button @click="searIconClick" slot="append" icon="ios-search"></Button>
</div>
</template>
<script>
export default {
data () {
return {
message: 'Hello',
}
},
methods: {
// 当点击按钮后,将message使用$emit传给B页面
searIconClick(){
this.bus.$emit("searInfo", this.message);
}
},
}
</script>
复制代码
B页面:
<template>
<div id="example">
{{value}}
</div>
</template>
<script>
export default {
data () {
return {
value: '',
}
},
components: {
},
methods: {
},
mounted () {
this.bus.$on('searInfo', (message) => {
this.value = message;
});
}
}
</script>
<style>
</style>
复制代码
A
页面发送的事件名和B
页面接受的事件名必须一致,并且需是全项目惟一的,否则会被其余传参影响,或者影响其余传参,我以前就出过这样的错,让小姐姐找问题找来好久😂 !
在咱们项目中,有时须要进行一些计算,只要数据改变,计算实时更新,如数据不发生变化,缓存计算结果。 效果展现地址:
在
vue
中的锚连接和普通的html
不一样,关于vue
中的锚连接能够参考vue
中的scrollBehavior
滚动行为
----------------废话很少说,直接上代码-----------
在router.js
中的router
实例中
const router = new VueRouter({
routes,
mode: 'history',
scrollBehavior(to, from, savedPosition) {
if (to.hash) {
return {
selector: to.hash
}
}
}
})
export default router;
复制代码
在vue
中点击跳转的位置 使用<a>
连接包起来
<div>
<a href="#populationInformation">A</a>
</div>
<div>
<a href="#peopleCounting">B</a>
</div>
<div>
<a href="#trafficAnalysis">C</a>
</div>
复制代码
在须要跳转到的位置
<div id='populationInformation '> A跳转到此</div>
<div id='peopleCounting'> B跳转到此</div>
<div id='trafficAnalysis '>C跳转到此</div>
复制代码
要保证<a>
标签的 href 的地址要和下面id
的值是相同的才能够完成相应的跳转, 至于在router
中的配置也是必须的。
当场景须要咱们获取url地址,以作某些判断操做时,咱们可使用下面的方法来获取。
1.获取所有url
console.log("完整的url地址:",window.location.href)
// 完整的url地址: https://juejin.im/editor/posts/5a1a6a6551882534af25a86b
复制代码
2.获取路由路径
console.log("路由路径:",this.$route.path)
// 路由路径:/activity/list
复制代码
3.获取路径参数
console.log("路径参数:",this.$route.query)
// 路径参数: {name: "detail", id: "109", tabView: "self", groupID: ""}
复制代码
(参考:十8、经过路由传参,获取参数,用于记录状态等)
1.经过后端接口直接经过url跳转到下载地址便可
window.location.replace(http://172.******/exports/${id}/download`)
复制代码
2.经过后端接口前端实现下载请求
this.$axios.get(`${this.$config.apiDomain}/crowds/exports/${row.id}/download-crowd`)
.then(({data})=>{
// data 直接传入now Blob中
const blob = new Blob([data], { type: 'cache-control,expires,pragma,content-type' })
const downloadElement = document.createElement('a')
const href = window.URL.createObjectURL(blob)
downloadElement.href = href
downloadElement.download = row.id+'.csv'
document.body.appendChild(downloadElement)
downloadElement.click()
document.body.removeChild(downloadElement) // 下载完成移除元素
window.URL.revokeObjectURL(href) // 释放掉blob对
})
复制代码
现阶段咱们前端开发者作项目通常手里都有各类各样的
UI
库,例如vue
的UI
库有iview
,elementUI
等等,UI
库的组件都会提供一些须要的事件,你可能有不少次想要在一个组件的根元素上直接监听一个原生事件。这时,你可使用v-on
的.native
修饰符:
<base-input v-on:focus.native="onFocus"></base-input>
复制代码
值得推荐:
接下来我还会持续追加,看文章的小伙伴们能够添加一下关注哦!
做者:Christine
出处:https://juejin.im/post/5a125827518825293b4fea8a
版权全部,欢迎保留原文连接进行转载:)
复制代码
若是你对我对文章感兴趣或者有些建议想说给我听👂,也能够添加一下微信哦!
PS:目前找工做中,求大佬们内推,中高级前端,偏JS,Vue,北京。
邮箱:christine_lxq@sina.com
最后:
祝各位工做顺利!
-小菜鸟Christine
复制代码