vue常见问题记录
- 1.不同路由共用同一组件
- 2.点击重复菜单页面数据不刷新
- 3.解决开发环境热加载编译慢
- 4.热重载和热替换
- 5.利用postcss pxtorem自动将px转为rem
- 6.解决跨域
- 7.优雅使用svg
- 8.解决core.js报错
- 9.解决ie兼容问题
- 10.computed、getters传参
- 11.mixins相关问题
- 12.父组件利用v-model传递数据到子组件
- 13.父组件传递数据给子组件,子组件v-model接收
- 14.computed计算属性无法根据state依赖值更新,vue无法监听
- 15.组件间循环调用
- 16.Vue.observable(obj)
- 17.eval()
- 18 v-if 和v-show组件的生命周期
- 19. v-model的用处
- 20. vue-cli3中dart-sass替代node-sass
- 21.源数据为被排序过得数组 运行爆红
- 22.this.$route.matched
- 23.data里如何获取其他data,建议使用methods获取其他data
- 24.如何使用public里的图片
- 25.@import ~
- 26.获取元素时 r e f s 和 refs 和 refs和refs.$el的区别
- 27.父子组件调用顺序
- 28.自定义指令
- 29.watch监听对象排除部分属性监听
1.不同路由共用同一组件
导致组件数据不刷新,created和destroy不会再次触发,组件被复用
方法1、监听路由
watch:{
$route(){
}
}
方法2、绑定唯一key
<router-view :key="key"></router-view>
方法3、或者声明不同的view 但view引入同一个组件
2.点击重复菜单页面数据不刷新
方法1、路由参数加时间戳
<router-view :key="key"></router-view>
this.$router.replace({
path: router,
query: {
t: +new Date() // 保证每次点击路由的query项都是不一样的,确保会重新刷新view
}
})
方法2、重定向
const { fullPath } = this.$route
this.$router.replace({
path: '/redirect' + fullPath
})
//redirect.vue
export default {
beforeCreate() {
const { params, query } = this.$route
const { path } = params
this.$router.replace({ path: '/' + path, query })
},
render: function(h) {
return h() // avoid warning message
}
}
3.解决开发环境热加载编译慢
VUE_CLI_BABEL_TRANSPILE_MODULES用来控制是否使用babel-plugin-dynamic-import-node(在vue-cli代码已实现)
.env.development
VUE_CLI_BABEL_TRANSPILE_MODULES = true
4.热重载和热替换
- hmr (热替换)代码更新,不刷新整个页面,只更新部分修改内容
- hot-reload(热重载) 监测代码,刷新整个页面
//开启热更新
chainWebpack: (config) => {
config.resolve.symlinks(true) // 修复热更新失效
}
5.利用postcss pxtorem自动将px转为rem
第一步:设置根节点的font-size 随窗口大小改变而自适应
//utils/rem.js
const baseSize = 19.2
function setRem() {
// 当前页面宽度相对于 1920 宽的缩放比例,可根据自己需要修改。
const scale = document.documentElement.clientWidth / 1920
// 设置页面根节点字体大小
document.documentElement.style.fontSize = baseSize * Math.min(scale, 2) + "px"
}
setRem()
window.onresize = () => {
setRem()
}
//main.js
import "@/utils/rem" //根据屏幕宽动态更改尺寸
第二步:利用posrcss-pxtorem 使得px自动转为rem
module.exports = {
//vue-cli3自动生成postcss.config.js若未生成则写在vue.config.js
css: {
loaderOptions: {
postcss: {
plugins: [
require("postcss-pxtorem")({
rootValue: 19.2, // 换算的基数 页面尺寸/19.2 1920px=100rem
"selectorBlackList": ['el-']//不转换element
}),
],
},
},
},
}
//main.js
import "postcss-pxtorem" //px-rem
最后:代码使用px即可
6.解决跨域
解决开发环境跨域
本地开发环境解决跨域请求
利用vue-cli3的proxy代理转发
本地模拟服务器,代理转发
//vue.config.js
devServer:{
proxy:{
"/api":{
target:"http://xx";//目标服务器地址
changeOrigin:true;//允许跨域
ws:true;//开启websocket
}
}
}
//axios.js
//请求的地址
VUE_BASE_APP_URL="/api/"
axios.get("/api/xx")
本地开模拟服务器,负责发送和请求目标服务器
7.优雅使用svg
7.1 vue中加载svg图片,svg-sprite-loader
多个svg图片拼接成雪碧图,拼接内容放到body下面,其他地方利用use复用
//1.文件存放如下 src/icons/svg/xx.svg
//2.vue.config.js配置
const path = require("path");
function resolve(dir) {
return path.join(__dirname, dir);
}
chainWebpack: config => {
// use svg
config.module
.rule("svg")
.exclude.add(resolve("src/icons/svg"))
.end();//先删除默认配置中处理svg
config.module
.rule("icon")
.test(/\.svg$/)
.include.add(resolve("src/icons/svg"))
.end();
.use("svg-sprite-loader")
.loader("svg-sprite-loader")
.options({
symbolId: "icon-[name]" //name为svg名字
})
.end();
}
//使用
import "@/icons/svg/add.svg";
<svg aria-hidden="true" width="200px" height="200px">
<use xlink:href="#icon-xx" /> //xx为name名
</svg>
8.解决core.js报错
报类似npm install --save core-js/modules/es.array.find错误
原因:core.js已更新至版本3,删除了“ core-js / modules / es.array.find
但@babel/preset-env 仍导入这个包
//babel.config.js
module.exports={
presets: [["@vue/app", { useBuiltIns: "entry" }]]
}
9.解决ie兼容问题
babel将高级语法转为浏览器识别的语法(不包括promise,symbol等函数),babel-polyfill 解决这个问题
注意:babel/polyfill 7.4后被遗弃,用core-js和regenerator-runtime替代
@bable/preset-env 根据配置的目标环境自动采用需要的babel插件
//vue-cli3中
vue add @vue/babel
10.computed、getters传参
computed:{
getDate(){
return function(params){
return 'xx'
}
}
}
getters:{
getData:state=>params=>{
return params+state.xx
}
}
11.mixins相关问题
11.1 A,B共用一个mixins ,A修改mixins会影响B吗?
- 不会影响,相当于A融合了一份mixins东西,B融合了一份
11.2 mixins里可以使用A或B的属性,方法?
- 可以使用和修改,此时A里的属性就变为mixins里修改过的
11.3 A引用多个mixins ,多个mixins能互相使用对方的数据吗?
能获取到,且mixins1里的数据mixins2也能获取和操作。
11.4 父组件引用A,B,mixins,A里面可以打印出mixins里东西吗?
- 不可以
12.父组件利用v-model传递数据到子组件
//parent
<child v-model="text"></child>
//child
<input :value='text'></input>
this.$emit('input',xx);//更改值
13.父组件传递数据给子组件,子组件v-model接收
//parent
<child :text.sync="text" ></child>
//child
<input v-model="newText" @change="changeInput"/>
props:['text'],
data(){
return{
newText:this.text
}
},
method(){
changeInput(){
this.$emit("update:text","")
}
}
14.computed计算属性无法根据state依赖值更新,vue无法监听
当state为对象 设置新字段时会遇到无法更新问题
//store中
setAddTopic2HashList(state, topic) {
//动态新增属性
#error
let hash = state.topicHashList;
hash[topic.uid] = topic;
#success
第一种
state.topicHashList = Object.assign({}, state.topicHashList, {
[topic.uid]: topic
});
第二种
Vue.set(state.topicHashList,[topic.uid], topic)
},
15.组件间循环调用
组件A中有多个子组件比如C、D,C里引用了A,会提示A组件未注册
原因是组件必须在实例化之前引入
方法1
全局注册A组件、在vue实例化之前
方法2
webpack异步组件,import方式引入
components: {
PosterTemplate: () => import('./Template.vue')
}
方法3
beforeCreate () {
//beforeCreate () {
// 官方文档给出的是require
// this.$options.components.PosterTemplate = require('./Template.vue')
// 在基于vue-cli@2.8.1按照上面的写法还是会报错
// Failed to mount component: template or render function not defined.
// 所以我们应该改为基于es6的写法异步加载一个组件如下
this.$options.components.PosterTemplate = () => import('./Template.vue')
}
16.Vue.observable(obj)
使obj可响应,返回的对象直接用于渲染函数和计算属性内 ,发生改变时触发相应更新
- 实现跨组件数据状态共享,类似最简化的vuex
17.eval()
方法名中拼接变量时
let drawFunction=eval("_draw"+drawType);
drawFunction()
18 v-if 和v-show组件的生命周期
//v-show时
默认值true,false 均执行created,mounted
切换时,生命周期不执行
//v-if时
默认值 false,生命周期不执行
默认值 true, 执行created,mounted
false-->true 执行created,mounted
true--false 执行destory
19. v-model的用处
- 利用v-model控制自身组件显隐
允许自定义组件在使用v-model时自定义prop和event,默认是v-model把value作为prop,input当做event
#父组件
<child v-model='isShow' value="value值"></dhild>
#子组件
model:{
prop:'checked',
event:'change'
},
props:['checked']
等价于
<child :checked='foo' @change='val=>{foo=val}' value="value值"></child>
20. vue-cli3中dart-sass替代node-sass
2. npm i sass sass-loader -D
3. module.exports = {
css: {
loaderOptions: {
sass: {
implementation: require('sass'), // This line must in sass option
},
},
}
//other code
};
- dart-sass不支持/deep/ 可更换为::v-deep
- ::v-deep只支持一级嵌套
// error
op {
::v-deep d{
}
}
//success
::v-deep op {
d{
}
}
21.源数据为被排序过得数组 运行爆红
报错提示 You may have an infinite update loop in a component render function
//error
computed:{
sortTags() {
return function(tags) {
return tags.sort(this.compare("indicators"));
};
}
}
原因是array.sort()改变数组本身,导致过滤器又被触发 导致无限循环,所以因在副本上排序
//success
return value.slice().sort(...)
// arr.slice(start,end) 浅复制返回新数组
22.this.$route.matched
- 返回一路由数组、可做面包屑
例如/a/a1
路由分别匹配到/,/a,/a1
23.data里如何获取其他data,建议使用methods获取其他data
- 不建议data里数据之间依赖 可利用computed
data(){
return {
temp:"测试",
formLogin:()=>{
console.log(this.temp);//利用箭头函数可实现
},
temp1:this.temp;//error 获取不到
}
}
- 使用methods
data(){
return{
temp:this.getData(),
otherData:2
}
}
methods:{
getData(){
console.log(this.otherData)
}
}
24.如何使用public里的图片
- public文件不经过webpack处理 当你通过绝对路径引用它时,留意应用将会部署到哪里
- 如果你的应用没有部署在域名的根部,那么你需要为你的 URL 配置 publicPath 前缀
index.html中
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
在template中
<img :src="`${publicPath}my-image.png`">
data () {
return {
publicPath: process.env.BASE_URL
}
}
在背景图片中使用
<div :style='imgStyle'></div>
data() {
return {
publicPath: process.env.BASE_URL
};
},
computed: {
imgStyle() {
return {
background: `url(${
this.publicPath
}static/mockpng/images/login.png) no-repeat center/cover`
};
}
}
25.@import ~
css文件导入其他css文件有@import
他是遇到@import 才http请求文件
scss里的@import
为生成文件时即导入其他文件,无需额外http请求
@import "~@/xxx"
~xx 表示后面跟的是别名
26.获取元素时 r e f s 和 refs 和 refs和refs.$el的区别
- 若ref绑定在组件上
则this. r e f s . x x 获取的是组件实例 V u e . refs.xx 获取的是组件实例 Vue. refs.xx获取的是组件实例Vue.el获取实例关联的dom元素
-若ref绑定在普通元素上
则this.$refs.xx获取的是dom元素 (offsetWidth ,style,……)
27.父子组件调用顺序
父beforeCreate -> 父created -> 父beforeMount -> 子beforeCreate -> 子created -> 子beforeMount -> 子mounted -> 父mounted
28.自定义指令
29.watch监听对象排除部分属性监听
mounted() {
Object.keys(this.params)
.filter((_) => !["c", "d"].includes(_)) // 排除对c,d属性的监听
.forEach((_) => {
this.$watch((vm) => vm.params[_], handler, {
deep: true,
});
});
},
data() {
return {
params: {
a: 1,
b: 2,
c: 3,
d: 4
},
};
},
watch: {
params: {
deep: true,
handler() {
this.getList;
},
},
}