## Vue的数据驱动原理?数据更新原理?响应式原理?
因为每个实例可以维护一份被返回对象的独立拷贝
vue提供了一种将父组件内容和子组件的模板整合的方法,内容分发,通过slot插槽实现.
分为具名插槽和匿名插槽
在关系链中可以用this.$children[X].xxx=" ” 改变子组件的xxx数据
用ref链实现修改
<son ref="a"/>// 在父组件的触发方法中写this.$refs.a.msg= " "
1.需要创建一个公共的vue实例对象 let bus = new Vue()
2.弟弟组件准备一个方法,如
hit(){
this.isShow=true;//用于一个标签显示隐藏
}
3.弟组件
mounted(){
bus.$on("hit",this.hit)//绑定一个事件,等待一个机会执行
}
4.哥组件触发的方法
bus.$emit("hit")
只渲染元素和组件一次,随后的重新渲染,元素/组件及其子节点将被视为静态资源跳过,这属于优化更新性能。
<transition name="abc"></transition>
//name属性写后改为abc-的样式名,默认v-
.abc-enter-alive
.abc-leave-active
多元素同时增加动画
<transition-group></transition-group>
//子元素要加key属性
多元素的过渡模式
多个元素过渡
transition里只能是一个元素,但增加v-if/v-else
当相同标签名切换时,由于虚拟DOM机制,会直接让动画消失,所以给transition组件中多个设置key是一个更好地实践
vue生命周期分三个阶段
初始化:beforeCreate/created/beforeMount/mounted
运行中:beforeUpdate updated
销毁:beforeDestroy destroyed
beforeCreate(){
//不能拿到this
}
created(){
//此钩子函数数据已加载完毕,但DOM未生成。
// 通常在这里面初始化一些事件与ajax请求
}
当动态组件被keep-alive包裹时,created只会执行一次,并且组件一直缓存在内存中,没有销毁,
问题:
例如我们在created中绑定一个定时器时,会造成定时器无法关闭。
解决:
动态组件给我们提供了activated和deactivated钩子函数
默认缓存所有组件
可以用include="组件名,组件名"指明有条件缓存
可以使用正则 :include=“/a|b/”
可以使用数组 :include=“[‘a’,‘b’]”
exclude是除了谁都缓存
目的:操作底层DOM元素,例如让初始化时输入框获取焦点
//全局的
<input v-focus/>
Vue.directive("focus",{
//当被绑定的元素插入父节点时,会触发inserted
inserted(el){
el.focus()
}
})
//局部的
new Vue({
el:"#box",
directives:{
focus:{
inserted(el){
el.focus()
}
}
}
})
页面加载时:bind inserted
更新组件: update componentUpdate
卸载组件: unbind
重新加载组件: bind inserted
bind:指令第一次绑定到元素时调用;
inserted:被绑定元素插入父节点时调用
update:所在组件的vnode更新时调用,但可能发生在其子vnode更新之前
componentUpdated:指令所在组件的vnode及其子vnode全部更新后调用
unbind: 指令与元素解绑是调用
el:指令绑定的元素,可以用来直接操作DOM
binding:一个对象,包含以下property。
<p v-color="'color'"></p>
//必须加' ' 否则变量应放在data里声明
Vue.directive("color",{
bind(el,binding){
el.style.background=binding.value
}
})
//有时候,可能在bind和update里触发相同行为可简写
Vue.directive("color",function(el,binding){
el.style.background=binding.value
})
用JavaScript驱动时,有以下缺点:
以vue-loader的装载器解析以.vue后缀名的文件
以 vue create . 安装vue全部脚手架
//创建vue.config.js文件
module . exports={
devserve:{
overlay:{
warnings:false,
errors:false
}
},
lintOnSave:false
//关闭eslint检查
}
//关闭某个eslint
找到.eslintrc.js文件中rules
error的最后一个单词 ' ' 引起来放到rules里,
然后 :'off'
在style中scoped属性指明仅当前组件可用
原理:会给标签添加额外的属性,内部会根据属性选择器来添加样式。
另:style中lang属性可以具体的CSS预处理语言(sass/less)
scoped的穿透问题
设置scoped的目的是为了限制样式只能影响当前的组件
若希望也可以影响到子组件或第三方组件时,需要使用scoped穿透。
div /deep/ p{
}
应用:组件里引用第三方插件时,后续想要在这个组件中修改第三方插件的样式,只能通过/deep/.abc实现scoped穿透修改。
//父组件
import Son from "子组件路径"
//或 const Son = require("子组件路径")
1.引入Son组件
2.声明组件并注册
export default{
components:{
One
}
}
3.传数据 :msg="父组件data的要穿的数据"
//子组件
export default{
props:["msg"]
}
//父组件
1.定义空数据
2.定义改变数据的方法
methods:{
changeData(data){
this.adata= data
}
}
<Son @change="changeData"/>
//子组件
created(){
this.$emit("change",参数)
}
//初始化时触发父组件方法
//通过axios请求本地资源
1.引入axios
import axios from "axios"
2.export default{
axios.get("/data.json").then(res=>{
console.log(res)
})
}
//注:data.json必须放在public文件里
//访问时须 / 根目录获取
请求在线资源
//请求在线资源要考虑跨域问题
//在控制台response Headers下Access-Control-Allow-Origin代表后台是否写跨域。
//卖座后台解决了跨域问题但在requl.Header下有个请求头 X-Client-Info和X-Host
//请求时需携带请求头
//get(" ",{
// headers:{
// ' ':' ',
// ' ':' '
//}
//})
前端写跨域时用proxy 代理服务器
在vue.config.js下的devserve
proxy:{
'/api':{
target:'http://m.maizuo.com',
changeOrigin:true,
pathRewrite:{
'^/api':''
}
}
}
网页不是直接放入浏览器中的,而是先放在viewport中,然后viewport再等比例缩放到浏览器宽度,放入浏览器,viewport在缩放过程中,内容也缩小了。
< meta name="viewport" content="width=device-width
,initial-scale=1.0,maximum-scale=1.0,
user-scalable=no">
//width=device-width宽度等于当前设备宽度
//initial-scale=1.0初始的缩放比
//maximum-scale=1.0允许用户缩放的最大比例
//minimum-scale=1.0允许用户缩放的最小比例
//user-scalable用户是否可以手动缩放
rem 指相对于根元素的字体大小的单位
VW 设备宽度的1%
布局
xs 超小屏幕 sm 小屏幕 md中等屏幕lg大屏幕
dpr = 设备像素比 / CSS像素比
iPhone6 750px dpr=2
css=750 / 2 =375
100vw=375px
100px=26.67vw
iphone5 640px dpr = 2
100px = 31.25vw
1080px dpr=3
100px = 27.78vm
传统多页MPA应用,底部通过a标签实现页面的跳转,但网速卡顿时会产生打开速度慢,并且伴随留白问题,用户体验较差。
引入spa single page application 单页面应用
原理:根据rul地址栏变化,来实现对应路由的组件的切换,整个网页没有刷新。只是组件间的卸载与装载,只有一个页面。
安装插件 yarn add vue-router
通过全局方法 Vue.use()使用插件,他需要在new Vue()启动前应用。
Vue.use()背后原理
通过调用插件里的install
vue-router提供了router-view,用来显示路由视图组件
<router-view></router-view>
import Films from '@/views/Films'
//@指向SRC目录
routes =[
{
path:'/film',
component:Films
}
]
import Films from '@/views/Films'
//@指向SRC目录
//引入二级路由
import ComingSoon ....,,
routes =[
{
path:'/film',
component:Films,
children:[
{
path:'/film/comingsoon'
component:ComingSoon
}
]
}
]
//在上面路由配置中加
name : 'cn',
<router-link :to="{name:'cn'}"></router-link>
router-link标签tag = “li” 指明渲染转化的页面标签
to = "/films"跳转地址
active-class="active"带的class名
replace 阻止浏览器返回按键(不留下浏览记录)
<p @click="toMine">点击进入我的页面</p>
export default{
methods:{
toMine(){
this.$router.push("/film")
}
}
}
或
<router-link :to="{path:'/film'}">进入我的</router-link>
//有时需要我们在路由跳转时带上参数
:to="{path:'/film/100'}"
在配置路由时
{
path:"/person/:id"
props:true
}
接收:
props:["id"]
或
this.$route.params.id
:to = "{path:'/film/100?title=我是二号'}"
this.$route.query.title接收
即需要的时候加载,随用随载
为什么需要懒加载?
向vue等这种单页面应用,若未用懒加载,运用webpack打包后的文件会异常大,造成进入首页时,需要加载的内容过多,时间过长,会出现长时间白屏,应用懒加载会分担首页所承担的加载压力,减少首页加载用时。
Es6写法
component:() => import('路径')
ES5写法
component:resolve => require(['路径'],resolve)
//命名webpack包的方法
component:()=>import(/*webpack(hunkName:'film')*/'路径')
vue中model模式
hash模式原理:调用window.onhashchange方法hash值切换
history模式原理:本质使用H5的history.pushstate方法更改URL
当路由跳转前或跳转后,进入,离开某个路由,需要做某些操作,就可以使用某些钩子来监听。
全局路由守卫
beforeEach | afterEach
前置路由beforeEach()路由跳转前执行
router.beforeEach((to,from,next)=>{
if(from.path === '/person'){
console.log("从哪里来")
}
next();
//代表放行 (必须写)
})
//to: 将要进入的路由对象,
// from:当前导航即将离开的路由
后置路由 跳转之后
router.after((to,from)=>{
if(to.path==='/person'){
console.log("进入person")
}
})
局部路由 写在路由配置里,放在person路由路径下
beforeEnter(to,from,next){
console.log("进入用户前打印")
next()
}
路由组件钩子
写在person.vue的export default里
beforeRouteEnter(to,from,next){
}
渲染组件的对应路由被confirm前调用,不能获取组件实例this,因为在路由守卫前执行组件未被创建
未完待续,将在本篇文章末尾处持续更新