vue提供了一个内置的标签,专门用来实现动态组件的渲染
动态组件每次被隐藏的组件都会被销毁,再次显示的时候重新创建,可以用keep-alive解决问题,在component外面包一层keep-alive标签,组件被隐藏的时候就是被缓存,不会被销毁
keep-alive对应的生命周期函数:
被缓存的时候,会自动触发deactivated生命周期函数
被激活的时候,会自动触发activated生命周期函数
组件第一次被创建的时候,既会触发created,又会触发activated;切换回来只是执行activated,而不会执行created,因为组件没有被重新创建
keep-alive的include属性:只有匹配属性值的组件才会被缓存 exclude属性:排除项,符合的不被缓存。两个属性二选一,不能同时使用
如果在声明组件的时候,没有为组件指定name名称,则组件的名称默认为注册时候的名称。但是当给组件提供了name属性的时候,组件的名称,就是 name 属性的值
export default {
name: 'MyRight'
}
对比两个组件名称:
组件的 “注册名称” 的主要应用场景是:以标签的形式,把注册好的组件,渲染和使用到页面结构之中
组件声明时候的 “name” 名称的主要应用场景:结合
标签实现组件缓存功能;以及在调试工具中看到组件的 name 名称
插槽(Slot)是vue为组件的封装者提供的能力,允许开发者咋封装组件时,把不确定的、希望由用户指定的部分定义为插槽
在组件中声明一个插槽区域
写在组件的标签之间的内容就会自动渲染到里面去
vue 官方规定:每一个 slot 插槽,都要有一个 name 名称 ,如果省略了 slot 的 name 属性,则有一个默认名称叫做 default。
默认情况下,在使用组件的时候提供的内容会填充到default插槽之中。如果把内容填充到指定名称的插槽中,需要使用v-slot指令,v-slot只能加给组件或者template使用,而不能直接加在元素h3身上。template这个标签是个虚拟元素,只有包裹作用,不会被渲染成任何标签
Left的标题区域
v-slot简写为#,可以在组件声明的区域写后备内容,如果用户不提供内容则生效,提供了内容就会被覆盖
如果需要封装组件时预留多个插槽,应该每个插槽都起名字,具名插槽
插槽还可以添加属性,附带自己的数据,用等号接收。叫做作用域插槽,作用域插槽也可以解构赋值
把counter数量变化的部分用插槽替换eventBus.js。这时候数量组件可以直接被商品组件引用,也可以直接访问item里面的属性。
之后绑定个自定义事件
add是写在methods里面的函数
add(){
/* const obj={id:this.id,value:this.num+1}
bus.$emit('share',obj) */ 注释部分为用eventbus传值的写法
this.$emit('num-change',this.num+1)
}
私有自定义指令:只有该组件能用,在directives节点下定义,和data,methods等平级。基本写法:directives:{color:{bind(el){el.style.color=red}}}
directives: {
// 定义名为 color 的指令,指向一个配置对象
color: {
// 当指令第一次被绑定到元素上的时候,会立即触发 bind 函数
// 形参中的 el 表示当前指令所绑定到的那个 DOM 对象
bind(el, binding) {
el.style.color = binding.value
}
}
update:bind函数只会触发一次,当指令第一次被绑定到元素上的时候。但DOM更新的时候bind函数不会被触发。而update函数会在每次DOM更新时被触发。同样写在directives里面
update(el, binding) {
console.log('触发了 v-color 的 update 函数')
el.style.color = binding.value
}
以上的代码bind和update的逻辑完全相同,可简写为
color(el, binding) {
el.style.color = binding.value
}
全局自定义指令
全局自定义指令通过Vue.directive()定义,要放到main.js里面
Vue.directive('color',{
bind(el,binding){el.style.color=binding.value},
update(el,binding){el.style.coloe=binding.value}
})
//简写形式
Vue.directive('color',function(el,binding){
el.style.color = binding.value
})
自定义指令一般都放在全局去定义
规范代码风格的工具,选择的时候可以选标准模式
了解.eslintrc.js的一些常用语法规则
no-console,禁用console,procss.env.NODE_ENV获取当前的打包模式,如果是production,生产的时候,就是warn警告,如果不是生产,就off,不警告
no-debugger,调试用,打断点的,代码打断点,在需要断点的位置 写 debugger,同样是生产模式警告,开发模式关掉警告
可以根据报错信息去官网搜常见的一些:不允许连用多个空行,不允许多余空格,文末要有一行空行,属性的值之前要有空格,字符串用单引号包裹,对象或数组末尾不允许多余的逗号,注释//后面也要有空格,强制禁止或需要缩进,import放顶部,未使用的变量或常量,方法形参之前保留一个空格…………
禁用规则:要禁用对应规则,去官网查找,然后配置在.eslintrc.js的rules里
装插件,保存时自动规范化:ESLint ,prettier
配置设置
`//ESLint配置`
`"editor.codeActionsOnSave": {`
`"source.fixAll": true`
`},`
`"eslint.alwaysShowStatus": true,`
`"prettier.trailingComma": "none",`
`"prettier.semi": false,`
`//每行文字个数超出此限制将会被迫换行`
`"prettier.printWidth": 300,`
`//使用单引号替换双引号`
`"prettier.singleQuote": true,`
`"prettier.arrowParens": "avoid",`
`//设置.vue 文件中,HTML代码的格式化插件`
`"vetur.format.defaultFormatter.html":"js-beautify-html",`
`"vetur.ignoreProjectWarning": true,`
`"vetur.format.defaultFormatterOptions":{`
`"prettier": {`
`"trailingComma": "none",`
`"semi": false,`
`"singleQuote": true,`
`"arrowParens": "avoid",`
`"printWidth": 300`
`},`
`"js-beautify-html": {"wrap_attributes": false}`
`},`
报错:Component name “Left” should always be multi-word vue/multi-word-component-names,这个问题是因为没有按照驼峰式或者短横式命名,百度只找到了关闭Onsave时候的检查,但是我并不想关掉,所以选择了重命名为MyLeft,报错消失
每次调用axios都要import axios from ‘axios’,很麻烦,可以写到全局(main.js)里面,然后把axios方法写到Vue的原型上Vue.prototype.$http = axios,
今后在组件里调用可以直接写this.$http.get
全局配置axios的请求根路径:axios.defaults.baseURL = ‘http://www.xxx’
但是这样会有缺点,把axios挂载到原型Vue上时,不利于API接口的复用
router 就是对应关系,Hash地址与组件的对应关系
前端路由的工作方式:
实现简易的前端路由:当Hash地址变化时,用window.onhashchange
监听,然后显示对应的组件
使用第三方库:vue-rooter
是vue.js官方给出的路由解决方案,只能在vue里面用,能轻松管理SPA(单页面程序)项目中组件的切换
安装和配置:装包->创建路由模块->导入并挂载模块->声明路由链接和占位符
使用:在src源代码目录,创建router/index.js
导入Vue和VueRouter的包 import from
调用Vue.use()函数,把VueRouter安装为Vue的插件 Vue.use(VueRouter)
创建路由的实例对象 const router = uev VueRouter()
向外共享路由的实例对象 export default router
在main.js离线引入组件,然后在里面的router实例中声明对应关系,在routes[]数组中完成路由规则的编写
安装和配置了vue-router之后,就可以用router-link替代普通的a链接了
路由重定向:路由强制跳转:在访问地址A的时候强制跳转到地址C,通过redirect属性,写在routes里
{path:’/’, redirect:’/home’}
如果某个组件本来就是通过路由跳转过来的,里面又有其他路由。即在router-view里面再嵌套子级模板内容
子路由规则写在父的children属性里面,子路由不要加/
{
path: '/about',
component: About,
// redirect: '/about/tab1',
children: [
// 默认子路由:如果 children 数组中,某个路由规则的 path 值为空字符串,则这条路由规则,叫做“默认子路由”,和重定向表示的同一个含义,写默认子路由的化要把链接处的地址删掉,变成父链接的地址
{ path: '', component: Tab1 },
{ path: 'tab2', component: Tab2 }
]
}
把Hash地址里面可变的部分定义为参数项,从而提高路由规则的复用性
在vue-router中使用英文的冒号 : 来定义路由的参数项。
传递路由的变化的参数,有两种方式
在Hash地址中,斜线后面的参数项叫路径参数,在路由参数对象$route
中,用this.$route.params
来访问参数的值
?后面的值=value为查询参数,在路由参数对象$route
中用this.$route.query
来访问参数的值
在this.$route中,path是路径部分,fullPath是完整地址,包含查询参数
导航:声明式导航/编程式导航
在浏览器中,通过点击链接实现导航的方式,叫声明式导航,比如,
在浏览器中,通过调用API方法实现导航的方式,叫编程式导航,比如location.href,浏览器原生的方法
this.$router.push(‘hash地址’)//跳转到指定hash地址,并增加一条历史记录
this.$router.replace(‘hash地址’)//跳转到指定hash地址,并替换掉当前的历史记录
this.$router.go(数值n)//
可以在浏览历史中前进和后退 go(-1)表示后退一次,如果后退次数超过上限则原地不动;go(1)就是前进一位,简化用法:$router.back()后退一层 $router.forward()前进一层。this省略会报错
导航守卫可以控制路由的访问权限
全局前置守卫:在跳转前就被触发,全局生效。每次发生路由的导航跳转时,都会触发全局前置首位。因此,在全局前置守卫中,程序员可以对每个路由进行访问权限的控制
创建路由实例对象->调用路由的beforeEach方法即可声明全局前置守卫,每次跳转时都自动触发fn函数
const router=new VueRouter({})->router.beforeEach(fn)
全局前置守卫的三个形参,router.beforeEach((to,from,next)=>{
//to是将要访问的路由对象
//from时将要离开的路由的信息对象
//next是一个函数,调用next()表示放行,允许这次路由导航,不调用任何路由都不能访问
})
next函数的三种调用方式