前端--vue篇

vue

vue-srr

SSR是Server Side Render
为什么要使用服务端渲染

一是更好的SEO(seo就是一个中文的缩写,搜索引擎优化),二是更快的渲染速度。

由于是服务端进行渲染,浏览器只需要渲染出服务端返回的html文件即可,减少了操作dom的时间,这在运行缓慢或者网络不好的设备上,会比较明显。
但是我认为这并不算是值得我们去使用服务端渲染的地方。更好的SEO,才是目前需要使用ssr的真正目的。

computed和watched区别

1.computed依赖于属性值的变化,数据才会更新,而watched是监听数据值的变化
2.computed没有异步,watch有异步
3.computed是有return的,他是可以传出来一个值的,watch没有
4.computed有缓存,当属性值没有变化时就用缓存值;watch只要数据有变化就调用

elementui自定义

vue的生命周期

创建前后
BeforeCreate 没有el,也没有data
created 有data,没有el
挂载前后
BeforeMount 有
mounted
更新前后
BeforeUpdate
update
销毁前后
beforeDestoryed
Destoryed
第一个生命周期函数:beforeCreat,当执行beforeCreat生命周期函数时,vue实例还没有被完全创建出来,此时data,methods等内部没有初始化。
第二个生命周期函数:created,执行这个函数的时候,vue实例已经初始化了,可以在这里调用数据,不过还没渲染到页面上。 在当前函数中我们可以访问到data中的属性,此时,会将data中的属性和methods的方法添加到vue的实例身上,同时会将data中所有的属性添加一个getter/setter方法。这里可以进行前后端上数据交互(ajax请求的时候) 需要在当前生命周期中使用
第三个生命周期函数:beforeMount,这时,vue已经将模板字符串编译成内存虚拟DOM,模板已经编译完成,已经完成渲染树,还没有渲染到页面上。
第四个:mounted,创建阶段完成,页面渲染完毕,进入运行阶段。此时我们可以通过 r e f s 来 访 问 到 真 实 的 D O M 结 构 。 r e f 类 似 与 i d 一 样 值 必 须 是 唯 一 的 , 访 问 的 时 候 我 们 可 以 使 用 t h i s . refs来访问到真实的DOM结构。ref类似与id一样 值必须是唯一的,访问的时候我们可以使用this. refs访DOMrefid访使this.refs.属性,可以进行用户交互操作方法
4.DOM渲染后阶段
当数据发生变化,比如触发了点击事件改动数据
beforeUpdate:内存中的数据已经改变,页面上的还没更新
updated:页面上数据和内存中的一致
5.离开阶段
离开页面销毁、解绑事件,例如:定时器等
beforeDestroy:出发这个函数时,还没开始销毁,此时刚刚脱离运行阶段。data,methods,指令之类的都在正常运行。在这个生命周期函数中我们可以将绑定的事件进行移除
destroyed:组件销毁完毕,data,methods,指令之类的不可用。

父子组件的vue生命周期

他在创建阶段和更新和销毁阶段都是遵循父亲—》子—》父,这里面第一个父都是要到最后了终止,就比如
创建阶段:
父:BeforeCreate—>Create——>Beforeamount
子:BeforeCreate—>Create---->BeforeAmount---->Amount
父:Amout
更新阶段:
父:BeforeUpdate—》
子:BeforeUpdate—>update
父:update
销毁阶段:
父:BeforeDestroy
子:BeforeDestroy---->Destroyed
父:Destroyed

vue中的nextTick的作用

nextTick的作用和使用场景
vue中的nextTick主要用于处理数据动态变化后,DOM还未及时更新的问题,用nextTick就可以获取数据更新后最新DOM的变化

vue当中v-if和v-show

V-if和v-show都是vue当中将元素隐藏的指令,
其中v-if是把元素直接在dom树当中删除
V-show是在元素样式当中加入display:none,元素从渲染树当中删除

vue当中的v-on v-bind v-html,v-model

v-on:动态绑定事件 比如说v-on:click
v-bind:动态绑定属性 像input的value
v-model:数据双向绑定

Proxy和Object.defineProperty的区别

Proxy可以监听数组的变化,但是Object.defineProperty不能监听数组,如果想要监听数组需要将数据的几个方法进行重写并且重新绑定this

Proxy

keep-alive

他是一个保存组件状态的vue的一个组件,它能够将组件进行缓存,会新增两个钩子函数activated和deactivated

vue的路由

vue的原理

vueRouter是前端路由,在无需刷新页面的情况下更新视图。
vueRouter有两种模式:一种是Hash模式,一种是History模式。
分别就是在HTML5History,HashHistory两个类中实现的。

hash模式和history模式

他们的不同点是什么

1.原理不同。

hash模式的实现原理是通过监听hashChange事件来实现的。history模式是通过调用 history.pushState方法(或者replaceState) 并且 监听popstate事件来实现的。history.pushState会追加历史记录,并更换地址栏地址信息,但是页面不会刷新,需要手动调用地址变化之后的处理函数,并在处理函数内部决定跳转逻辑;监听popstate事件是为了响应浏览器的前进后退功能。
hash模式就是加#,是页面里的锚。切换页面只是进行锚的修改,切换显示的div而已,通过onhashchange来监听hash的改变,没有发生页面跳转行为。history是浏览器的API,同样保存了切换状态,使用此模式的history.pushState只会向浏览器添加一条记录,页面内容不会发生任何改变。页面内容之所以能改变,和上面的切换div一样,将对应的div操作与pushState操作配套起来。举个最直观的例子,我们现在F12并在控制台输入一下代码

history.pushState({title: 'b'}, 'bbb', 'bbbb')

会立刻发现导航栏的地址改变了,但是当前页面内容不变。如果此时再刷新浏览器的话,会发现404,知乎服务器并不能响应该地址。
3.history模式特点
history模式开发的SPA项目,需要服务器端做额外的配置,否则会出现刷新白屏(链接分享失效)。原因是页面刷新时,浏览器会向服务器真的发出对这个地址的请求,而这个文件资源又不存在,所以就报404。处理方式就由后端做一个保底映射:所有的请求全部拦截到index.html上。

2.请求不同

hash跳转路由是不会发起请求的
history是会发起请求的

路由传值

1.显示传值

this.$router.push({
		path:"这里是要跳转的路由",
		query:a
})
跳转组件接受值
this.$route.query.a

2.隐式传值

 this.$router.push({
		name:"这里是要跳转的路由",
		param:a
})
跳转组件接受值
this.$route.param.a

路由导航守卫

3.1 全局路由导航

beforeEach 导航守卫
1.to是将要访问的路由的信息对象
2.from是将要离开路由的信息对象
3.next是一个函数,调用next() 表示放行,允许这次路由通行
第一种是全局守卫

beforeEach 路由进入之前

afterEach 路由进入之后

第二种 组件内守卫

beforeRouteEnter 路由进入之前

beforeRouteUpdate 路由更新之前

beforeRouteLeave 路由离开之前

第三种 独享守卫

beforeEnter 路由进入之前

动态路由

路由嵌套

当有一些组件的内部只是发生小的变化的时候,

const routes = [
  {
    path: '/user/:id',
    component: User,
    children: [
      {
        // 当 /user/:id/profile 匹配成功
        // UserProfile 将被渲染到 User 的 <router-view> 内部
        path: 'profile',
        component: UserProfile,
      },
      {
        // 当 /user/:id/posts 匹配成功
        // UserPosts 将被渲染到 User 的 <router-view> 内部
        path: 'posts',
        component: UserPosts,
      },
    ],
  },
]

注意,以 / 开头的嵌套路径将被视为根路径。这允许你利用组件嵌套,而不必使用嵌套的 URL

为什么vue中的 style 会有scoped

1.scope原理
加了scope起到样式隔离作用,会在当前组件加上标识,data-v-xxx
利用css属性选择器,**div【data-v-xxx】**进行了选择

vue首页白屏问题

这里里面很重要
https://www.cnblogs.com/yyshow/p/16630297.html

MVVM的理解

现在来看主流的框架都是MVVM模式的,比如我使用的vue.MVVM就是MODEL层也就是数据层,V就是VIEW视图层,中间通过viewmodel层就是进行一个数据双向绑定的过程,而他主要是由Object.defineProperty()中的get和set的方法0进行数据劫持,也就是dom监听和数据绑定的功能,进而实现了数据驱动视图。并且无需人为干涉,
因此开发者只需关注业务逻辑,不需要手动操作DOM, 不需要关注数据状态的同步问题,
复杂的数据状态维护完全由 MVVM 来统一管理。

Vue项目优化

1.路由懒加载

// 1、Vue异步组件技术:
{
  path: '/home',
  name: 'Home',
  component: resolve => require(['../views/home.vue'], resolve)
}

// 2、es6提案的import()
{
  path: '/',
  name: 'home',
  component: () => import('../views/home.vue')
}

// 3、webpack提供的require.ensure()
{
  path: '/home',
  name: 'Home',
  component: r => require.ensure([],() =>  r(require('../views/home.vue')), 'home')
}

2.图片懒加载
3.组件懒加载
3.图片在打包的时候对图片进行了压缩
4.组件的封装

Vuex

1.states:vuex的基本属性,用来储存变量
2.mutation:vuex唯一改变state里面数据的方法,类似于method
3.action:vuex里面可以改变数据结构的方法,可以支持异步,需要使用dispatch
4.getter:vuex当中的计算属性

Vuex用法的例子


Vue组件封装需要注意什么

组件是什么?

答:组件是包含数据、逻辑功能、展现样式的代码片段
可读性。首先组件命名要语义化,大家看到组件就一目了然,知道该组件的功能是啥;其次我们组件要有一个清晰明了的注释,演示组件用例,属性、参数、方法说明,让大家几乎不用动脑就可以完美使用。
逻辑功能合理性。封装公共组件要设计好组件功能,看哪些功能需要在组件内完成,哪些功能需要暴露给父组件。我们一般的设计原则是,能在组件内完成的功能,尽量不要暴露给父组件处理。
数据设计的合理性。设计原则:组件自身除了必要的数据,一般不携带大量私有数据,尽量由父组件输入,处理完后根据业务场景决定是否需要输出。
样式的一致性。首先组件样式风格要和网站整理风格一致;其次组件在不同地方,不同空间展示样式尽量保持一致,不要变形。
可扩展性。我们封装公共组件基本可以满足我们百分之80到90的业务场景,但是一些个性化话的场景,需要组件的大部分功能,但是又有新的需求,这时候再开发一个新的组件没有必要,那么我们就要在原有组件的基础上加功能。这是时候我们就要用到插槽slot来做好预留,来增强组件的扩展

mixin

Mixin对于封装一小段想要复用的代码来讲是有用的,Mixin的优点是不需要传递状态,但缺点也显而易见可能会被滥用。

slot(插槽)

slot主要就是为组件留出可以插入的位置一个位置
是“占坑”,在组件模板中占好了位置,当使用该组件标签时候,组件标签里面的内容就会自动填坑(替换组件模板中位置),当插槽也就是坑<slot name= ” mySlot ” >有命名时,组件标签中使用属性slot= ” mySlot ” 的元素就会替换该对应位置内容;

我会以插槽常用的有几种、插槽的作用、分别如何使用、使用场景
插槽分为匿名插槽/具名插槽/作用域插槽
插槽的作用是我们可以给组件预留空间自己定义内容

匿名插槽: 不写name属性时的使用方法就叫匿名插槽,其时所谓的匿名插槽是有名字的 他的名字是default

具名插槽: 可以通过v-slot:插槽的名字 , 给指定的插槽定义内容 ,v-slot:名字可以简写为 #名字

作用域插槽: 插槽也可以通过自定义属性预备插槽需要使用的数据 而这种插槽就叫做作用域插槽,

使用场景比如在我写后台管理系统的时候,用到了表格,表格有操作列,
里面需要使用插槽自定义列写按钮,还有我们的组件中在子组件定义一个具名插槽,
在父组件就可以传入不同的数据,利用name属性,显示不同的内容

子组件
  <!-- // 默认插槽 可以省略name default-->
  <slot></slot>

  <!-- //具名插槽 要指定name属性-->
  <slot name="h"></slot>

  <!-- // 作用域插槽  要指定name和自定义属性,自定义属性绑定数据-->
  <slot name="z" :say1="say1" :say2="say2"></slot>

</div>

父组件

  <!-- 默认插槽/我其实也有名字是#default -->
  <template>
    <div>
      我是盖伦-----默认插槽/我其实也有名字是#default,只是默认插槽可以在template不写名字
    </div>
  </template>

  <!-- 具名插槽 在template v-solt:xx名字 -->
  <template v-slot:h>
    <div>
      我是皇朝
    </div>
  </template>

  <!-- 具名插槽 v-slot:h 简写#h -->
  <template #z>
    <div>
      我是赵云
    </div>
  </template>

  <!-- 作用域 插槽可以写数据 -->
  <!-- 结构子组件数据出来 say1, say2-->
  <template #z="{say1, say2}">
    <div>{{say1}}</div>
    <div>{{say2}}</div>
  </template>

</com>

作用域插槽

组件间通信

父传子

子组件

props:{
    // 字符串形式
 name:String // 接收的类型参数
    // 对象形式
    age:{  
        type:Number, // 接收的类型为数值
        defaule:18,  // 默认值为18
       require:true // age属性必须传递
    }
}

Father.vue组件

<Children name:"jack" age=18 />

子传父

子组件

selectSeason() {
 
      this.showValue = 5
      this.$emit('toFind', this.showValue)
    },

父组件

在template中使用,先获取到自定义的传输名字,给他赋值到一个自定义的方法上面去

<template>
<Quarter @toFind="getData"></Quarter>
</template>
下面就获取到值了
import Quarter from "./Quarter";
components: {
    Quarter
  },
methods:{

getData(data){
      console.log(data)
    },

兄弟组件

1.EventBus
class Bus {
  constructor() {
    this.callbacks = {};   // 存放事件的名字
  }
  $on(name, fn) {//注册事件
    this.callbacks[name] = this.callbacks[name] || [];
    this.callbacks[name].push(fn);
  }
  $emit(name, args) {触发事件
    if (this.callbacks[name]) {
      this.callbacks[name].forEach((cb) => cb(args));
    }
  }
}

// main.js
Vue.prototype.$bus = new Bus() // 将$bus挂载到vue实例的原型上
// 另一种方式
Vue.prototype.$bus = new Vue() // Vue已经实现了Bus的功能

全局引用

2.Vuex

mutations

3.parent 和 root
//兄弟组件
this.$parent.on('add',this.add)
//另一个兄弟组件
this.$parent.emit('add')

爷传孙

 <div id="app">
    我是爷组件
    <fu
      :msg1="msg1"
      :msg2="msg2"
      :msg3="msg3"
      :msg4="msg4"
    ></fu>
  </div>
</template>

<script>
import fu from "./views/fu.vue";
export default {
  components: {
    fu,
  },

2.中间需要父组件进行一个
3.

<template>
  <div class="sunClass">
    我是孙子组件
    <h2>接收爷组件数据:-->{{ msg2 }}</h2>
    <h2>接收爷组件数据:-->{{ msg3 }}</h2>
    <h2>接收爷组件数据:-->{{ msg4 }}</h2>
  </div>
</template>

<script>
export default {
  name: 'Sun',
  // $attrs一般搭配interitAttrs 一块使用
  inheritAttrs: false, // 默认会继承在html标签上传递过来的数据,类似href属性的继承
  /*
    孙子组件通过props,就能接收到父组件传递过来的$attrs了,就能拿到里面的数据了,也就是:
    爷传父、父传子。即:祖孙之间的数据传递。
  */ 
  props: {
    msg2: {
      type: String,
      default: '',
    },
    msg3: {
      type: Array,
      default: () => {
        return [];
      },
    },
    msg4: {
      type: Object,
      default: () => {
        return {};
      },
    },
  }
};

孙传爷

1.现在父组件当中加入v-on=“$listeners”

<sun v-bind="$attrs" v-on="$listeners"></sun>
  1. 使用fromSun进行传值
methods: {
    fromSun(payload) {
      console.log("孙传祖", payload);
      this.fromSunData = payload;
    },
  1. 绑定在父组件中
 <fu :msg1="msg1" :msg2="msg2" :msg3="msg3" :msg4="msg4" 
        @fromSun="fromSun">
    </fu>

4.子组件中加载

methods: {
    sendToZu() {
      // 孙组件能够触发爷组件的fromSun方法的原因还是因为父组件中有一个$listeners作为中间人,去转发这个事件的触发
      this.$emit("fromSun", this.data);
    },
  },

组件间的v-model传值

监听原生组件的事件, 当获取到原生组件的值后,再通过调用 e m i t ( ′ i n p u t ′ , d a t a ) 方 法 去 触 发 i n p u t 事 件 即 : 子 组 件 向 父 组 件 传 值 通 过 t h i s . emit('input' ,data) 方法去触发 input事件 即:子组件向父组件传值通过this. emit(input,data)inputthis.emit(‘input’,data),父组件通过@input来接收。
父组件

1. 父组件 home
<template><home-child v-model="vModelData"></home-child>
</template>

<script>
import HomeChild from './child/HomeChild.vue'
export default {name: 'Home',components: {HomeChild},data () {return {vModelData: 'hello v-model'}}
}
</script> 

子组件

2. 子组件homeChild
<template><div class="box"><span>{{ value }}</span><button @click="testVModel">测试v-model</button></div>
</template>

<script>
export default {name: 'HomeChild',props: {value: {type: String,default: ''}},methods: {testVModel () {this.$emit('input', '我是子组件')}}
}
</script> 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值