1.vue v-for 循环一个数组,key值报错,但是数据是正常显示的
报错:
v-for使用key,需要在key前加上:key;
srcList是个数组,key值绑定不能是数据类型Object的item,应该绑定item对象下一个属性,这个属性不能重复出现,否则依旧会出现key值报错;你这里可以改成v-for="(item,index) in srcList" :key="index",index对象数组里的索引,不会重复出现,也就不会报错
2.计算属性 和 watch 的区别
计算属性是自动监听依赖值的变化,从而动态返回内容,监听是一个过程,在监听的值变化时,可以触发一个回调,并做一些事情
所以区别来源于用法,只是需要动态值,那就用计算属性;需要知道值的改变后执行业务逻辑,才用 watch,用反或混用虽然可行,但都是不正确的用法
watch 用法: 例如有请求需要再也没初始化的时候就执行一次,然后监听他的变化,很多人这么写:
created(){ this.fetchPostList() }, watch: { searchInputValue(){ this.fetchPostList() } }
上面这种写法,我们完全可以如下写:
watch: { searchInputValue:{ handler: 'fetchPostList',
immediate: true } }
immediate:true代表如果在 wacth 里声明了之后,就会立即先去执行里面的handler方法,如果为 false就跟我们以前的效果一样,不会在绑定的时候就执行。
3.keep-alive
简单来说,就是把一个组件的编译缓存起来
4.router 与 route 的区别
$route对象表示当前的路由信息,包含了当前 URL 解析得到的信息。包含当前的路径,参数,query对象等。
// 1.$route.path 字符串,对应当前路由的路径,总是解析为绝对路径,如 "/foo/bar"。 // 2.$route.params 一个 key/value 对象,包含了 动态片段 和 全匹配片段, 如果没有路由参数,就是一个空对象。 // 3.$route.query 一个 key/value 对象,表示 URL 查询参数。 例如,对于路径 /foo?user=1,则有 $route.query.user == 1, 如果没有查询参数,则是个空对象。 // 4.$route.hash 当前路由的 hash 值 (不带 #) ,如果没有 hash 值,则为空字符串。锚点 // 5.$route.fullPath 完成解析后的 URL,包含查询参数和 hash 的完整路径。 // 6.$route.matched** 数组,包含当前匹配的路径中所包含的所有片段所对应的配置参数对象。 // 7.$route.name 当前路径名字** // 8.$route.meta 路由元信息
$router对象是全局路由的实例,是router构造方法的实例。
路由实例方法:
1. $router.push()
// 字符串 this.$router.push('home') // 对象 this.$router.push({ path: 'home' }) // 命名的路由 this.$router.push({ name: 'user', params: { userId: 123 }}) // 带查询参数,变成 /register?plan=123 this.$router.push({ path: 'register', query: { plan: '123' }}) // push方法其实和<router-link :to="...">是等同的。 // 注意:push方法的跳转会向 history 栈添加一个新的记录,当我们点击浏览器的返回按钮时可以看到之前的页面。
2. $router.go()
// 页面路由跳转 前进或者后退 this.$router.go(-1) // 后退
3. $router.replace()
//push方法会向 history 栈添加一个新的记录,而replace方法是替换当前的页面,不会向 history 栈添加一个新的记录 // 一般使用replace来做404页面 this.$router.replace('/') // 配置路由时path有时候会加 '/' 有时候不加,以'/'开头的会被当作根路径,就不会一直嵌套之前的路径。
5.vue base64编码
// 项目根目录下安装 npm install --save js-base64 // 项目文件中引入 let Base64 = require('js-base64').Base64 // base64编码 Base64.encode('dankogai'); // ZGFua29nYWk= // base64解码 Base64.decode('5bCP6aO85by-'); // 小飼弾 // base64加密后的内容,如果放到 url中传输,就会出现空格问题,即经过加密的字符串中如果有‘+’号,就会变成空格 encodeURIComponent(Base64.encode('dankogai'))
6.vue 实现消息的无缝滚动效果
<template> <div id="box" @mouseover="pause" @mouseout="goon"> <ul id="con1" ref="con1" :class="{anim:animate==true}"> <li v-for='item in items'>{{item.name}}</li> </ul> </div> </template> <script> export default { data() { return { animate:false, timer: null, items:[ //消息列表对应的数组 {name:"马云"}, {name:"雷军"}, {name:"王勤"} ] } }, created(){ setInterval(this.scroll,1000) // 在钩子函数中调用我在method 里面写的scroll()方法,注意此处不要忘记加this,我在这个位置掉了好几次坑,都是因为忘记写this。 }, methods: { play () { this.timer = setInterval(this.scroll, 2000) }, pause () { clearInterval(this.timer) }, goon () { this.timer = setInterval(this.scroll, this.val.scrollSpeed * 1000) }, scroll(){ let con1 = this.$refs.con1; con1.style.marginTop='-30px'; this.animate=!this.animate; var that = this; // 在异步函数中会出现this的偏移问题,此处一定要先保存好this的指向 setTimeout(function(){ that.items.push(that.items[0]); that.items.shift(); con1.style.marginTop='0px'; that.animate=!that.animate; // 这个地方如果不把animate 取反会出现消息回滚的现象,此时把ul 元素的过渡属性取消掉就可以完美实现无缝滚动的效果了 },500) } } } </script> <style> *{ margin: 0 ; padding: 0; } #box{ 300px; height: 32px; line-height: 30px; overflow: hidden; padding-left: 30px; border: 1px solid black; transition: all 0.5s; } .anim{ transition: all 0.5s; } #con1 li{ list-style: none; line-height: 30px; height: 30px; } </style>
7.vue 项目结构启动原理
vue调用顺序: index.html → main.js → app.vue → index.js → components/组件
一般项目创建好后会有三个文件:index.html、main.js、app.vue
1、index.html :所有vue文件都是单页面形式开发,所有vue组件都是通过index.html进行渲染加载。
2、main.js:相当于
java的入口函数,控制初次启动vue项目要加载的组件
import Vue from 'vue' 引入vue
import App from './App' 引入App.vue文件
import router from './router' 引入一段路由配置
Vue.use(C)全局方法定义为C
el:'#app'这个和index.html中的app组件挂钩。官网解释为:模板将会替换挂载的元素。
watch:用来监听路由的变换,可以用来定义页面切换时的过渡效果。
3、App.vue默认为一个根组件
export 中的name属性组件名字
created:生命周期函数
4、index.js文件
引入组件的代码
routes定义时,path为你以后页面间路由跳转的路径
name为import进来的名字
component也为这个名字
其他文件:
-build
-build.js 生产环境构建脚本
-utils.js 构建相关工具方法
-webpack.base.conf.js webpack基础配置
-webpack.dev.conf.js webpack开发环境配置
-webpack.prod.conf.js 生产环境配置
-confg 项目配置
--dev.env.js 开发环境变量
--index.js 项目配置文件
--prod.env.js 生产环境变量
--test.env.js 测试环境变量
-package.json npm包配置文件,里面定义了项目的npm脚本,依赖包等信息
-src 源码目录
--main.js 入口js文件
--app.vue 根组件
--components 公共组件目录
--title.vue
————————————————
版权声明:本文为CSDN博主「No Silver Bullet」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/sunhuaqiang1/article/details/85099769
8.vue 生命周期相关
生命周期:Vue 实例从开始创建、初始化数据、编译模板、挂载Dom→渲染、更新→渲染、卸载等一系列过程,我们称这是 Vue 的生命周期,各个阶段有相对应的事件钩子
注意:
-
created阶段的ajax请求与mounted请求的区别:前者页面视图未出现,如果请求信息过多,页面会长时间处于白屏状态
-
mounted 不会承诺所有的子组件也都一起被挂载。如果你希望等到整个视图都渲染完毕,可以用 vm.$nextTick
vue2.0之后主动调用$destroy()不会移除dom节点,作者不推荐直接destroy这种做法,如果实在需要这样用可以在这个生命周期钩子中手动移除dom节点
单个组件的生命周期
-
初始化组件时,仅执行了beforeCreate/Created/beforeMount/mounted四个钩子函数
-
当改变data中定义的变量(响应式变量)时,会执行beforeUpdate/updated钩子函数
-
当切换组件(当前组件未缓存)时,会执行beforeDestory/destroyed钩子函数
-
初始化和销毁时的生命钩子函数均只会执行一次,beforeUpdate/updated可多次执行
父子组件的生命周期
//父组件 <script> import Child from './Child'; export default { components: { Child }, beforeCreate() { console.log('parent before create'); }, created() { console.log('parent created'); }, beforeMount() { console.log('parent before mount'); }, mounted() { console.log('parent mounted') }, render(h) { console.log('parent render'); return ( <div> <h1>Vue中父子组件的挂载顺序</h1> <h1>父亲</h1> <Child/> </div> ) }, } </script> // 子组件 <script> export default { beforeCreate() { console.log('child before create'); }, created() { console.log('child created'); }, beforeMount() { console.log('child before mount'); }, mounted() { console.log('child mounted') }, render(h) { console.log('child render'); return ( <div> <h1>Vue中父子组件的挂载顺序</h1> <h1>孩子</h1> </div> ) }, } </script>
父子组件中使用render函数代替<template>,打印输出结果
父组件先初始化 -> 父组件渲染完毕 -> 子组件开始初始化 -> 子组件挂载完毕 -> 父组件挂载完毕
-
仅当子组件完成挂载后,父组件才会挂载
-
当子组件完成挂载后,父组件会主动执行一次beforeUpdate/updated钩子函数(仅首次)
-
父子组件在data变化中是分别监控的,但是在更新props中的数据是关联的(可实践)
-
销毁父组件时,先将子组件销毁后才会销毁父组件
兄弟组件的生命周期
-
组件的初始化(mounted之前)分开进行,挂载是从上到下依次进行
-
当没有数据关联时,兄弟组件之间的更新和销毁是互不关联的
宏mixin的生命周期
- mixin中的生命周期与引入该组件的生命周期是仅仅关联的,且mixin的生命周期优先执行
9. 怎样监听vuex中的数据变化
将vuex中的数据映射成组件中的计算属性
import { mayState } from 'vuex'; . . . computed: { ...mapState([ 'dataName' ]) }
10. 自定义组件的v-model
// 父组件 <template> <div class="login"> <BaseInput :value="message" @input="message = $event"/>
<p>文字: {{message}}</p>
<hr/>
<BaseCheckbox style="40px;height:40px;" :checked="checked" @change="checked = $event"></BaseCheckbox>
<p>是否选中: {{checked}}</p> </div> </template> <script>
import BaseInput from "./baseInput" import BaseCheckbox from './baseCheckbox' export default { components: {
BaseInput, BaseCheckbox }, data() { return {
message: 'Hello 输入框', checked: true, } } }; </script>
// 子组件baseCheckbox <template> <div> <input type="checkbox" :checked="checked" @change="handleChange" /> </div> </template> <script> export default { model: { prop: 'checked', event: 'change' }, props: ['checked'], methods: { handleChange(e) { this.$emit('change', e.target.checked); } } }; </script>
// 子组件baseInput <template> <div> <input type="text" :value="value" @input="handleInput" /> </div> </template> <script> export default { props: ['value'], methods: { handleInput(e) { this.$emit('input', e.target.value); } } }; </script>
11. Vue异步组件
在项目当中有些组件不想马上加载,如点击按钮之后再加载组件,可以使用异步组件
<template> <div> <h1>vue异步组件的使用</h1> <button @click="handleClick">点击加载组件</button> <div v-if="show"> <List /> </div> </div> </template> <script> export default { components: { // 使用异步组件,在需要的时候发送ajax请求,下载对应组件的代码 // List: ()=> import('./list') // 为了便于查看,在控制台中设置文件名称为 list List: ()=> import(/* webpackChunkName: list */'./baseCheckbox') }, data() { return { show: false } }, methods: { handleClick() { this.show = !this.show; } } } </script>
或者使用异步组件工厂函数的形式,设置加载属性,如加载时间,延时时间,加载失败后组件等等
<template>
<div>
<h1>vue异步组件的使用</h1> <button @click="handleClick">点击加载组件</button> <div v-if="show"> <AsyncList/> </div> </div> </template> <script> import LoadingComponent from './LoadingComponent';
import ErrorComponent from './ErrorComponent';
const AsyncList = () => {
return {
component: import('./list'),
loading: LoadingComponent,
error: ErrorComponent,
delay: 200,
timeout: 3000
}
} export default { components: { AsyncList }, data() { return { show: false } }, methods: { handleClick() { this.show = !this.show; } } } </script>