1. v-for中使用v-model
1.1 报错实例
<div v-for="(shopitem, index) in productsGroup" :key="index">
<checkout-comment v-model="shopitem"></checkout-comment>
</div>
1.2 报错信息
You are binding v-model directly to a v-for iteration alias. This will not be able to modify the v-for source array because writing to the alias is like modifying a function local variable. Consider using an array of objects and use v-model on an object property instead.
翻译内容
您正在将v-model直接绑定到v-for迭代别名。这将无法修改v-for源数组,因为写入别名就像修改函数局部变量。考虑使用一个对象数组,对对象属性使用v-model。
1.3 解决方案
v-model不可以直接修改 v-for循环迭代时别名上的数据, 可以通过index下标来引用所需的数据, 达到目的
<div v-for="(shopitem, index) in productsGroup" :key="index">
<checkout-comment v-model="productsGroup[index]"></checkout-comment>
</div>
2. 网页双击不选中html文字
在DOM元素上添加onselectstart="return false"即可,该DOM元素及其子元素均不可双击选中
3. 单选框取消选中
3.1 方法1:使用复选框模拟(手动更改样式,以elementui为例)
// 设置max属性,缺点:需要将选中的先取消选中,才可以选别的
<el-checkbox-group v-model="check" :max="1">
<el-checkbox label="1"></el-checkbox>
<el-checkbox label="2"></el-checkbox>
</el-checkbox-group>
// 绑定change方法,缺点:需要手动去设置
<el-checkbox-group v-model="check" @change="change">
<el-checkbox label="1"></el-checkbox>
<el-checkbox label="2"></el-checkbox>
</el-checkbox-group>
change(val) {
this.check = this.check.length > 1 ? [this.check[1]] : val;
}
3.2 方法2:手动设置单选框状态
<el-radio-group v-model="radio">
<el-radio label="1" @click.native.prevent="change('1')"></el-radio>
<el-radio label="2" @click.native.prevent="change('2')"></el-radio>
</el-radio-group>
change(val) {
this.radio = this.radio == val ? "" : val;
},
4. token过期一次提示
4.1 起因
当token过期后,同时向后端发起n个请求,根据后端返回的过期提示,提示用户重新登录
4.2 解决方案
思路:定义一个变量,来标识是否弹窗,当第一次接受到token过期code码,进行弹窗,并将标识置为其他值
// 全局变量 -> tokenInvaildFlag
if (error.response.data.code === 403 && globalVariable.tokenInvaildFlag == 0) {
globalVariable.tokenInvaildFlag = 1;
ELEMENT.MessageBox.alert("登录已过期,请重新登录", "提示", {
confirmButtonText: "确定",
callback: (action) => {
// do sth
},
});
}
5. Vue项目配置问题
5.1 全局scss变量
- 安装插件
npm i sass-resources-loader --save-dev
- 修改配置文件
- 老版本 build/utils.js
// scss: generateLoaders('sass')
->
scss: generateLoaders("sass").concat({
loader: "sass-resources-loader",
options: {
resources: path.resolve(__dirname, "../src/styles/variables.scss"),
},
}),
- 新版本 vue.config.js
css: {
loaderOptions: {
// 全局配置scss
scss: {
prependData: `@import "~@/assets/css/mixin.scss";@import "~@/assets/css/variables.scss";`,
},
},
},
- 定义变量 variables.scss
$themeColor: #123456
- 页面中引用
<style lang="scss" scoped>
div {
color: $themeColor;
}
</style>
5.2 cdn配置
- 修改配置文件
- 老版本 build/webpack.base.conf.js
module.exports = {
externals: {
vue: "Vue",
vueRouter: "vue-router",
vuex: "Vuex",
axios: "axios",
element: "element-ui",
echarts: "echarts", //默认是配置引用的库(这里是echarts)暴露出的全局变量
},
}
- 新版本 vue.config.js
module.exports = {
chainWebpack: (config) => {
config.externals({
vue: "Vue",
vueRouter: "vue-router",
vuex: "Vuex",
axios: "axios",
element: "element-ui",
echarts: "echarts", //默认是配置引用的库(这里是echarts)暴露出的全局变量
});
}
}
5.3 别名配置
- 老版本 build/webpack.base.conf.js
module.exports = [
resolve: {
alias: {
vue$: 'vue/dist/vue.esm.js',
'@': resolve('src'),
}
},
}
- 新版本 vue.config.js
module.exports = {
chainWebpack: (config) => {
config.resolve.alias
.set("img", resolve("src/assets/images")) // html中引用需要加~
.set("api", resolve("src/api"));
},
}
6. Vue实例创建时初始化顺序(源码)
initLifecycle(vm);
initEvents(vm);
initRender(vm);
callHook(vm, 'beforeCreate');
initInjections(vm); // resolve injections before data/props
initState(vm);
initProvide(vm); // resolve provide after data/props
callHook(vm, 'created');
其中initState方法如下
function initState (vm) {
vm._watchers = [];
var opts = vm.$options;
if (opts.props) { initProps(vm, opts.props); }
if (opts.methods) { initMethods(vm, opts.methods); }
if (opts.data) {
initData(vm);
} else {
observe(vm._data = {}, true /* asRootData */);
}
if (opts.computed) { initComputed(vm, opts.computed); }
if (opts.watch && opts.watch !== nativeWatch) {
initWatch(vm, opts.watch);
}
}
可以看出,初始化顺序为:props, methods, data, computed, watch
7. Vue多路由引用同一组件,切换时组件更新问题
示例代码:
{
path: '/user',
component: A
},
{
path: '/role',
component: A
}
当从/user切换到/role时,组件A并不会重新加载
解决方法:
- 在组件A中监听路由,变化时重新调用接口
- 给
<router-view :key="$route.fullPath">,该方法在做<keep-alive>缓存时,会使缓存失效,慎用
8. vue-router组件导航守卫不生效问题
示例代码:
// 路由
{
path: '/user',
component: User
}
// 父组件 User.vue
<div>
<Child />
</div>
beforeRouteEnter(to, from, next) {
console.log('parent')
}
// 子组件 Child.vue
...DOM
beforeRouteEnter(to, from, next) {
console.log('child')
}
当路由跳转到/user时,控制台只会输出parent,这是因为组件导航守卫只会作用到以<router-view>作为出口的组件身上,即例子中的User.vue
9. vue create创建vue项目,报spawn yarn enoent
9.1 原因
设置yarn为默认包管理工具,但是没有找到yarn
9.2 解决方案
-
安装
yarn -
修改默认包管理工具
// C:/user/.vuerc
{
"useTaobaoRegistry": false,
"latestVersion": "4.5.15",
"lastChecked": 1636436558444,
"packageManager": "yarn" // 将这里修改为npm
}
- 创建项目时指定包管理工具
vue create <projectname> -m, --packageManager npm