VUE面试题

生命周期

// 创建之前,在beforeCreate生命周期执行的时候,data和methods中的数据都还没有初始化,不能访问data数据
1. beforeCreate(){
console.log('beforeCreate',this.msg);
},
//创建之后,data和methods中的数据已经初始化,此时可以访问data数据
// 一般在这个函数中发起ajax请求
2. created(){
console.log('created',this.msg);
},
// 挂载之前,表示模板已经在内存中编译完成,但尚未把模板渲染到页面中。
// 此时还没有渲染用数据生成的新dom
3. beforeMount(){
console.log('beforeMount',this.el); }, // 挂载完毕 ,表示内存中的模板,已经真实的挂载到了页面中,用户已经可以看到渲染好的页面了 // 此时可以访问dom 4. mounted(){ console.log('mounted',this.el);
},
// 更新之前,当且仅当data被修改时才触发这个生命周期函数,但此时仅仅是数据被修改,页面还未更新。
5. beforeUpdate(){
console.log('beforeUpdate',this.msg);
console.log('beforeUpdate',this.el.innerHTML); }, // 更新之后, 会根据新数据生成最新的内存DOM树,重新渲染到真实的页面中去, // 此时的data数据和页面已完成同步 6. updated(){ console.log('updated',this.el.innerHTML);
},
// 销毁之前,当执行beforeDestory钩子函数的时候,Vue实例就已经从运行阶段,进入到了销毁阶段。
// 当执行beforeDestory的时候,实例身上所有的data和所有的methods,以及过滤器、指令...都处于可用状态,此时还没有真正执行销毁过程。
7. beforeDestroy(){
console.log('beforeDestroy');
},
// 销毁之后,当执行到destoryed函数的时候,组件已经被全部销毁了,data与methods均不可用。
// 更改data数据,页面不会更新
//应用: 清除定时器
8. destroyed(){
console.log('destroyed');
}

当使用了<keep-alive>缓存组件时,会增加两个生命周期钩子

Vue全家桶

  vue的全家桶:   
        vue.js   
        vue-router.js  
        vue-cli (脚手架,快速搭建vue项目)
        axios  
        vuex.js

v-if与v-show的区别

v-if的显示和隐藏 是dom的创建与销毁
v-show的显示和隐藏是 基于display-none 和 display-block 无论是显示或是隐藏都会生成dom

vue指令

v-html 元素的innerHTML
v-text 元素的InnerText 只能用在双标签中
v-model 双向数据流绑定 主要作用于表单的 value 属性
v-bind 给元素绑定动态属性
v-on 处理自定义原生事件
v-if
v-else
v-else-if
v-show
v-once 只渲染一次 ,数据改变,视图更新,但v-once对应的元素不会再更新
v-slot 插槽

vue 脚手架中的data为什么必须是个函数

避免组件中的数据互相影响
组件中的data写成一个函数,数据以函数返回值形式定义,这样每复用一次组件,就会返回一份新的data,类似于给每个组件实例创建一个私有的数据空间,让各个组件实例维护各自的数据。而单纯的写成对象形式,就使得所有组件实例共用了一份data,就会造成一个变了全都会变的结果。

vue中计算属性computed和方法methods和侦听器watch的区别

  1. 计算属性和方法都是函数,计算属性一定有返回值,它通过对数据进行处理,返回一个结果

     2. 在模板中调用时,计算属性不加(),而methods必须需要加()
     
     3. 计算属性和方法最主要的区别是计算属性有缓存功能。
    
         方法被调用时每次都要重复执行函数
    
         计算属性初次调用时执行函数,然后会缓存结果。当再次被调用时,如果依赖的响应式数据没有发生改变,则直接返回之前缓存的结果 。
    
         如果依赖发生了改变,则会再次执行函数并缓存结果 
    
     4. 不支持异步,当computed内有异步操作时无效,无法监听数据的变化
    

watch:

1. 侦听响应式数据的变化,数据变化时,执行相应的业务逻辑,可以有返回值,也可以没有

2. 侦听器默认在页面初始化时不执行,只有侦听数据发生变化才会执行。添加上immediate可初始化时就执行

3. 添加上immediate可初始化时就执行

Vue中如何获取原生dom

  1. 在元素标签上添加ref属性
  2. 通过this.$refs.属性名来获取dom
  3. 应用场景: 楼层导航中,要获取每个楼层距离页面顶端的偏移值
    注意:如果是异步请求的数据渲染的dom 需要使用 this.$nextTick()回调来获取更新后的dom

<ul ref="ulEl">
<li v-for="(item,index) in list" ref="liEl">{{item}}</li>
</ul>
<p ref="pEl">这是一个段落</p>

Vue中的 this.$nextTick()

一般在请求数据后,需要获取dom的时候使用。

在下次 DOM 更新循环结束之后执行延迟回调。在修改数据之后立即使用这个方法,获取更新后的 DOM。

Vue中 this.$router 与this.$route的区别

    在一个vue组件中,都可以访问到这两个对象,它俩的区别 
    this.$route是路由记录对象,只读,存储了与路由相关的信息

    this.$router是路由对象,用来进行路由跳转

什么是SPA 单页面应用

单页Web应用(single page web application,SPA): SPA 是一种特殊的 Web 应用,是加载单个 HTML 页面并在用户与应用程序交互时动态更新该页面的。它将所有的活动局限于一个 Web 页面中,仅在该 Web 页面初始化时加载相应的 HTML 、 JavaScript 、 CSS 。一旦页面加载完成, SPA 不会因为用户的操作而进行页面的重新加载或跳转,而是利用 JavaScript 动态的变换 HTML(采用的是 div 切换显示和隐藏),从而实现UI与用户的交互。在 SPA 应用中,应用加载之后就不会再有整页刷新。相反,展示逻辑预先加载,并有赖于内容Region(区域)中的视图切换来展示内容。

实现数组,对象更新检测的方法

push()
pop()
shift()
unshift()
splice()
sort()
reverse()

// ====================================数组更新检测

// 三个参数: 数组,索引,新值
Vue.set(this.list,3,5)  //可以触发视图更新
this.$set(this.list,3,5)  //可以触发视图更新

// =====================================对象的更新检测

// 三个参数:对象,属性,新值
Vue.set(this.person,"sex","男") //可以触发视图更新
this.$set(this.list,3,5) //可以触发视图更新

for循环中的key值的作用

需要使用key来给每个节点做一个唯一标识,Diff算法就可以正确的识别此节点,找到正确的位置区插入新的节点。
所以一句话,**key的作用主要是为了高效的更新虚拟DOM**。

另外vue中在使用相同标签名元素的过渡切换时,也会使用到key属性,其目的也是为了让vue可以区分它们,否则vue只会替换其内部属性而不会触发过渡效果。

为什么v-for和v-if不能在同一标签(元素)上

v-for比v-if优先,即每一次都需要遍历整个数组,影响速度。

    <div
        v-for="(fileMsg,index) in fileMsgList"
        :key="fileMsg.id"
        v-if="index < 2"
        >
        <sys-file-layout :fileMsg="fileMsg"></sys-file-layout>
    </div>

以上代码,如果有100条数据,虽然显示两条,但需要遍历100次,因为v-for优先

    更好的解决方案: 是用computed先获取符合条件的数据,再进行遍历

事件修饰符

事件修饰符: @click.修饰符
1. @click.stop 阻止冒泡
2. @click.prevent 阻止浏览器默认行为
3. @click.once 只执行一次
4. @keyup.键名 (13,enter都是指回车键, 38: 上箭头)
5. @click.self 当事件发生在该元素本身而不是子元素的时候会触发;
6. @click.capture 在事件捕获阶段触发事件处理程序
7.@keyup.native 使非原生标签也可以绑定事件

token的工作流程

    1.用户填写登录信息,发起请求,服务端收到请求,去验证用户名与密码
    2.验证成功后,服务端会签发一个 Token,再把这个 Token 发送给客户端
    3.客户端收到 Token 以后可以把它存储起来,比如放在 Cookie 里或者 Local Storage 里
    4.客户端每次向服务端请求资源的时候需要带着服务端签发的 Token
    5.服务端收到请求,然后去验证客户端请求里面带着的 Token,如果验证成功,就向客户端返回请求的数据

什么是Vuex

如果应用比较简单,就不需要使用Vuex,直接使用父子组件传值及它传值方式即可,使用Vuex就要额外的引入vuex的框架,可能是繁琐冗余的

如果需要构建一个中大型单页应用,就可以使用vuex更好地在组件外部管理状态

Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。

它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。

Vuex的工作流程

一、在项目创建store文件夹,及index.js
定义相关的vuex的state, getters actions mutations

二、在入口文件main.js中引入store,并在根实例注册

三、在任一组件中,通过this.$store.state就可以访问到共享数据

四、当通过组件要修改store中的数据时,

1. 如果该操作是同步的,可以用this.$store.commit()来触发mutations, 只有mutations才可以直接更改state共享数据

2. mutations中只能有同步操作,不能有异步操作

3. 如果修改数据的操作是异步的,通过this.$store.dispatch()触发actions, actions中可以发起异步请求,获取数据后,再调用 commit触发mutations,通过mutations修改共享数据

Vuex的五个属性

State

储存公共数据

Action

类似于mutation 不同在于
Action 提交的是mutation,而不是直接变更状态,(action不能直接更改state数据)
Action 可以包含任意异步操作

总结一下:
  mutation不能有异步操作,而action可以有异步操作
  mutation可以直接更改数据,而action只能通过提交mutation,通过mutation的方法来改变数据
  实际通过组件改变数据时,如果没有异步操作,可以直接提交(commit)mutation,如果有异步操作,必须派发(dispatch)action,通过action提交(commit)mutation来更改数据 

Mustion

更改Vuex中store中的状态唯一的办法是提交mutation
mutation的方法中有两个参数,一个是state,第二个是参数
mutations:{
方法名(state,参数){
state.属性=参数
}
}
在组件中提交mutations的方法:this.$store.commit('方法名',参数)
state中的数据时响应式的,数据改变,相关视图会重新渲染

getters

就像计算属性一样,getter的返回值会根据它的依赖被缓存起来,且只有当它的依赖值发生了改变才会被重新计算

Modelu 模块


Vuex中的辅助函数

mapState

mapGetters

mapActions

mapMutations

Vue中如何自定义组件

一、普通组件

  1. 新建一个单个文件组件 *.vue , 内部: <template> <script> <style>, 导出
  2. 在父组件中引入组件
  3. 在components配置项中进行注册
  4. 在模板直接使用

二、路由组件

  1. 新建一个单个文件组件 *.vue , 内部: <template> <script> <style>, 导出
  2. 在路由文件中引入组件
  3. 在路由配置中,设置path和对应的component选项,来配置路由
  4. 在路由切换时,如何匹配到当前组件所对应的路由,则会在<router-view>中渲染该组件

页面跳转的方式

1.声明式导航

<router-link to="/index"></router-link>

2.编程式导航

//在当前路由后添加路由
this.$router.push('/index')
//替换当前路由
this.$router.replace('/index')
//上一页下一页
this.$router.go(-1)
this.$router.go(1)

路由传值

1.直接在路径后写?id=1 此方法类似get请求 参数会直接写在url地址后 使用query接收

<router-link to="/index?id=1"></router-link>
this.$router.push({path:'/index?id=1'})
this.$router.push({path:'/',query:{id:1}})

接收参数

this.$route.query.id

2. 需要在路由表配置传过去的值的键名 此方法类似post请求 使用params接收 页面刷新数据不会丢失

  {path: '/index/:id',  component: Index}
<router-link to="/index/1"></router-link>
 this.$router.push({
        path: `/index/${id}`
      })
this.$router.params.id

3. 使用路由的name属性来确定匹配的路由,通过params来传递参数

  this.$router.push({
          name: 'index',
          params: {
            id: id
          }
        })
  {
     path: '/index',
     name: 'Index',
     component: Index
   }

接收

this.$route.params.id

动态路由的实现

动态路由应用场景 : 样式相同数据不同时 可以使用动态路由实现组件复用 (详情页)

  1. 在路由配置中,设置path选项为"/url/:属性名"
    path: "/detail/:id"

    1. 传递参数: 在url后加/加参数

      <router-link to="/detail/3"></router-link>

    2. 在组件中接收参数的方式:
      this.$route.params.属性名

      如果在切换动态路由组件时,每次路由组件都会销毁,则在created中接收参数,
      比如: 列表进详情

      如果在切换动态路由组件时,每次路由组件被复用,则用watch监听路由的变化,来获取参数
      比如: 美团--> 发现--->三个版块的切换: 推荐 , 丽人, 旅行, 版块切换时,组件复用,只是传参不同

vue中实现角色权限管理

前端的权限管理 实现方案

首先登录验证 成功返回
token --------------------------------存到本地存储
用户权限id --------------------------------存到本地存储
路由表信息 --------------------------------存到vuex(页面刷新 vuex会被重置 )--------所以也需要存到本地存储中

设置请求拦截器 添加请求头 token 和 用户权限id
后端接收到请求 首先验证 token

动态路由法

登陆后 获得到后端返回的uid(用户权限等级),或者路由表的树,然后把相对应的路由表动态添加到公共路由表中,同时在最下边配置全局路由防止用户访问无权限页面

  {
    path: "*",
    redirect: "/login",
  },

路由元信息法

在路由元信息的meta属性中添加 meta: { role: ['admin','user']}
在路由前置守卫中判断逻辑:
1 是否已经登录(有token)
2 indexOf 获取自身的用户名对比要前往的页面的role属性 中是否允许访问(不为-1) 如果允许则放行 不允许则拦截并跳转404

路由元信息+动态路由

(配置路由前置守卫,路由表分两个一个是不需要任何权限的(login),一个是需要权限的)
首先先登录获得token,和后端数据库的user_info (用户名,头像,用户权限(admin))
前端获得数据后 存到本地
此时登录成功跳转新页面时,会被路由前置守卫拦截判断 是否有token 有token的情况下判断是否有user_info,
获取到user_info中的用户权限 并使用数组的过滤方法找出有权限访问的路由的路由信息 生成一个新的数组,
然后动态添加到路由表中(每次跳转都会执行)


Vue中添加动态路由

动态添加路由的API router对象的addRoutes方法,参数必须是一个数组

     // 把下面的路由配置动态添加到路由表中
     let route = [{
        path: '/user',
        component: ()=> import("@/views/user.vue")
     }]
     this.$router.addRoutes(route)
     alert('添加了新路由')

角色管理(权限管理)

  1. 在需要动态添加的路由上添加角色的路由元信息 meta: { role: ['admin','user']}
  2. 在用户登录后,会根据用户账号,来过滤有权限的路由,并把这些路由通过addRoutes方法动态添加到路由表中

嵌套路由

一、在路由配置中,一级路由中添加children选项,来配置嵌套路由

const routes = [
{
path: '/home',
component: ()=> import(路由组件的地址),
children: [
{
path: 'star',
component: Star
}
]

}
]

二、在父组件中,通过<router-link to="/home/star">跳转到该嵌套路由

三、该嵌套路由对应的出口 <router-view>是在它的父级路由组件中定义的

solt

slot就是子组件里给DOM留下的坑,规定父组件写在子组件标签里的内容 在哪里显示
<子组件>DOM</子组件>
slot动态的DOM、props是动态的数据
1.匿名插槽
2.具名插槽
3.作用域插槽

组件之间传值的方法

兄弟组件之间传值的方式

1 vuex
2 子传父 父传子
3 在main.js中定义一个新的vue实例并导出,在子组件1中导入该实例,使用该实例的$emit方法自定义事件并发出数据,在子组件2中监听该自定义事件,并接受该值(案例是用一个回调函数以传参的方式获取)

父子组件之间传值的方式

1 在子组件标签上自定义属性并传值,子组件内部使用props接收
2 回调函数 在父组件定义一个回调函数 this.num=2 并且把num变量和这个回调函数传给子组件,子组件接收后就可以在子组件内部调用父组件函数
3 $parent $children属性
在子组件中 this.$parent.num访问父组件的num变量
在父组件中 this.$children[0].num访问第一个子组件的num变量

4 provide inject

在父组件中定义变量,子组件获取并使用
5 $attrs $listeners 实现父孙组件通信
6 $ref 在子组件上注册ref 之后使用$refs.子组件.属性 来获取属性和方法

MVVM 与 MVC

MVC和MVVM都是程序开发的架构模式

MVC: M,即model,指数据层 V,指view, 即视图层 C, controller,控制器

View层发起数据请求,Controller层接到请求后,接收参数,把命令传向Model层,Model层处理数据后,把数据传回controller,而controller把数据传回客户端,也就是view层

典型代表: nodejs的Egg框架, php的ThinkPHP框架都是使用的MVC模式

MVVM: M: model,数据层 V: view,视图层,即UI , VM (ViewModel)是视图层和数据层的中间层

典型代表: Vue框架

Vue的双向数据绑定就得益于MVVM框架, 视图层改变,底层封装好的VM层会更新数据,而数据改变,VM层会更新视图

双向数据绑定的原理

1.采用数据劫持结合发布者-订阅者模式的方式,通过Object.defineProperty()来劫持各个属性的setter,getter在数据变动时发布信息给订阅者,触发相应的监听回调
2.当把一个普通的javascript对象传给Vue实例来作为它的data选项时,Vue将遍历它的属性,用Object.defineProperty 将它们转为 getter/setter
3.用户看不到getter/setter,但是在内部它们让Vue追踪依赖,在属性被访问和修改时通知变化
4.Vue3中用ES6的proxy对象替换了Object.defineProperty(),因为Object.defineProperty() 只能劫持一个属性,而proxy可以劫持对象的所有属性

路由导航守卫

一、 全局前置守卫

router.beforeEach((to,from,next)=>{})

二、 全局解析守卫

和 router.beforeEach 类似,区别是在导航被确认之前,同时在所有组件内守卫和异步路由组件被解析之后,解析守卫就被调用

router.beforeResolve((to,from,next)=>{})

三、 全局后置钩子

和守卫不同的是,这些钩子不会接受 next 函数也不会改变导航本身:

router.afterEach((to,from)=>{})

四、 路由独享的守卫

在路由配置上直接定义 beforeEnter 守卫

            {
                path: '/foo',
                component: Foo,
                beforeEnter: (to, from, next) => {
                    // ...
                }
            }

五、 组件内的守卫

            const Foo = {
                template: `...`,
                beforeRouteEnter(to, from, next) {
                    // 在渲染该组件的对应路由被 confirm 前调用
                    // 不!能!获取组件实例 `this`
                    // 因为当守卫执行前,组件实例还没被创建
                },
                beforeRouteUpdate(to, from, next) {
                    // 在当前路由改变,但是该组件被复用时调用
                    // 举例来说,对于一个带有动态参数的路径 /foo/:id,在 /foo/1 和 /foo/2 之间跳转的时候,
                    // 由于会渲染同样的 Foo 组件,因此组件实例会被复用。而这个钩子就会在这个情况下被调用。
                    // 可以访问组件实例 `this`
                },
                beforeRouteLeave(to, from, next) {
                    // 导航离开该组件的对应路由时调用
                    // 可以访问组件实例 `this`
                }
            }

完整的导航守卫解析流程

  1. 导航被触发。
    2. 在失活的组件里调用 beforeRouteLeave 守卫。
    3. 调用全局的 beforeEach 守卫。
    4. 在重用的组件里调用 beforeRouteUpdate 守卫 (2.2+)。
    5. 在路由配置里调用 beforeEnter。
    6. 解析异步路由组件。
    7. 在被激活的组件里调用 beforeRouteEnter。
    8. 调用全局的 beforeResolve 守卫 (2.5+)。
    9. 导航被确认。
    10. 调用全局的 afterEach 钩子。
    11. 触发 DOM 更新。
    12. 调用 beforeRouteEnter 守卫中传给 next 的回调函数,创建好的组件实例会作为回调函数的参数传入。

路由中的滚动行为设置

应用场景 : 在一个路由组件中滚动页面,切换到另一个组件中时,滚动条自动恢复到页面顶端的位置

    下面的代码要加在router对象的配置中

    //创建路由对象
    const router = new VueRouter({
        routes,
        scrollBehavior(to, from) {
            return { x: 0, y: 0 }
        }
    })

vue虚拟DOM

第一种: 更详细

1、读取data数据
2、读取模板
3、数据 + 模板 生成虚拟DOM(虚拟DOM就是一个JS对象,用它来描述真实DOM)(损耗一点性能)
原本准备生成的真实dom: <div id=“abc”><span> hello world </span></div>
虚拟DOM:['div', {id: 'abc‘}, ['span', '', 'hello world']]
4、用虚拟DOM的结构生成真实的DOM -> 视图显示 (用createElement可基于虚拟DOM生成真实DOM)
真实DOM:<div id='abc'><span></span></div>
5、当data发生了变化
6、数据 + 模板 生成新的虚拟DOM:
['div', {id: 'abc'}, ['span', '', 'hi world']](极大提升性能)
7、比较原始虚拟DOM和新的虚拟DOM的区别,找到的区别是span中的内容发生了变化(极大提升了性能)
8、将变化的部分生成真实DOM (用createElement可基于虚拟DOM生成真实DOM)
9、将不同部分渲染在页面(直接操作DOM,改变span中的内容)

虚拟DOM优点:1、性能提升了 2、它使得跨端应用得以实现,比如:React Native

第二种: 简洁版

1.获取数据
2.根据数据创建VDOM (相当于给对象赋值)
3.根据VDOM渲染生成真实DOM ( 根据createElement(‘DIV’) )
4.当数据发生改变后,又会生成新的VDOM

  1. 通过 diff 算法 比对 多次生成的 VDOM, 将不同的内容比对出来,然后再进行真实DOM渲染,
    一样的内容是不会进行渲染的,这就是VDOM 的 ‘就地复用’ | ‘惰性原则’

keep-alive

组件缓存
内置组件中<keep-alive>
被其包裹的组件,在v-if=false的时候,不会销毁,而是停用
v-if="true" 不会创建,而是激活
避免频繁创建组件对象的性能损耗

    最重要的是前两条:

    
    一、keep-alive组件:  缓存组件

    作用:可以让组件保留状态,避免重新渲染,提升页面性能

    二、举例:  在tab切换中,切换三个组件,不用keep-alive,每个组件在重新显示时,都会再执行created,并重复发起请求
            如果在外面包裹keep-alive, 则初次创建后会缓存组件,再次显示,不会再执行created,而是直接显示缓存的内容,不会再重复发起请求







    三、使用keep-alive后,缓存组件会多两个生命周期钩子:

        当缓存组件被激活时
        activated(){
            console.log('a-当缓存组件被激活时');
        },
        当缓存组件失活时
        deactivated(){
            console.log('a-当缓存组件失活时');
        }

    四、keep-alive有两个属性:  include exclude

        <keep-alive include="a1">    只有a1被缓存,a1是组件的name属性的值
        <keep-alive exclude="a1">    只有a1没有被缓存



    五、实例: 参考vue资料:  app各阶段项目代码-----21-0401-keep-alive缓存组件在项目中的使用(component组件-动态路由组件)


    六、**** 在动态路由的出口 <router-view>上使用keep-alive的技巧

        如果不用keep-alive,会重复发起请求(请求写到created,不会重复请求,但写到watch中,监听$route的变化,就会重复请求)

        使用的步骤:

        (1) 在动态路由组件内部的created中发起ajax请求
        (2)  设置key值
            <keep-alive>
                <router-view :key="$route.fullPath"></router-view>
            </keep-alive>

自定义过滤器

一、应用场景 :

  1. 展示商品价格时,添加人民币符号
  2. 展示时间时,把时间戳转换为规范的时间

二、 定义
全局定义
Vue.filter(”过滤器名称", (要处理的数据)=>{
return 处理后的结果
})

局部定义

new Vue({
    filters: {
        过滤器名称: (){

        }
    }
})

三、使用时

<div>{{price | 过滤器名称}}</div>

自定义指令

一、应用场景 : 初始化时,文本框获取焦点

二、 定义
全局定义
Vue.directive(”focus", (要处理的数据)=>{
return 处理后的结果
})

局部定义

new Vue({
    directives: {
        focus: (){

        }
    }
})

三、使用时

<input type="text" v-focus>

Vue中如何实现服务器代理

在vue.config.js中通过proxy代理,实现跨域

module.exports = {
......
devServer: {
// 代理
proxy: {
'/api': {
target: 'http://localhost:3000/',
changeOrigin: true,
//根据具体需求可选择把url中的/api部分替换为空
//pathRewrite: {
// '^/api': ''
//}
}
}
}
}

  1. 上线后,用Nginx实现服务器代理
    打包vue项目
    npm run build
    把dist文件夹放在nginx根目录

修改nginx的 conf/nginx.conf

server {
        listen       80;  #nginx服务器端口
        server_name  localhost;  #nginx域名

        location / {
            root   dist; #首页所在文件夹
            index  index.html index.htm;
        }

        location /api/ {
           proxy_pass   http://127.0.0.1:3000; # 将/api/开头的url转向该域名
        }

    }

重载nginx,浏览

nginx -s reload

3000端口的服务器要打开

vue-router的两种路由模式

hash: 地址栏中有#
history: 地址栏没有#,更好看一些

    改变模式,添加mode选项,默认是hash

    const router = new VueRouter({
        routes,
        mode: 'history'
    })

    hash: 使用 URL 的 hash 来模拟一个完整的 URL,于是当 URL 改变时,页面不会重新加载。

    history: 如果不想要很丑的 hash,我们可以用路由的 history 模式,这种模式充分利用 history.pushState API 来完成 URL 跳转而无须重新加载页面。

style 中的 scoped的作用

基本要求: 记住第一条

一、 scoped的作用: 使当前组件的样式不会和其它组件冲突,因为它会给每个组件相关的选择器添加不会重复的属性

        h1 {

        }

        h1[data-e543434] {
            
        }

        二、注意事件:
            1、使用 scoped 后,父组件的样式将不会渗透到子组件中。
            2、不过一个子组件的根节点会同时受其父组件的 scoped CSS 和子组件的 scoped CSS 的影响。
            3、这样设计是为了让父组件可以从布局的角度出发,调整其子组件根元素的样式

                <style scoped>

                </style>


        三、在swiper轮播图中,如果要修改分页器的样式,要进行样式穿透(穿透之后,父组件定义的样式可以作用于子组件中的子元素)

                (因为有scoped,所以默认情况下,父组件的样式不能作用于子组件的子元素)

                
                下面这句话放在所有选择器的上面

                1.  scss的样式穿透的写法: 加上/deep/

                    .swiper-container /deep/ .swiper-pagination-bullet {
                        background-color: #f00;
                        opacity: 1;
                    }

                2. stylus的样式穿透的写法: 加上::v-deep

                .wrapper ::v-deep .swiper-pagination-bullet
                    opacity 1
                    background-color #fff
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,047评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,807评论 3 386
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,501评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,839评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,951评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,117评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,188评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,929评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,372评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,679评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,837评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,536评论 4 335
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,168评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,886评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,129评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,665评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,739评论 2 351