问题一:
要处理生命周期几个函数
*new Vue 创建vue实例
*初始化:生命周期,事件,但代理数据还未开始。
beforeCreate : 此时:无法通过vm访问到data中得数据,methods中的方法。
*初始化:数据监听和数据代理。
created : 此时:可以通过vm访问到data中的数据,methods中的方法。
*此阶段Vue开始解析模板,生成虚拟DOM(内存中),页面还不能显示解析好的内容。
beforeMount : 此时:1.页面中呈现的是未经Vue编译的DOM结构,2.所有DOM的操作,最终都不奏效。
*将内存中的虚拟DOM转为真实DOM插入页面。
mounted : 此时:1.页面中呈现的是经历Vue编译的DOM。2.对DOM的操作均有效(尽可能避免)。至此初始化过程结束,一般在此进行:开启定时器,发送网络请求,订阅消息,绑定自定义事件,等初始化操作。
beforeUpdate
updated
beforeDestroy
destroyed
问题二:
有影响,
有el:问题一解释得流程是有el且没有template的流程会一直渲染到mouted;
没有el:就是没有告诉vm要执行哪个节点,vm迷失了,会走到created就不向下走了,需要调用vm.$mount(el)指定才会执行到mounted;
## MVVM模型
1.M : 模型(Model):对应data中的数据; 最终会出现再vm实例对象身上,所以可以直接被调用;
2.V : 视图(View) : 模板代码(页面);
3.VM : 试图模板(ViewModel): vue实例对象 ;实现页面监听和数据绑定;所以经常用vm这个字段代表vue实例;
## 观察发现:
data中所有属性,最后都出现在vm身上;
vm身上的所有属性及Vue原型上的所有属性,再vue模板中都可以直接使用。
回答:v-model实现的是双向数据绑定,:value是展示默认值,所以,当一个input需要双向数据绑定的时候用v-model,只需要展示默认值的时候直接用value
等价于
## 普通监听
watch:{
isHot(newVal,oldVal){
console.log(newVal,oldVal);
}
}
## 深度监听
watch:{
isHot:{
immediate:false, // 默认是否执行监视(页面加载的时候就执行)
deep:true, // a:{b:c:{}} 如果是多层的那么需要开启deep
handler(newVal,oldVal){
console.log(newVal,oldVal);
}
}
}
## computed(计算属性)监听
computed:{
fullName:{
get(){
return `${this.firstName}-${this.lastName}`
},
set(value){
let arr = value.split('-')
this.firstName = arr[0]
this.lastName = arr[1]
}
}
}
fullName(){
return `${this.firstName}-${this.lastName}`
}
## 又获取又修改需要用完整写法
get :1.初次读取数据时,被调用;2.所依赖的数据发生变化时;
computed:{
fullName:{
get(){
return `${this.firstName}-${this.lastName}`
},
set(value){
let arr = value.split('-')
this.firstName = arr[0]
this.lastName = arr[1]
}
}
}
答:
wacth:监听date中的数据,
computed 计算属性是不需要,且不能再data中声明,可以想data一样使用;
1.computed能完成的功能watch一定都能完成;
2.watch能完成的功能,computed不一定能完成,例如:watch可以异步处理(定时器)
注意:computed能实现的时候都用computed ,couputed不能实现用watch;
1.字符串类型:data中有个属性叫classA:‘normal’,会汇总成为一个class,适用于样式的名称不确定,需要动态绑定;
class = 'a' :class='classA'
2.数组类型:data中有个属性叫arr的数组[‘atgu1’,‘atgu2’,‘atgu3’],适用于要绑定的样式个数不确定,名字也不确定;
class = 'a' :class='arr'
3.对象类型:data中有个属性叫classObj的对象{obj1:false,obj2:true},适用于要绑定的样式个数确定,名字也确定,但是要动态控制用不用;
class='a' :class='classObj'
4.数组和对象可以同时应用
class="[{ active: isActive }, errorClass]"
答:1.v-if 适用于切换频率比较低的场景,不展示的DOM直接被移除了;v-show适用于切换频率比较高的场景,不展示的DOM被隐藏了未移除;使用v-if的时候元素可能获取不到,使用v-show元素一定可以获取到;
2.切换频率较高用v-show;
3.频繁想vm插入清除节点,自然没有v-show隐藏来的好;
4.v-show在页面初次渲染时对于页面性能影响较大,因为需要同时把DOM内容渲染; v-if则在页面初次渲染时只渲染true部分DOM,所以对于页面性能影响较小;
答:for 优先级更高,先遍历后根据遍历的条件进行判断if;(最好不要一起使用)要结合computed 遍历出来 符合条件的,再用v-for遍历;
答案:翻译过来就是如何让这两个表单切换后每次都是清空的,方法有很多 指定key 就会清空
"loginType">
"Enter your username" key="username-input">
"Enter your email address" key="email-input">
{{index}}
正常写法:因为10遍历后是12345678910,看上图显示的index应该是1-9,不会出现重复数据,设立key也不会出现冲突,所以直接用一个item就可以解决代码key不一致的问题,具体情况具体分析,按照当前的这个结构的话,不用index是最明智的;
{{ item-1 }}
方法1,啥都接收不规定类型,不会有报错提示;
props:['name','age']
方法2,生命接收的参数的类型,会又报错提示;
props:{
name:String,
age:Number
}
方法3,生命接收的参数的类型,会又报错提示;
props:{
name:{
type:String,// 类型
required:true, // 必须
}
age:{
default:14, // 默认
type:Number
}
}
注意:不要尝试去修改props中的值;
方法一 父组件通过给子组件传一个函数类型的props来实现,父组件监听子组件事件的变化
父组件:
// 在methods方法中定义getName方法监听子组件是否有变化val 就是子组件传过来的值
methods:{
getName(val){
console.log(val) // 输出结果:张三
}
}
子组件:
props:['getName'] , // 接收父组件传递过来的参数
// 比如说有个点击事件
methods:{
sendName(){
this.getName('张三')
}
}
方法二 自定义事件来实现父组件监听子组件 v-bind: @
父组件:
@methodName = 'getName' />
// 在methods方法中定义getName方法监听子组件中是否触发了一个叫做methodName自定义事件;
methods:{
getName(val){
console.log(val) // 输出结果:李四
}
}
子组件:
// 比如说有个点击事件触发父组件的方法
methods:{
sendName(){
this.$emit('methodName','李四')
}
}
方法三 子组件的ref事件监听子组件的事件变化
父组件:
// 在methods方法中定义getName方法监听子组件中是否触发了一个叫做methodName自定义事件;
mounted(){
this.$refs.child.$on('methodName',this.getName)
this.$refs.child.$on('methodName',(val)=>{
console.log(val)
}) // 用这种方法就不要methods中的getName方法了;
},
methods:{
getName(val){
console.log(val) // 输出结果:李四
}
}
子组件:
// 比如说有个点击事件触发父组件的方法
methods:{
sendName(){
this.$emit('methodName','李四')
}
}
方法四 全局事件总线,比说监听父组件了,任意组件全绝都可以监听
方法五 消息订阅与发布
1.默认插槽
如果子组件中,父组件中调用的子组件的开始标签和结束标签中间的内容将会展示再子组件slot中,
如果子组件没有定义slot,父组件中调用的子组件的开始标签和结束标签中间的内容将不会展示;
2.具名插槽
在子组件中声明插槽带名字
在父组件调用的地方用v-slot:header或者 #header
3.插槽作用域,插槽prop父组件定义的子组件想用子组件中的接到的某个参数某个参数
在父组件中:default要对应到子组件中的user要保持一致记得;
在子组件中,:user要根据父组件中的v-slot:user一致
总结:以上代码中的v-bind 可换成:
以上代码中的v-slot可换成#
理解:是vue的一个插件库,专门用来实现SPA单页面应用的。
需要 npm i vue-router
SPA应用理解?
1.单页 web 应用(single page web application,SPA)。
2.整个应用只有一个完整的页面。
3.点击页面中的导航链接不会刷新页面,只做页面局部更新。
4.数据需要通过ajax请求获得。
什么是路由?
1.一个路由就是一组映射管理(key-value)
2.key为路径,value可能是fuc或component
前端路由:value是个component,用于展示页面内容,当路由器的路径变了,对应的组件就会显示。
总结:路由路由,根据你的路径,由我决定展示哪个组件;
** ## 使用: **
第1步:npm i vue-router
第2步:在main.js中引入并use vue-router(绿色框),第3步定义的路由引入(红色框)
第3步:创建一个router-》index.js 如下图编些router的配置项。
第4步:使用路由
// 1.实现路由的切换
<router-link :to='/about' active-class='action'>About
// 2.指定组件的呈现位置
<router-view:to='/about' active-class='action'>About
注意:切换路由组件,原路由组件被销毁的;
全局路由守卫
router.beforeEach:前置路由守卫 收到参数 to,from ,next;
router.afterEach:后置路由守卫 收到参数 to,from ;
组件路由守卫
beforeRouteEnter:通过路由规则进入组件,收到参数,to,from,next
beforeRouteUpdate:通过路由规则更新组件,收到参数,to,from,next
beforeRouteLeave:通过路由规则离开组件,收到参数,to,from,next
独享路由守卫 只有前置没有后置
beforeEnter:只对设置的组件进行监听,收到参数,to,from,next
** watch 监听 **
watch:{
$route(to,from){
console.log(to.path);
}
},
第一种跳转方式:
// 实现路由的切换
<router-link :to='/about' active-class='action'>About
// 指定组件的呈现位置
注意:如果是跳转二级路由 to的时候要把它父亲的二级带出来;
第二种跳转方式编程
this.$router.push(name:'Hello',paramas:{name:'zhagnsan'})
const router = new VueRouter({...})
router.beforeEach(()=>{
next()
})
router.afterEach(()=>{
next()
})
回答:1.beforeEach前置路由守卫有3个参数,to,from,next
afterEach后置路由守卫有2个参数,to,from,没有next
2.全局前置路由守卫:初始化执行,每次路由切换之前执行,可以根绝to中的meta:{auth:true}去执行是否需要登录
写法 ,用to.meta.auth可以在这个位置判断一下处理跳转到登录页面还是直接跳转指定页面;
3.全局后置路由守卫:每次路由切换后执行。后置路由一般应用于设置页面标题,能成功跳转后再设置title;
const router = new VueRouter({...})
router.beforeEach((to, from, next) => {
console.log(to,from)
next() // 放行就是可以跳转的意思
})
router.afterEach((to, from) => {
console.log(to,from)
})
通过路由规则进入组件:举例不是通过路由规则的import一个组件;
区别:进入,更新,离开;
作用:通过路由规则,进入该组件被调用,更新该组件是被调用,离开该组件是被调用;
// 通过路由规则,进入该组件是被调用
beforeRouteEnter(to,from,next){
console.log(to,from,next)
}
// 通过路由规则,更新该组件是被调用
beforeRouteUpdate(to,from,next){
console.log(to,from,next)
}
// 通过路由规则,离开该组件是被调用
beforeRouteLeave(to,from,next){
console.log(to,from)
}
const router = new VueRouter({
routers: [{
path: “/”,
component: ()=> import(“@/pages/index/index”)
alias: “/Index”
}]
})
回答:http://yuzhankeji.com/Index
回答:router-link 和 编程式路由
**router-link 第1种 跳转路由并携带query参数 **
to的字符串写法
<router-link :to='`/about?name=${item.name}&age=${item.age}`' active-class='action'>About // 传参
to的对象写法
<router-link :to="{path:'/about',query:{name:item.name,age:item.age}}" active-class='action'>About // 传参
to的对象name跳转
<router-link :to="{name:'About',query:{name:item.name,age:item.age}}" active-class='action'>About // 传参
mounted(){this.$route.query } // 接收参数
** router-link 第2种 跳转路由并携带params参数 **
需要在js中配置
path:'detail/:id:name'
<router-link :to='`/about/${item.name}/${item.age}`' active-class='action'>About // 传参
to的对象name跳转
<router-link :to="{name:'About',params:{name:item.name,age:item.age}}" active-class='action'>About // 传参
mounted(){this.$route.params} // 接收参数
总结:特别注意:路由携带params参数时,如使用to得对象写法,则不能使用path配置项,必须使用name配置!
** router-link 第3种 路由的props 配置 **
编程式路由传参
this.$router.push(name:'Add',params:{age:1}) // 跳转可返回
this.$router.replace(name:'Add',params:{age:1}) // 跳转不可返回
this.$router.back() // 返回
this.$router.forward() // 前进
this.$router.go() // +数向前走,-数后退
//路由缓存:路由保持挂载不被销毁;Message是组件名组件名组件名;
// 使用keep-alive 会触发如下两个方法,跟methods同级;
activated(){}
deactivated(){}
区别:进入,更新,离开;
作用:通过路由规则,进入该组件被调用,更新该组件是被调用,离开该组件是被调用;
// 通过路由规则,进入该组件是被调用
beforeRouteEnter(to,from,next){
console.log(to,from,next)
}
// 通过路由规则,更新该组件是被调用
beforeRouteUpdate(to,from,next){
console.log(to,from,next)
}
// 通过路由规则,离开该组件是被调用
beforeRouteLeave(to,from,next){
console.log(to,from)
}
集中式状态(数据)管理的一个vue插件。
多个组件依赖统一状态。-共享
搭建vuex环境
1.安装 npm i vuex
2. 引入store;
import store from ‘你的存放路径’
在new 中 写store使用store;
创建store的两种方式
src下创建store文件夹,新增一个index.js文件
编写index.js文件 创建三个对象分别是actions ,mutations,state
// 引入vuex
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
// 准备actions中的方法接到两个参数一个context一个value - 用于响应组件中的动作(服务员);
// 组件中调用actions this.$store.dispatch('add',2)
const actions = {
add(context,value){
context.commit('ADD',value)
}
}
// 准备mutations中的方法接到两个参数一个state一个value - 用于操作数据(state)(厨师);
// 组件中调用mutations this.$store.commit('ADD',2)
const mutations = {
ADD(state,value){
state.sum += value
}
}
// 准备state - 用于存储数据;
// 组件中调用state的值 ,this.$store.state.sum
const state= {
sum:0
}
// 准备getters - 用于将state中的数据进行加工;有点像计算属性可以处理state中的值;
// 组件中调用getters中的值 this.$store.getters.bigSum方法名
const getters = {
bigSum(state){
return state.sum * 10
}
}
//创建并暴露store
export default new Vuex.Store({
actions,
mutations,
state,
getters
})
方法1.组件中使用store,需要actions
第一步.需要异步处理或者需要判断之类需要调用actions,在组件中调用actions中名称为add的方法,
this.$store.dispatch('add',3)
第二步。在store.js的actions中使用的时候,要有add这个方法,接收两个参数一个context为整个store对象,一个value传过来的值,需要调用mutations中的ADD方法
add(context,value){
context.commit('ADD',value)
}
第三步,在mutations中创建方法接受参数一个state 一个value
ADD(state,value){
state.sum += value
}
方法2,不需要调用actions,在组件中直接调用;
this.$store.commit('ADD',3)
import { mapState ,mapGetters,mapMutations,mapActions} from ‘vuex’
在computed中
...mapState({he:‘sum’,scl:‘school’,sub:‘subject’}) //object写法
...mapState([‘sum’,‘school’,‘subject’]) //数组写法
...mapGetters({bigSum:‘bigSum’}) //object写法
...mapGetters([‘bigSum’]) //数组写法
在methods
@click = 'add(3)' // 必须传参。
...mapMutations({add:'ADD'}) // object
@click = 'ADD(3)' // 必须传参。
...mapMutations(['ADD']) // 数组写法。
@click = 'add(3)' // 必须传参。
...mapActions({add:'add'}) // object
@click = 'add(3)' // 必须传参。
...mapActions(['add']) // 数组写法。
注意:封装注意事项
1.namespaced:true
2.模块化后要用 :
3.指定名称;
4.如果用的commit方法请求的注意要这么写下图
最后的最后,分别把学生和数分别放到不同得文件夹,方便管理
新建js
在store中引入 名字自己定义就行了随便定义,保持一致就行;
总结一下:
1.在组件中调用store中的state $store.state.sum;
2.调用store中actions this.$store.dispatch(‘add’,2) ;
3.调用store中的mutations this.$store.commit(‘ADD’,2);
4.actions中的add方法接受两个参数,第一个参数是整个context,第二个是传过来的值value,context中必须要执行mutations中的方法 context.commit(‘ADD’,value)
5.state中存放的就是全局中的公用状态;
6.getter类似计算属性中的方法有一个参数就是state中的对象且方法必须又返回值必须又return,获取方法$store.getter.方法名。
答案:两个地方需要用到他,
1.组件中.this.$store.commit (‘ADD’,2)
2.actions中使用 context.commit(‘ADD’,2)
(1.)简述代码实现的功能?多个组件共享同一状态
(2.) 描述页面temp2.vue文件最终输出结果?
**vmVue.js文件**
import Vue from 'vue'
export default new Vue()
**Temp-1.vue文件**
**Temp-2.vue文件**
姓名:{{name || "-"}}
手机:{{phone || "-"}}