最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • 手撕代码

    正文概述 掘金(----影子)   2021-02-24   702

    2-3 css部分

    • 两栏布局
    • 三栏布局
    • 双飞翼和圣杯布局:和三栏布局要求相同,不过中间列要写在前面保证优先渲染。
    • 三角形
    • 使用 css 实现一个宽高自适应的正方形
    • 实现扇形(border+旋转)
    • 垂直居中(left:0,margin:0,top:0,right:0,margin:auto)
    • 清除浮动(伪元素clear:both),父级触发BFC
    • 弹出框
    • 导航栏(滑动)

    CSS 部分完,总结,Flex 无敌。

    2-4 js 部分

    • hash路由
    window.addEventlistener('hashchange',(e)=>{
      location.hash
    } )
    1.监听
    2.操作BOM
    
    • history路由
    调用 history.pushState() 或者 history.replaceState() 不会触发 popstate 事件。
    

    2-4 css部分

    • 扩大可点击区域
        .expand-range {
          position: relative;
          cursor: pointer;
        }
    
        .expand-range::after {
          content: '';
          position: absolute;
          top: -10px;
          right: -10px;
          bottom: -10px;
          left: -10px;
        }
    

    scss方式

    @mixin expand-range($top: -10px, $right: $top, $bottom: $top, $left: $right, $position: relative,$cursor:pointer) {
      position: $position;
      cursor: $cursor;
      &:after {
        content: '';
        position: absolute;
        top: $top;
        right: $right;
        bottom: $bottom;
        left: $left;
      }
    }
    //使用:.test { @include expand-range($top: -5px) }
    
    • 巧用层叠上下文

      元素的层叠关系,背景,负z-index,盒子z-index

      利用伪元素实现圆角矩形并叠加在父元素的背景之上文字之下

    /*边框内圆角*/
    div {
      position: relative;
      z-index: 1;
      height: 200px;
      padding: 10px;
      background: #333;
    }
    
    div::after {
      content: '';
      position: absolute;
      left: 10px;
      top: 10px;
      right: 10px;
      bottom: 10px;
      z-index: -1;
      border-radius: 5px;
      background: cyan;
    }
    
    • clip-path
    • min-content (自适应宽度)
    • box-shadow
    • 解析background
    • linear-gradient
    • animation

    总结:背景颜色,渐变,动画,position,box-shadow

    2-4 vue部分

    • 说说你对 SPA 单页面的理解,它的优缺点分别是什么?
    • v-show 与 v-if 有什么区别?
    • Class 与 Style 如何动态绑定?(都是对象和数组,稍微有点区别而已,style数组的值是写好的在data上)
    • 怎样理解 Vue 的单向数据流?(props)
    • computed 和 watch 的区别和运用的场景?
    • 直接给一个数组项赋值,Vue 能检测到变化吗?
    • 谈谈你对 Vue 生命周期的理解?
    • Vue 的父组件和子组件生命周期钩子函数执行顺序?
    • 在哪个生命周期内调用异步请求?
    • 父组件可以监听到子组件的生命周期吗?
    • 谈谈你对 keep-alive 的了解?
    <keep-alive>
    	<router-view />
    </keep-alive>
    直接嵌套二级组件是不会缓存的
    那么就会缓存在Ndode节点中了,就不会重新创建,那么也就不会触发生命周期了 activated,deactivated 
    组件内路由导航:beforeRouteEnter,beforeRouteLeave  
    
    
    如果想记住二级切换的是哪个组件
    data(){
    	return {
    		path:/home
    	}
    }
    activated(){
    	this.$router.push(this.path)
    },
    deactivated(){},
    beforeRouteLeave(to,from,next){
      this.path =this.$route.path
      next()
      }
    这样就是记住上一个二级路由
    
    • 组件中 data 为什么是一个函数?
    • v-model 的原理?

    在表单 input、textarea、select 等元素上创建双向数据绑定

    <input v-model='something'>
        
    相当于
    
    <input v-bind:value="something" v-on:input="something = $event.target.value">
    
    

    如果在自定义组件中,v-model 默认会利用名为 value 的 prop 和名为 input 的事件,如下所示:

    父组件:
    <ModelChild v-model="message"></ModelChild>
    
    子组件:
    <div>{{value}}</div>
    
    props:{
        value: String
    },
    methods: {
      test1(){
         this.$emit('input', '小红')
      },
    },
    
    
    • Vue 组件间通信有哪几种方式?
    • 能说下 vue-router 中常用的 hash 和 history 路由模式实现原理吗?
    • 什么是 MVVM?
    • Vue 是如何实现数据双向绑定的?
    • Vue 框架怎么实现对象和数组的监听?
    • Vue 怎么用 vm.$set() 解决对象新增属性不能响应的问题

    2-6 ES6部分

    • ES6面向对象

    通过class关键字创建类,类名我们还是习惯性定义首写字母大写

    类里面有个constructor函数,可以接受传递过来的参数,同时返回实例对象

    constructor 函数只要new生成实例时,就会自动调用这个函数,如果我们不写这个函数,类也会自动生成这个函数

    生成实例 new 不能省略

    最后注意语法规范,创建类 类名后面不要加小括号,生成实例 类名后面要加小括号,构造函数不需要加function

    我们类里面的所有函数不需要写function

    多个函数方法之间不需要添加逗号分隔

    class Name {
    	constructor(x,y){
        this.x = x;
        this.y = y;
      }
      say(){}
      good(){}
    }
    // 继承
    class Father{
      constructor(x,y){
        this.x = x;
        this.y = y;
    	}
      say(){
        console.log('father')
      }
    }
    class Son extends Father{
      constructor(x,y){
        super(x,y)
      }
    }
    
    
    // 私有属性方法
    const name = Symbol("name");
    const print = Symbol("print");
    class Person{
      constructor(age){
        this[name] = 'aking'
        this.age = age;
    	}
      [print](){
        console.log(`${this[name]} is ${this.age} years old`)
      }
    }
    
    // 混合继承
    function CopyProperties(target, source) {
        for (const key of Reflect.ownKeys(source)) {
            if (key !== "constructor" && key !== "prototype" && key !== "name") {
                const desc = Object.getOwnPropertyDescriptor(source, key);
                Object.defineProperty(target, key, desc);
            }
        }
    }
    function MixClass(...mixins) {
        class Mix {
            constructor() {
                for (const mixin of mixins) {
                    CopyProperties(this, new mixin());
                }
            }
        }
        for (const mixin of mixins) {
            CopyProperties(Mix, mixin);
            CopyProperties(Mix.prototype, mixin.prototype);
        }
        return Mix;
    }
    class Student extends MixClass(Person, Kid) {}
    

    2-7 vue通信的细节

    • props
    • this.$xxx

    通过this下面的数据直接获取vue实例这种方法比较暴力,因为我们所谓的组件,最终都会是一个对象,存放组件的各种信息,组件和组件通过this.$childrenthis.$parent指针关联起来。因为在项目中只有一个root根组件,理论上,我们可以找到通过this.$children this.$parent来访问页面上的任何一个组件 ,但是实际上如何精确匹配到目标组件,确是一个无比棘手的问题。

    • provide inject
    // 父组件   
    provide(){
           return {
               /* 将自己暴露给子孙组件 ,这里声明的名称要于子组件引进的名称保持一致 */
               father:this
           }
       },
    // 这里我们通过provide把本身暴露出去。⚠️⚠️⚠️这里声明的名称要与子组件引进的名称保持一致
    
    // 子组件
       /* 引入父组件 */
       inject:['father'],
         methods:{
           send(){
             this.father.sonSay(this.mes)
           }
         },
    
    // 父组件
    // 如果我们向外提供了方法,如果方法里面有操作this行为,需要绑定this
       provide(){
           return {
               /* 将通信方法暴露给子孙组件(注意绑定this) */
               grandSonSay:this.grandSonSay.bind(this),
               sonSay:this.sonSay.bind(this)
           }
       },   
       methods:{
          /* 接受孙组件信息 */
          grandSonSay(value){
              this.grandSonMes = value
          },
          /* 接受子组件信息 */ 
          sonSay(value){
              this.sonMes = value
          },
       },
    // 子组件
    /* 引入父组件方法 */
       inject:['sonSay'],
       methods:{
           send(){
               this.sonSay(this.mes)
           }
       },
    
    • vuex
    import Vuex from 'vuex'
    import Vue from 'vue'
    
    Vue.use(Vuex)
    
    export default new Vuex.Store({
      state: {
        fatherMes: 'fatherMes',
        sonMes: 'sonMes',
        fatherMesAsync: 'fatherMesAsync'
      },
      mutations: {
        sayFaher(state, value) {
          state.fatherMes = value
        },
        saySon(state, value) {
          state.sonMes = value
        },
        sayAsyncFather(state, value) {
          state.fatherMesAsync = value
        }
      },
      actions: {
        asyncSayFather({ commit }, payload) {
          return new Promise((resolve) => {
            setTimeout(() => {
              resolve(payload)
              console.log(payload)
            }, 2000)
          }).then(res => {
            console.log('后执行')
            commit('sayAsyncFather', res)
          })
        }
      }
    })
    
    
    <template>
      <div class="father">
        <input v-model="mes" /> <button @click="send">同步:对子组件说</button
        ><br />
        <input v-model="asyncMes" />
        <button @click="asyncSend">异步:对子组件说</button><br />
        <div>子组件对我说:{{ sonMes }}</div>
      </div>
    </template>
    <script>
    export default {
      /* 父组件 */
      name: 'father',
      data() {
        return {
          mes: '',
          asyncMes: ''
        }
      },
      computed: {
        sonMes() {
          return this.$store.state.sonMes
        }
      },
      mounted() {
        console.log(this.$store)
      },
      methods: {
        /* 触发mutations,传递数据给子组件 */
        send() {
          this.$store.commit('sayFaher', this.mes)
        },
        /* 触发actions,传递数据给子组件 */
        asyncSend() {
          this.$store.dispatch('asyncSayFather', this.asyncMes)
        }
      }
    }
    </script>
    
    
    • 总结:通信就是组件实例之间的数据相互传递,组件实例相互暴露。

    vue最终版

    • v-bind="props"vbind="props" v-bind="props"v−bind="attrs" v-on="$listeners"
    post: {
      id: 1,
      title: 'My Journey with Vue',
    	placeholder:'默认'
    }
    <!-- 利用 v-bind 可以传入一个对象的所有 property,类似 v-bind="Obj" -->
    <blog-post v-bind="post"></blog-post>
    <!--等价于-->
    <blog-post
      v-bind:id="post.id"
      v-bind:
    ></blog-post>
    
    <input type="text" v-bind="$attrs"/>
    
    // top组件,传递了name,age,gender,sdf四个属性到子组件center,然后接收了两个isClick()和asd()方法
    <template>
      <section>
        <centers
          name="name"
          age="18"
          gender="666"
          sdf="asd"
          @isClick="isClick"
          @asd="asd"
        ></centers>
      </section>
    </template>
    <script>
      import centers from '~/components/center';
      export default {
        components: {
          centers
        },
        methods: {
          asd() {
            console.log(999);
          },
          isClick() {
            console.log(666);
          }
        }
      };
    </script>
    // 未识别的事件可通过v-on="$listeners"传入(.native绑原生事件是没用的) center组件
    <template>
      <section>
        <div class="mt-10">
          <bottom v-bind="$attrs" v-on="$listeners" />
        </div>
      </section>
    </template>
    
    <script>
      import bottom from '~/components/bottom';
      export default {
        components: {
          bottom
        },
        props: {
          name: {
            type: String,
            default: 'default'
          },
          age: {
            type: String,
            default: 'default'
          }
        }
      };
    </script>
    
    //bottom组件
    <template>
      <section>
        <div>
          {{ $attrs['gender'] }}  在$attrs里面只会有props没有注册的属性
          <br>
          {{ gender }}
        </div>
      </section>
    </template>
    
    <script>
      export default {
        props: {
          gender: {
            type: String,
            default: ''
          }
        },
        mounted() {
          console.log(this.$attrs);
          console.log(this.$listeners);
          this.$listeners.isClick();
          this.$listeners.asd();
        }
      };
    </script>
    
    • Props 校验
    Vue.component('my-component', {
        // 带有默认值的对象
        propA: {
          type: Object,
          // 对象或数组默认值必须从一个工厂函数获取
          default: function () {
            return { message: 'hello' }
          }
        }
    })
    Vue.component('my-component', {
        // 自定义验证函数
        propF: {
          validator: function (value) {
            // 这个值必须匹配下列字符串中的一个
            return ['success', 'warning', 'danger'].indexOf(value) !== -1
          }
        }
    })
    
    
    • 插槽
        <!-- 具名插槽 -->
        <h3>具名插槽</h3>
        <Child2>
          <template v-slot:footer><div>我是底部</div></template>
          <template #header><div>我是头部</div></template>
          <template v-slot:default>
            <div>我是内容</div>
          </template>
        </Child2>
    
    
      <div class="child">
        <slot name="header"></slot>
        <slot></slot>
        <div>Hello, I am from Child.</div>
        <slot name="footer"></slot>
      </div>
    
    
      <div class="child">
        <div>Hello, I am from Child.</div>
        <!-- 将user和callMe通过 v-bind 的方式传递 -->
        <slot :user="user" :callMe="callMe"></slot>
      </div>
    <!--然后在父组件中的插槽内,通过类似 v-slot:default="slotProps" 接受子组件传递过来的数据-->
        <Child3>
          <!-- slotProps 可以自定义-->
          <template v-slot:default="slotProps">
            <div>我的名字:{{slotProps.user.name}}</div>
            <div>我的年龄:{{slotProps.user.age}}</div>
            <button @click="slotProps.callMe">Clicl Me</button>
          </template>
        </Child3>
    <!-- 以上 slotProps 可以自定义,而且可以使用解构赋值的语法 -->
    
    <!-- 解构赋值 -->
    <template v-slot:other="{ user, callMe}">
      <div>我的名字:{{user.name}}</div>
      <div>我的年龄:{{user.age}}</div>
      <button @click="callMe">Clicl Me</button>
    </template>
    
    
    
    • 动态的指令参数

    
    <template>
      ...
      <my-button @[someEvent]="handleSomeEvent()"/>
      ...
    </template>
    
    <script>
      ...
      data(){
        return{
          ...
          someEvent: someCondition ? "click" : "dblclick"
        }
      },
      
      methods:{
        handleSomeEvent(){
          // do something
        }
      }
      ...
    </script>
    
    
    • hookEvent 的使用
    比如,我们调用了一个很耗费性能的第三方组件 List,这个组件可能需要渲染很久,为了更好的用户体验,我们想在 List 组件进行更新的时候添加一个 loading 的动画效果
    
    <List @hook:updated="handleTableUpdated"></List >
    
    另外,我们还可以通过下面的方式给一个 Vue 组件添加生命周期处理函数
    vm.$on('hooks:created', cb)
    vm.$once('hooks:created', cb)
    
    mounted(){
    	const thirdPartyPlugin = thirdPartyPlugin()
    	this.$on('hook:beforeDestroy',()=>{
    		thirdPartyPlugin.destroy()
    })
    }
    
    • key 值的使用
    • CSS scoded 和深度作用选择器
    • watch immediate deep $watch
    这里 watch 的一个特点是,最初绑定的时候是不会执行的,要等到 id 改变时才执行监听计算。这可能导致我们页面第一次渲染出错
    
    watch: {
      id: {
        handler(newValue) {
          this.getDetails(newValue);
        },
        // 代表在wacth里声明了id后这个方法之后立即先去执行handler方法
        immediate: true
        // 通过指定deep属性为true, watch会监听对象里面每一个值的变化
        deep: true
      }
    }
    
    但是如果要在页面初始化时候加载数据,我们还需要在created或者mounted生命周期钩子里面再次调用$_loadData方法。不过,现在可以不用这样写了,通过配置watch的立即触发属性,就可以满足需求了
    
    我们可以在需要的时候通过this.$watch来监听数据变化。那么如何取消监听呢,上例中this.$watch返回了一个值unwatch,是一个函数,在需要取消的时候,执行 unwatch()即可取消
    
    export default {
      data() {
        return {
          formData: {
            name: '',
            age: 0
          }
        }
      },
      created() {
        this.$_loadData()
      },
      methods: {
        // 模拟异步请求数据
        $_loadData() {
          setTimeout(() => {
            // 先赋值
            this.formData = {
              name: '子君',
              age: 18
            }
            // 等表单数据回填之后,监听数据是否发生变化
            const unwatch = this.$watch(
              'formData',
              () => {
                console.log('数据发生了变化')
              },
              {
                deep: true
              }
            )
            // 模拟数据发生了变化
            setTimeout(() => {
              this.formData.name = '张三'
            }, 1000)
          }, 1000)
        }
      }
    }
    
    
    • v-once 和 v-pre 提升性能
    • v-cloak 解决页面闪烁问题
    // template 中
    <div class="#app" v-cloak>
        <p>{{value.name}}</p>
    </div>
    
    // css 中
    [v-cloak] {
        display: none;
    }
    
    
    • 表单输入控制——表单修饰符/change事件/filter
    <input v-model.number="age" type="number">
    <input v-model.trim="msg">
    
    给表单绑定事件,在事件处理中进行表单输入控制
    <input v-model="value2" type="text" @change="inputChange(value2)" />
    
    methods: {
      inputChange: function(val) {
        if (!val) return ''
        val = val.toString()
        this.value2 = val.charAt(0).toUpperCase() + val.slice(1)
      }
    }
    
    filter:
    <input v-model="value1"  type="text" />
    
    Vue.filter('capitalize', function (value) {
      if (!value) return ''
      value = value.toString()
      return value.charAt(0).toUpperCase() + value.slice(1)
    })
    
    watch: {
      value1(val) {
         this.value1 = this.$options.filters.capitalize(val);
      }
    }
    
    
    • 事件:特殊变量 $event
    <!-- 注意这里调用的方法有两个参数 -->
    <input v-model="value1" @change="inputChange('hello', $event)">
    
    methods: {
      inputChange(msg, e) {
        console.log(msg, e);
      }
    }
    在自定义事件中,$event 是从其子组件中捕获的值
    
    场景:你想监听 el-input 的传递过来的值的同时,传递其他的参数。
    
    <el-input
          v-model="value2"
          @change="change($event, 'hello')"
          placeholder="Input something here"
        />
    methods: {
      change(e, val) {
        console.log("event is " + e); // el-input 输入的值
        console.log(val); // hello
      }
    }
    
    
    • 调试template
    // 这里最好是判断一下,只有在测试环境中才使用
    // main.js
    Vue.prototype.$log = window.console.log;
    
    // 组件内部
    <div>{{$log(info)}}</div>
    
    

    继续肝

    • require.context()
    const path = require('path')
    const files = require.context('@/components/home', false, /\.vue$/)
    const modules = {}
    files.keys().forEach(key => {
      const name = path.basename(key, '.vue')
      modules[name] = files(key).default || files(key)
    })
    components:modules
    
    
    • .sync
    // 父组件
    <home :title.sync="title" />
    //编译时会被扩展为
    <home :  @update:/>
    
    // 子组件
    // 所以子组件可以通过$emit 触发 update 方法改变
    mounted(){
      this.$emit("update:title", '这是新的title')
    }
    
    
    • .EventBus
    1.就是声明一个全局Vue实例变量 EventBus , 把所有的通信数据,事件监听都存储到这个变量上; 2.类似于 Vuex。但这种方式只适用于极小的项目 3.原理就是利用on和on和emit 并实例化一个全局 vue 实现数据共享
    
    
    // 在 main.js
    Vue.prototype.$eventBus=new Vue()
    
    // 传值组件
    this.$eventBus.$emit('eventTarget','这是eventTarget传过来的值')
    
    // 接收组件
    this.$eventBus.$on("eventTarget",v=>{
      console.log('eventTarget',v);//这是eventTarget传过来的值
    })
    
    
    • 路由传参
    // 路由定义
    {
      path: '/describe/:id',
      name: 'Describe',
      component: Describe
    }
    // 页面传参
    this.$router.push({
      path: `/describe/${id}`,
    })
    // 页面获取
    this.$route.params.id
    
    
    // 路由定义
    {
      path: '/describe',
      name: 'Describe',
      component: Describe
    }
    // 页面传参
    this.$router.push({
      name: 'Describe',
      params: {
        id: id
      }
    })
    // 页面获取
    this.$route.params.id
    
    
    // 路由定义
    {
      path: '/describe',
      name: 'Describe',
      component: Describe
    }
    // 页面传参
    this.$router.push({
      path: '/describe',
        query: {
          id: id
      `}
    )
    // 页面获取
    this.$route.query.id
    
    
    • 路由按需加载
    {
      path:'/',
      name:'home',
      components:()=>import('@/components/home')
    }
    
    import()方法由es6提出,import()方法是动态加载,返回一个Promise对象,then方法的参数是加载到的模块。
    类似于Node.js的require方法,主要import()方法是异步加载的。
    
    
    • 动态组件
    <transition>
    <keep-alive>
      <component v-bind:is="currentTabComponent"></component>
    </keep-alive>
    </transition>
    
    • components和 Vue.component
    components:局部注册组件
    
    export default{
      components:{home}
    }
    
    Vue.component:全局注册组件
    Vue.component('home',home)
    
    • Vue.extend
    // 创建构造器
    var Profile = Vue.extend({
      template: '<p>{{extendData}}</br>实例传入的数据为:{{propsExtend}}</p>',//template对应的标签最外层必须只有一个标签
      data: function () {
        return {
          extendData: '这是extend扩展的数据',
        }
      },
      props:['propsExtend']
    })
    
    // 创建的构造器可以挂载到元素上,也可以通过 components 或 Vue.component()注册使用
    // 挂载到一个元素上。可以通过propsData传参.
    new Profile({propsData:{propsExtend:'我是实例传入的数据'}}).$mount('#app-extend')
    
    // 通过 components 或 Vue.component()注册
    Vue.component('Profile',Profile)
    
    
    • mixins
    场景:有些组件有些重复的 js 逻辑,如校验手机验证码,解析时间等,mixins 就可以实现这种混入 mixins 值是一个数组
    
    const mixin = {
      created(){
        this.dealTime()
      },
      methods:{
        dealTime(){
          console.log('这是mixin的dealTime里面的方法')
        }
      }
    }
    export default{
      mixins:[mixin]
    }
    
    • Vue.vue()
    • install
    var MyPlugin = {};
      MyPlugin.install = function (Vue, options) {
        // 2. 添加全局资源,第二个参数传一个值默认是update对应的值
        Vue.directive('click', {
          bind(el, binding, vnode, oldVnode) {
            //做绑定的准备工作,添加时间监听
            console.log('指令my-directive的bind执行啦');
          },
          inserted: function(el){
          //获取绑定的元素
          console.log('指令my-directive的inserted执行啦');
          },
          update: function(){
          //根据获得的新值执行对应的更新
          //对于初始值也会调用一次
          console.log('指令my-directive的update执行啦');
          },
          componentUpdated: function(){
          console.log('指令my-directive的componentUpdated执行啦');
          },
          unbind: function(){
          //做清理操作
          //比如移除bind时绑定的事件监听器
          console.log('指令my-directive的unbind执行啦');
          }
        })
    
        // 3. 注入组件
        Vue.mixin({
          created: function () {
            console.log('注入组件的created被调用啦');
            console.log('options的值为',options)
          }
        })
    
        // 4. 添加实例方法
        Vue.prototype.$myMethod = function (methodOptions) {
          console.log('实例方法myMethod被调用啦');
        }
      }
    
      //调用MyPlugin
      Vue.use(MyPlugin,{someOption: true })
    
      //3.挂载
      new Vue({
        el: '#app'
      });
    
    
    • Vue.nextTick
    mounted(){ //因为 mounted 阶段 dom 并未渲染完毕,所以需要$nextTick
      this.$nextTick(() => {
        this.$refs.inputs.focus() //通过 $refs 获取dom 并绑定 focus 方法
      })
    }
    
    • vue.derective
    // 全局定义
    Vue.directive("change-color",function(el,binding,vnode){
      el.style["color"]= binding.value;
    })
    
    // 使用
    <template>
    <div v-change-color=“color”>{{message}}</div>
    </template>
    <script>
      export default{
        data(){
          return{
            color:'green'
          }
        }
      }
    </script>
    
    
    • vue.filter
    // 使用
    // 在双花括号中
    {{ message | capitalize }}
    
    // 在 `v-bind` 中
    <div v-bind:id="rawId | formatId"></div>
    
    // 全局注册
    Vue.filter('stampToYYMMDD', (value) =>{
      // 处理逻辑
    })
    
    // 局部注册
    filters: {
      stampToYYMMDD: (value)=> {
        // 处理逻辑
      }
    }
    
    // 多个过滤器全局注册
    // /src/common/filters.js
    let dateServer = value => value.replace(/(\d{4})(\d{2})(\d{2})/g, '$1-$2-$3') 
    export { dateServer }
    // /src/main.js
    import * as custom from './common/filters/custom'
    Object.keys(custom).forEach(key => Vue.filter(key, custom[key]))
    
    
    
    • 事件修饰符
    • 缓存和动画

    注:匹配首先检查组件自身的 name 选项,如果 name 选项不可用,则匹配它的局部注册名称 (父组件 components 选项的键值)。匿名组件不能被匹配

    • 全局路由钩子
    // 1.router.beforeEach
    
    router.beforeEach((to, from, next) => {
      console.log('全局前置守卫:beforeEach -- next需要调用') //一般登录拦截用这个,也叫导航钩子守卫
      if (path === '/login') {
        next()
        return
      }
      if (token) {
        next();
      } 
    })
    
    
    • 组件路由钩子

    1.beforeRouteEnter 在渲染该组件的对应路由被确认前调用,用法和参数与router.beforeEach类似,next需要被主动调用 此时组件实例还未被创建,不能访问this 可以通过传一个回调给 next来访问组件实例。在导航被确认的时候执行回调,并且把组件实例作为回调方法的参数

    beforeRouteEnter (to, from, next) {
      // 这里还无法访问到组件实例,this === undefined
      next( vm => {
        // 通过 `vm` 访问组件实例
      })
    }
    

    2.beforeRouteUpdate (v 2.2+) 在当前路由改变,并且该组件被复用时调用,可以通过this访问实例, next需要被主动调用,不能传回调

    3.beforeRouteLeave 导航离开该组件的对应路由时调用,可以访问组件实例 this,next需要被主动调用,不能传回调

    • Vue.routerVue.router Vue.routerVue.route
    this.$router.push():跳转到不同的url,但这个方法回向history栈添加一个记录,点击后退会返回到上一个页面
    this.$router.replace():不会有记录
    this.$router.go(n):n可为正数可为负数。正数前进, 负数后退,类似 window.history.go(n)
    
    • router-view 的 key

    场景:由于 Vue 会复用相同组件, 即 /page/1 => /page/2 或者 /page?id=1 => /page?id=2 这类链接跳转时, 将不在执行created, mounted之类的钩子

    <router-view :key="$route.fullPath"></router-view>
    

    这样组件的 created 和 mounted 就都会执行

    • vue-loader

    它允许你以一种名为单文件组件 (SFCs)的格式撰写 Vue 组件。简而言之,webpack 和 Vue Loader 的结合为你提供了一个现代、灵活且极其强大的前端工作流,来帮助撰写 Vue.js 应用。

    • img 加载失败

    场景:有些时候后台返回图片地址不一定能打开,所以这个时候应该加一张默认图片

    // page 代码
    <img :src="imgUrl" @error="handleError" >
    <script>
    export default{
      data(){
        return{
          imgUrl:''
        }
      },
      methods:{
        handleError(e){
          e.target.src=reqiure('图片路径') //当然如果项目配置了transformToRequire,参考上面 33.2
        }
      }
    }
    </script>
    
    
    • 基础指令
    • vue-loader是什么?使用它的用途有哪些?

    vue 文件的一个加载器,将 template/js/style 转换成 js 模块。

    用途:js 可以写 es6style样式可以 scsslesstemplate 可以加 jade


    起源地下载网 » 手撕代码

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元