我是靠谱客的博主 贤惠泥猴桃,最近开发中收集的这篇文章主要介绍Vue2知识点总结及学习心得1.模板语法2.el和data两种写法3.数据绑定4.MVVM模型5.Object.defineProperty6.事件处理⭐️7.method与computed的区别8.watch侦听器8.class和style9.条件渲染11.Vue监测数据⭐️12.收集表单数据13.过滤器14.指令15.生命周期⭐️16.非单文件组件17.Cli脚手架18.ref属性19.props属性父传子⭐️20.mixin21.插件22.scoped样式23.自动生成id插件24.自定义,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

Vue2中文文档

1.模板语法

  1. 插值
   <body>
     <div class="app">
       <!-- 模板语法中支持表达式,不支持语句
       表达式:会生成一个值,比如a,a+b,demo(1),ok ? 'YES' : 'NO'
       就是我们可以拿一个变量在表达式左边接到值,可以用+连接-->
       <h1> Hello {{address+name}},{{name}},{{1+1+num}}</h1>
       <h2>{{school.name}}</h2>
     </div>
     <script>
       // 阻止Vue在启动时生成生产提升
       Vue.config.productionTip = false
       var app = new Vue({
         el: '.app',
         // data中用于存储数据,数据供el所指定的容器去使用,data中数据改变,页面也会随之改变
         data: {
           name: 'Vue!',
           address: '北京',
           num: 2,
           school: {
             name: '国防科大'
           }
         }
       })
  1. 指令

     <div id="root">
        <h1>插值语法</h1>
        <h3>你好,{{name}}</h3>
        <hr>
        <h1>指令语法</h1>
        <a v-bind:href="url">点我去B</a>
        <!-- 指令简写 -->
        <a :href="url.toUpperCase()">点我去B</a>
        <!-- 动态参数 -->
        <a :[att]="url">动态参数</a>
        <hr>
        <h1>dom事件</h1>
    
      </div>
      <script>
        new Vue({
          el: '#root',
          data: {
            name: 'jact',
            url: 'https://www.bilibili.com/',
            att: 'href'
          }
        })
    

2.el和data两种写法

<div id="root">
    <h1>{{name}}</h1>
  </div>
  <script>
    const v = new Vue({
      el: '#root',
      /* data: {
      //   name: '对象式data写法'
      } */
      //data写法2函数式
      //vue管理的函数不要写箭头函数,否则this就不再是Vue实例了
      data: function () {
        return {
          name: '函数式data写法'
        }
      },
    })
    console.log(v);
    // setTimeout(() => {
    //   v.$mount('#root');el第2种写法
    // }, 1000)
  </script>

3.数据绑定

v-bind ⭐️

拿到的是“”双引号里面的值,没加则拿到的是字符串

  <!-- v-bind数据只能从data流向页面 -->
    <h2>单向数据绑定:<input type="text" :value="name"></h2>
    <!-- v-module只能应用在表单类元素上,对应的value属性 -->
    <h2>双向数据绑定:<input type="text" v-model:value="name"></h2>
    <h2>双向数据绑定简写:<input type="text" v-model="name"></h2>

v-model

  1. v-model绑定的值不能是props传过来的值,因为props是不可以修改的
  2. props传过来的若是对象类型的值,只要不直接修改对象而是修改对象中的属性时Vue不会报错,但不推荐这样做

4.MVVM模型

M—model(模型):对应data中的数据

V–View(视图):模板代码

VM–ViewModel(视图模板):Vue实例对象

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jSW2F9R4-1669432222699)(D:新的开始mdVueimage1.png)]

5.Object.defineProperty

基本使用

object.defineProperty(obj,prop,descriptor)

只有用这个方法加进去的才受控制

  • obj:必需。目标对象

  • prop:必需。需定义或修改的属性的名字

  • descriptor:必需。目标属性所拥有的特性

    • value:设置属性的值
    • writable:值是否可以重写修改。true/false,默认为false
    • enumerable:目标属性是否可以被枚举。true/false,默认为false
    • configurable:目标属性是否可以被删除或是否可以再次修改特性true/false,默认为false
    • 这里id是本身有的,所以不受控制
      var obj = {
          id: 1,
          pname: '小米',
          price: 1999
        };
        // 有则修改,无则添加
        Object.defineProperty(obj, 'num', {
          value: 1000,
          // 因为writable默认为false
        });
        obj.num = 3;
        obj.id = 3;
        console.log(obj);//id:3,num:1000
    

getter和setter数据代理

  let number = 18;
      let person = {
        name: '张三',
        sex: '男'
      }
      Object.defineProperty(person, 'age', {
        /*- value:设置属性的值
        - writable:值是否可以重写修改。true/false,默认为false
        - enumerable:目标属性是否可以被枚举。true/false,默认为false
        - configurable:目标属性是否可以被删除或是否可以再次修改特性true/false,默认为false*/

        //当有人读取person的age属性时,get函数就会被调用,且返回值就是age的值  
        get() {
          // 无论你咋修改person的值它都是取number
          console.log('有人读取了age属性');
          return number
        },
        //当有人修改age属性时,set函数就会被调用,且会收到修改的具体值
        set(value) {
          console.log('有人修改了age属性,且值是' + value);
          number = value;
        }
      })

简单数据代理

  let obj = {
      x: 100
    }
    let obj2 = {
      y: 100
    }
    Object.defineProperty(obj2, 'x', {
      // 当有人读取Obj2的x属性时,就会调用get函数,且返回的值会给x
      get() {
        return obj.x
      },
      //当有人修改Obj2的x属性时,set函数就会被调用,且会收到修改的具体值
      set(value) {
        obj.x = value
      }
    })

Vue中的数据代理

也是利用Object.defineProperty中的getter和setter

<h1 id="main">学校名称: {{name}} <br>
    校址: {{address}}</h1>
  <script>
    const vm = new Vue({
      el: '#main',
      data: {
        name: '井冈山大学',
        address: '江西吉安'
      }
    })
    console.log(vm);
    console.log(vm.address === vm._data.address);//true,江西吉安

6.事件处理⭐️

事件回调要写到methods对象上,this.name可以拿到data里面的name数据

1.使用v-on:xxx或者@click绑定事件,xxx是事件名,2.事件回调要写到methods对象上,最终会在vm中,3.this指向vm或组件实例对象,4.@click='demo’和=demo($event)效果一致

<div id="root">
    <h2>欢迎来到{{name}}学习</h2>
    <button @click="showInfo">不传参</button>
    <button v-on:click="showInfo2(66)">传参</button>
    <button @click="showInfo3('刘总',$event)">2个参数和evert</button>
  </div>
  <script>
    const vm = new Vue({
      el: '#root',
      data: {
        name: '武当派',
      },
      methods: {
        showInfo(e) {
          console.log(e.target);
          console.log(this === vm);//true
        },
        showInfo2(number) {
          console.log(number);
        },
        showInfo3(str, e) {
          console.log(str);
          console.log(e);
        }
      },
    })

Vue中的事件修饰符

还可以连着使用.stop.prevent,可以看文档

  1. prevent:阻止默认事件(常用)
  2. stop:阻止事件冒泡(常用)
  3. once:事件只触发一次(常用)
  4. capture:使用事件的捕获模式
  5. self:只有event.target是当前操作的元素时才触发事件
  6. passive:事件的默认行为立即执行,无需等待事件回调执行完毕

对图片的监听

<!-- @Load监听图片是否加载完 -->

    <img v-lazy='showImage' @load="imageLoad">

 methods:{

      imageLoad(){

         this.$bus.$emit('itemImageLoad')

Vue中常用键盘事件

  • enter

  • .tab

  • .delete (捕获“删除”和“退格”键)

  • .esc

  • .space

  • .up

  • .down

  • .left

  • .right

  • <div id="root">
       <input type="text" placeholder="按下回车提示输入" @keyup.enter="showInfo">
     </div>
     <script>
       new Vue({
         el: '#root',
         methods: {
           showInfo(e) {
             console.log(e.target.value);
           }
         },
       })
    

7.method与computed的区别

computed计算属性会有缓存,依赖数据改变才会重新触发,下面打印一个,methods打印3次

computed⭐️

计算属性不要加(),是靠返回值拿东西的;
刚加载页面初始化自动触发一次,然后依赖数据发生改变也会触发
如果值只读取,则可以简写,如果还要修改则得写setter
  <span>{{fullName}}</span><br>
    <span>{{fullName}}</span><br>
    <span>{{fullName}}</span>
  </div>
  <script>
    new Vue({
      el: '#root',
      data: {
        user: '刘',
        name: '总'
      },
      computed: {
        fullName() {
          console.log('444');
          return this.user + '-' + this.name
        }
      }
      // methods: {
      //   fullName() {
      //     console.log('444');
      //     return this.user + '-' + this.name
      //   }
      // },

8.watch侦听器

Vue自身可以检测对象内部值的改变,但是watch默认不行,得加deep:true

  • 配合本地存储贼好用
import { setItem, getItem } from "@/utils/storage";
export default {
  components: { searchHistory, SearchSuggest, SearchResult },
  name: "Search",
  data() {
    return {
      searchText: "",
      isResultSHow: false, //控制搜索结果的展示
      searchHistories: getItem("SEARCH-HISTORY") || [], //搜索的历史记录
    };
  },
  watch: {
    searchHistories(newVal) {
      setItem("SEARCH-HISTORY", newVal);
    },
  },
<div id="root">
    <h1>今天天气很{{info}}</h1>
    <button @click="change">切换天气</button>
    <hr>
    <h3>a的值是:{{numbers.a}}</h3>
    <button @click="numbers.a++">点我让a+1</button>
  </div>
  <script>

    const vm = new Vue({
      el: '#root',
      data: {
        isHot: true,
        numbers: {
          a: 1,
          b: 1
        }
      },
      computed: {
        info() {
          return this.isHot ? '炎热' : '凉爽';
        }
      },
      methods: {
        change() {
          this.isHot = !this.isHot
          //console.log(vm);
          //写法2
          // this.$watch('isHot', {
          //   deep: true,
          //   handler() {
          //     console.log('f方法2');
          //   }
          // })
        },
      },
      watch: {
        isHot: {
          //immediate: true,初始化时handler调用一下
          handler(news, olds) {
            console.log('isHot被修改了');
            console.log(news, olds);
          }
        },
        numbers: {
          // 监听多级结构中某个属性的变化
          deep: true,
          handler() {
            console.log('对象发生了变化');
          }
        }
      }
    })

watch简写

不需要额外参数只有handler时可以简写比如监听isHot
this指向vm
isHot(news){
  console.log(news);}

watch与computed的区别

比如整个定时器,用watch,computed返回不了
异步计算优先用watch,其他都用computed

关键字搜索案例⭐️

  1. watch实现

    <div id="root">
        <input type="text" v-model="keyword">
        <ul>
          <li v-for="(item,i) in filPersons" :key="item.id">{{item.name+'-'+item.age+'-'+item.sex}}</li>
        </ul>
      </div>
      <script>
        new Vue({
          el: '#root',
          data: {
            keyword: '',
            persons: [
              { id: '1', name: '马冬梅', age: 18, sex: '女' },
              { id: '2', name: '周冬雨', age: 19, sex: '女' },
              { id: '3', name: '周杰伦', age: 20, sex: '男' },
              { id: '4', name: '温兆伦', age: 21, sex: '男' },
            ],
            filPersons: []
          },
          watch: {
            keyword: {
              immediate: true,
              handler(news) {
                this.filPersons = this.persons.filter((value) => {
                  return value.name.indexOf(news) !== -1;
                })
              }
            }
          }
        })
    
  2. computed实现⭐️

     <div id="root">
        <input type="text" v-model="keyword">
        <ul>
          <li v-for="(item,i) in filPersons" :key="item.id">{{item.name+'-'+item.age+'-'+item.sex}}</li>
        </ul>
      </div>
      <script>
        new Vue({
          el: '#root',
          data: {
            keyword: '',
            persons: [
              { id: '1', name: '马冬梅', age: 18, sex: '女' },
              { id: '2', name: '周冬雨', age: 19, sex: '女' },
              { id: '3', name: '周杰伦', age: 20, sex: '男' },
              { id: '4', name: '温兆伦', age: 21, sex: '男' },
            ],
          },
          computed: {
            filPersons() {
              return this.persons.filter((value) => {
                return value.name.indexOf(this.keyword) !== -1;
              })
            }
          }
        })
    

8.class和style

绑定class

<div id="root">
    <!--字符串写法,适用于类名不确定需要动态指定 -->
    <div class="base" :class="main" @click="change">{{name}}</div>
    <!-- 数组写法:适用于要绑定的样式个数不确定,名字也不确定 -->
    <div class="base" :class="arr">{{name}}</div>
    <!-- 对象写法:适用于要绑定样式个数确定,名字也确定,但要动态决定用不用 -->
    <div class="base" :class="obj">哈哈哈哈</div>
    <div class="base" :class="{a:active1,b:active2}">哈哈哈哈</div>
  </div>

  <script>
    const vm = new Vue({
      el: '#root',
      data: {
        name: '刘-总',
        main: 'fun',
        arr: ['a', 'b', 'c'],
        obj: {
          a: false,
          b: false
        },
        active1: true,
        active2: false

      },
      methods: {
        change() {
          var arr = ['fun', 'sad', 'happy'];
          let index = Math.floor(Math.random() * 3);
          this.main = arr[index];
        }

style

直接看文档

9.条件渲染

  1. v-if适合切换频率低的

  2. v-show适合高频率切换的,display的形式

  3. v-if还可以配合template来使用

  4. v-if和v-else-if,v-else一起使用时,中间不能有其他元素打断

  5. 使用v-if时,元素可能无法获取到,而v-show一定可以获取到

  6. 下面的input加key是为了防止input复用,这样里面的内容也会复用不好

  7. <div id="root">
       <span v-if="flag"><label for="username">用户账号</label>
         <input type="text" id="username" placeholder="用户账号" key="acount"></span>
       <span v-else><label for="mails">用户邮箱</label> <input type="text" id="mains" placeholder="用户邮箱" key="mail"></span>
    
       <button @click="info()">切换类型</button>
     </div>
     <script>
       new Vue({
         el: '#root',
         data: {
           flag: true
         },
         methods: {
           info() {
             this.flag = !this.flag
           },
         }
       })
     </script>
       </body>
    
8. ​

# 10.v-for列表渲染

> 如果不写key,则会默认补key为index,最好以唯一标识为key
>
> index如果逆序添加也是会出问题的,最好是id

​```js
<!-- 遍历数组 -->
    <h2>人员列表</h2>
    <!-- <ul>
      <li v-for="item of persons" :key="item.id">{{item.name+'-'+item.age}}</li>
    </ul> -->
    <ol>
      <!-- 可以有两个参数,第一个参数为值,第2个参数为索引 -->
      <li v-for="(item,index) in persons" :key="item.id">{{item.name+'-'+index}}</li>
    </ol>
    <!-- 遍历对象 -->
    <h2>车辆信息</h2>
    <ul>
      <li v-for="(value,key) in car" :key="key">
        {{value+': '+key}}
      </li>
    </ul>
  </div>
  <script>
    new Vue({
      el: '#root',
      data: {
        persons: [
          { id: '1', name: '张三', age: 18 },
          { id: '2', name: '李四', age: 19 },
          { id: '3', name: '王五', age: 20 },
        ],
        car: {
          name: '奥迪A8',
          price: '70万',
          color: '蓝色'
        }

关键字搜索案例⭐️

# <body>
  <div id="root">
    <input type="text" v-model="keyword">
    <button @click="sortType=2">年龄升序</button>
    <button @click="sortType=1">年龄降序</button>
    <button @click="sortType=0">默认排序</button>
    <ul>
      <li v-for="(item,i) in filPersons" :key="item.id">{{item.name+'-'+item.age+'-'+item.sex}}</li>
    </ul>
  </div>
  <script>
    new Vue({
      el: '#root',
      data: {
        keyword: '',
        sortType: 0,//0原顺序 1降序 2升序
        persons: [
          { id: '1', name: '马冬梅', age: 62, sex: '女' },
          { id: '2', name: '周冬雨', age: 29, sex: '女' },
          { id: '3', name: '周杰伦', age: 55, sex: '男' },
          { id: '4', name: '温兆伦', age: 41, sex: '男' },
        ],
        sortType: 0,
      },
      computed: {
        filPersons() {
          const arr = this.persons.filter((val, index) => {
            return val.name.indexOf(this.keyword) !== -1;
          })
          if (this.sortType) {
            arr.sort((a, b) => {
              return this.sortType === 1 ? b.age - a.age : a.age - b.age;
            })
          }
          return arr
        }
      }
    })

11.Vue监测数据⭐️

这样加Vue才会监测到,才是响应式的,且不能直接给data添加数据,会报错,下面代码可以配合文档看

对象Vue.set

 body>
  <div id="root">
    <h2>{{ta}}</h2>
    <h2>姓名:{{student.name}}</h2>
    <h2>年龄:{{student.age}}</h2>
    <!-- 如果值为未定义undefined但它是有依赖student属性的,那么它既不会报错也不会展示 -->
    <h2 v-if="student.sex">性别:{{student.sex}}</h2>
    <button @click="add">添加一个性别属性,默认值为男</button>
  </div>
  <script>
    const vm = new Vue({
      el: '#root',
      data: {
        student: {
          name: 'tom',
          age: 13
        },
      },
      methods: {
        add() {
          /* 不能直接给data添加数据,会报错
          /this.ta = '666'
           这样Vue监测不到,不是响应式的
          this.student.sex = 'ss1'*/
          Vue.set(this.student, 'sex', '男')
            this.$delete(this.student,'name')
        }
      },
    })

数组Vue.set或者原生7个方法

<body>
  <div id="root">
    <ol>
      <li v-for="(val,i) in hobby">{{val}}</li>
    </ol>
    <button @click="add">Vue.set修改数组属性</button>
    <button @click="update">利用其他方法</button>
  </div>
  <script>
    const vm = new Vue({
      el: '#root',
      data: {
        hobby: ['抽烟', '喝酒', '打豆豆']
      },
      methods: {
        add() {
          Vue.set(this.hobby, 2, '赌博')
        },
        update() {
          // push(),pop(),shift(),unshift(),splice(),sort(),reverse()
          this.hobby.push('炸街')
        }
      },
    })
  </script>
</body>

12.收集表单数据

还有3个修饰符trim,lazy,number,可以结合文档使用

 <div id="root">
    <form action="" style="background-color: #ccc;">
      账号:<input type="text" v-model="account"><br>
      密码:<input type="password" v-model="password"><br>
      年龄:<input type="number" v-model.number="age"><br>
      性别:男 <input type="radio" v-model="picked" value="male"><input type="radio" v-model="picked" value="famale"
        name="sex" id=""><br>
      爱好:抽烟 <input type="checkbox" name="hoddy" v-model="checkedNames" value="抽烟">
      喝酒 <input type="checkbox" name="hoddy" v-model="checkedNames" value="喝酒">
      烫头 <input type="checkbox" name="hoddy" v-model="checkedNames" value="烫头"> <br>
      所属校区:<select v-model="selected">
        <option value="">请选择校区</option>
        <option value="beijing">北京</option>
        <option value="shanghai">上海</option>
        <option value="shenzheng">深圳</option>
        <option value="wuhan">武汉</option>
      </select><br><br>
      其他信息: <textarea v-model="message" cols="30" rows="10"></textarea><br><br>
      <input type="checkbox" name="auto" v-model="check"> 阅读并接受<a href="http://www.atguigu.com">《用户协议》</a><br>
      <input type="submit" value="提交" @click.prevent="demo">
    </form>
  </div>
  <script>
    new Vue({
      el: '#root',
      data: {
        account: '',
        password: '',
        picked: 'male',
        checkedNames: [],
        selected: '',
        message: '',
        check: '',
        age: ''
      },
      methods: {
        demo() {
          //不能这样拿,会报错
          //console.log(this.data);
          console.log(this._data);
          console.log(JSON.stringify(this._data));
        }
      },
    })
  </script>

13.过滤器

过滤器只可以用在两个地方:双花括号插值和 v-bind 表达式

前端第3方库

 <script src="../vue.js"></script>
  <script src="../dayjs.min.js"></script>
</head>

<body>
  <div id="root">
    <h2>显示格式化后的时间</h2>
    <!-- 通过计算属性实现 -->
    <h3>现在是:{{fmtTime}}</h3>
    <!-- 通过methods方法实现 -->
    <h3>现在是:{{getFmtTime()}}</h3>
    <!-- 过滤器实现 -->
    <h3>现在是:{{time | timeFmt}}</h3>
    <!-- 过滤器传参,第一个参数就是time,这是不会变的 -->
    <h3>现在是:{{time | timeFmt('YYYY-MM-DD')}}</h3>
    <!-- 过滤器是可以叠加的 -->
    <h3>现在是:{{time | timeFmt('YYYY-MM-DD') | mySlice}}</h3>
  </div>
  <div id="main">
    <h3 :x="msg |mySlice">666</h3>
  </div>
  <script>
    // 全局过滤器
    Vue.filter('mySlice', function (value) {
      return value.slice(0, 4)
    })
    new Vue({
      el: '#root',
      data: {
        time: Date.now()
      },
      computed: {
        fmtTime() {
          return dayjs(this.time).format('YYYY-MM-DD HH:mm:ss');
        }
      },
      methods: {
        getFmtTime() {
          return dayjs(this.time).format('YYYY年MM月DD日 HH:mm:ss');
        }
      },
      //局部过滤器
      filters: {
        timeFmt(value, str = 'YYYY-MM-DD HH:mm:ss') {
          return dayjs(value).format(str);
        },
        // mySlice(value) {
        //   return value.slice(0, 4)
        // }
      }
    })
    new Vue({
      el: '#main',
      data: {
        msg: '你好,尚硅谷'
      }
    })

14.指令

v-html,text

 <div id="root">
    <!-- 会覆盖原内容,且不会解析html -->
    <h2 v-text="name">欢迎大家</h2>
    <h1>{{name}}</h1>
    <h2 v-text="str"></h2>
    //与v-text区别是可以识别html
    <h2 v-html="str"></h2>
  </div>
  <script>
    new Vue({
      el: '#root',
      data: {
        name: '大白兔',
        str: '<h1>你好呀!</h1>'
      }
    })

v-pre,once

<div id="root">
    <h2>{{name}}</h2>
    <!-- 只渲染一次,不会随着数据的改变而改变 -->
    <h2 v-once>{{name}}</h2>
  </div>
  <script>
    const vm = new Vue({
      el: '#root',
      data: {
        name: '大白兔',
        str: '<h1>你好呀!</h1>'
      }
    })

v-cloak

<style>
  [v-cloak] {
    display: none;
  }
</style>

<body>
  <!-- Vue解析之前div中有一个属性,v-cloak -->
  <div id="root" v-cloak>
    <!-- v-pre跳过这个元素和子元素的编译过程,不会识别模板语法是属性 -->
    <h2>Vue其实很简单</h2>
    <h2>当前的n值是:{{n}}</h2>
  </div>
  <script>
    setTimeout(function () {
      new Vue({
        el: '#root',
        data: {
          n: 0,
        }
      })
    }, 2000)

自定义指令

  1. 指令定义时不加v-,但使用时要加v-;

  2. 指令名如果是多个单词,要使用kebab-case命名方式,不要用camelCase命名。且定义的时后哟要‘kebab-case包起来

  3. bind():指令与元素成功绑定时,inserted():指令所指元素被插入页面时,update()指令所在模板被重新解析时

  4. <div id="root">
        <h2>当前的n值是: <span v-text="n"></span></h2>
        <h2>放大10倍后的n值是: <span v-big="n"></span></h2>
        <button @click="n++">点我n+1</button>
        <hr>
        <input type="text" v-fbind:value="n">
      </div>
      <script>
        /*
     1.指令定义时不加v-,但使用时要加v-;
     2.指令名如果是多个单词,要使用kebab-case命名方式,不要用camelCase命名。
     //定义全局指令
       Vue.directive('fbind',{
        //指令与元素成功绑定时(一上来)
        bind(element,binding){
          element.value = binding.value
        },
        //指令所在元素被插入页面时
        inserted(element,binding){
          element.focus()
        },
        //指令所在的模板被重新解析时
        update(element,binding){
          element.value = binding.value
        }
      }) 
        vue.directives('big', function (element, binding) {
        console.log('big', this) //注意此处的this是window
        // console.log('big')
        element.innerText = binding.value * 10
      })
        */
        new Vue({
          el: '#root',
          data: {
            n: 1
          },
          directives: {
            // 这是简写,只能实现部分功能
            // 刚绑定时或指令所在模板被重新解析时
            big(element, binding) {
              element.innerText = binding.value * 10
            },
            fbind: {
              //指令与元素成功绑定时(一上来)
              bind(element, binding) {
                element.value = binding.value
              },
              //指令所在元素被插入页面时
              inserted(element, binding) {
                // 没有插入的话,focus是无效的
                element.focus()
              },
              //指令所在的模板被重新解析时
              update(element, binding) {
                element.value = binding.value
              }
            }
          }
        })
    

15.生命周期⭐️

  • 创建期间的生命周期函数
    • beforeCreate:实例刚在内存中创建出来,此时还没有初始化data和methods属性
    • created:实例已经在内存中创建OK,此时data和methods已经创建ok,此时还没有开始编译模板
    • beforeMount: 此时已经完成了模板的编译,但还没有挂载到页面中
    • mounted:此时,已经将编译好的模板,挂载到了页面指定的容器中显示
  • 运行期间的生命周期函数:
    • beforeUpdate:状态更新之前执行此函数,此时data中的状态值是最新的,但是界面上显示的数据还是旧的,因为此时还没有重新开始渲染Dom节点
      • 这里可以访问到数据和调用方法,但是对数据的更改不会再更新了
    • updated:实例更新完毕后调用此函数,此时data中的状态值和界面上显示的数据都已经完成了更新,界面已经被重新1渲染好了
  • 销毁期间的生命周期函数:
    • beforeDestory:实例销毁之前调用,在这一步,实例仍完全可用,这里可以访问到数据和调用方法,但是对数据的更改不会再更新了
    • destroyed:Vue实例销毁后调用,调用后,Vue实例指示的所有东西都会解除绑定,所有的事件监听器都会被移除,所有的子实例也会被销毁

16.非单文件组件

组件:先创建,后注册,然后使用-------注意:组件里面的data要写成函数的形式

局部组件注册使用

<div id="root">
    <h2>{{msg}}</h2>
    <hr>
    <!-- 3.编写组件标签 -->
    <school></school>
    <!-- <xuexiao></xuexiao> -->
    <hr>
    <!-- 组件复用,因为data写的函数式,改其中的值不影响另一个组件 -->
    <student></student>
    <student></student>
    <!-- <xuesheng></xuesheng> -->
  </div>
  <div id="main">

  </div>
  <script>
    // 创建school组件
    const school = Vue.extend({
      data() {
        return {
          schoolName: '尚硅谷',
          address: '北京昌平',
        }
      },
      template: `
      <div>
         <h2>学校名:{{address}}</h2>
         <h2>学校地址:{{schoolName}}</h2>
         <button @click="showName">点我提示学校名</button>
     </div>
     `,
      methods: {
        showName() {
          alert(this.schoolName)
        }
      },
    })
    // 1.创建学生组件
    const student = Vue.extend({
      template: `
        <div> 
          <h2>学生姓名:{{studentName}}</h2>
          <h2>学生年龄:{{age}}</h2>
        </div>
      `,
      // 组件里面的data必须写成函数的形式
      data() {
        return {
          studentName: '张三',
          age: 18
        }
      }
    })

    new Vue({
      el: '#root',
      data: {
        msg: '你好啊'
      },
      // 2注册组件(局部注册)
      components: {
        school,
        student
        // xuexiao: school,
        // xuesheng: student
      }
    })

全局组件

<body>
  <div id="root">
    <hello></hello>
  </div>
  <hr>
  <div id="main">
    <hello></hello>
  </div>
  <script>
    const qj = Vue.extend({
      data() {
        return {
          name: 666
        }
      },
      template: `<h2>{{name}}</h2>`
    })
    Vue.component('hello', qj)
    new Vue({
      el: '#root',

    })
    new Vue({
      el: '#main'
    })

注意事项

  1. 单文件组件名应该要么始终是单词大写开头 (PascalCase),要么始终是横线连接 (kebab-case)。
  2. 自闭合组件不能写在Dom模板(html里)
  3. 对于绝大多数项目来说,在单文件组件和字符串模板中组件名应该总是 PascalCase 的——但是在 DOM 模板中总是 kebab-case 的。
     1.关于组件名
	一个单词组成:
			第一种写法(首字母小写):school
			第二种写法(首字母大写):School								
	多个单词组成:
			第一种写法(kebab-case命名)'my-school'								
			第二种写法(CamelCase命名):MySchool (需要Vue脚手架支持)								
	备注:
			(1).组件名尽可能回避HTML中已有的元素名称,例如:h2、H2都不行。							
			(2).可以使用name配置项指定组件在开发者工具中呈现的名字。							

	2.关于组件标签:
		    第一种写法:<school></school>
			第二种写法:<school/>
			备注:不用使用脚手架时,<school/>会导致后续组件不能渲染。
  1. 自闭合组件不能写在Dom模板(html里)
  2. 对于绝大多数项目来说,在单文件组件和字符串模板中组件名应该总是 PascalCase 的——但是在 DOM 模板中总是 kebab-case 的。
  3. template里面的内容一定要用一个根元素包起来,比如拿div做根元素把他们包起来
    template:
           `
         <div>
           <h2>学校名称:{{schoolName}}</h2>
           <h2>学校地址:{{address}}</h2>
         </div>
         `
  1. 组件标签名如果定义时设置了name属性则按最终按name的来

组件的嵌套

vm直接管理的app跟组件

 <div id="root">
    <app></app>
  </div>
  <script>
    // 定义学生1组件
    const student = Vue.extend({
      name: 'student',
      data() {
        return {
          studentName: '尚硅谷',
          age: '18'
        }
      },
      template:
        `
      <div>
        <h2>学生名:{{studentName}}</h2>
        <h2>学生年龄:{{age}}</h2>
      </div>
      `
    })
    // 定义学生1组件
    const hello = Vue.extend({
      data() {
        return {
          msg: '欢迎来到尚硅谷学习'
        }
      },
      template:
        `
        <h1>{{msg}}</h1>
      `
    })
    // 定义school组件包裹student组件
    const school = Vue.extend({
      name: 'school',
      data() {
        return {
          schoolName: '尚硅谷',
          address: '北京'
        }
      },
      template:
        `
      <div>
        <h2>学校名称:{{schoolName}}</h2>
        <h2>学校地址:{{address}}</h2>
        <student></student>
      </div>
      `,
      components: {
        student
      }
    })
    // 定义根组件App,
    const app = Vue.extend({
      name: 'app',
      template:
        `
        <div><school></school>
    <hello></hello></div>
  `,
      components: {
        school,
        hello
      }
    })
    new Vue({
      el: '#root',
      components: {
        app
      }
    })
  </script>

VueComponent

1.school组件本质是一个名为VueComponent的构造函数,且不是程序员定义的,是Vue.extend生成的。

2.我们只需要写<school/><school></school>,Vue解析时会帮我们创建school组件的实例对象,即Vue帮我们执行的:new VueComponent(options)3.特别注意:每次调用Vue.extend,返回的都是一个全新的VueComponent!!!!

4.关于this指向:
(1).组件配置中:data函数、methods中的函数、watch中的函数、computed中的函数 它们的this均是【VueComponent实例对象】。
(2).new Vue(options)配置中:data函数、methods中的函数、watch中的函数、computed中的函数 它们的this均是【Vue实例对象】。

5.VueComponent的实例对象,以后简称vc(也可称之为:组件实例对象)。Vue的实例对象,以后简称vm。

==VueComponent.prototype.proto=============Vue.prototype

17.Cli脚手架

自带express,可以直接用

cli创建项目中main.js的render函数

/* 
	该文件是整个项目的入口文件
*/
//引入Vue,没有写明具体引入vue的哪个东西,默认引入vue.runtime.xxx.js是运行版的Vue,只包含:核心功能;没有模板解析器。
import Vue from 'vue'
//引入App组件,它是所有组件的父组件
import App from './App.vue'
//关闭vue的生产提示
Vue.config.productionTip = false

/* 
	关于不同版本的Vue:
	
		1.vue.js与vue.runtime.xxx.js的区别:
				(1).vue.js是完整版的Vue,包含:核心功能+模板解析器。
				(2).vue.runtime.xxx.js是运行版的Vue,只包含:核心功能;没有模板解析器。

		2.因为vue.runtime.xxx.js没有模板解析器,所以不能使用template配置项,需要使用
			render函数接收到的createElement函数去指定具体内容。
*/

//创建Vue实例对象---vm
new Vue({
	el:'#app',
	//render函数完成了这个功能:将App组件放入容器中
  render: h => h(App),
	// render:q=> q('h1','你好啊')

	// template:`<h1>你好啊</h1>`,
	// components:{App},
})

修改默认配置

Vue.config.js可以修改默认配置

18.ref属性

可以拿到元素或者组件实例

div>
    <h1 v-text="msg" ref="title"></h1>
    <button @click="showDom" ref="btn">点我输出上方的Dom元素</button>
    <School ref="sch"></School>
  </div>
</template>

<script>
import School from "./components/School.vue";
export default {
  name: "App",
  components: { School },
  data() {
    return {
      msg: "欢迎学习Vue",
    };
  },
  methods: {
    showDom() {
      console.log(this.$refs.btn);
      console.log(this.$refs.title);
      console.log(this.$refs.sch);
    },
  },
};

19.props属性父传子⭐️

  1. 父组件App.vue传值,多个单词用camelCase小驼峰命名法,不写:默认为传字符串

    <template>
      <div>
        <Student name="李四" sex="女" :age="18"></Student>
      </div>
    </template>
    
    <script>
    import Student from "./components/Student.vue";
    
    export default {
      name: "App",
      components: { Student },
    };
    </script>
    
    <style>
    </style>
    
  2. 子组件接收值,porps是只读的,接收的值不能直接修改,需要借助变量转接,或者可以改数组对象内部的值,可以深改不能浅改(意思就是不能之间赋值,但是可以改里面的数据)

    <template>
      <div>
        <h1>{{ msg }}</h1>
        <h2>学生姓名:{{ name }}</h2>
        <h2>学生性别:{{ sex }}</h2>
        <h2>学生年龄:{{ myAge + 1 }}</h2>
        <button @click="updateAge">修改年龄+1</button>
      </div>
    </template>
    
    <script>
    export default {
      name: "Student",
      data() {
        return {
          msg: "我是一个尚硅谷的学生",
          // 传过来的值我们直接修改会报错,但是我们可以借助变量修改
          myAge: this.age,
        };
      },
      methods: {
        updateAge() {
          this.myAge++;
        },
      },
      //1.简单接收
      props: ["name", "sex", "age"],
      //2.接收的同时对数据进行类型限制
      // props: {
      //   name: String,
      //   age: Number,
      //   sex: String,
      // },3.复杂配置
      // props: {
      //   name: {
      //     type: String,
      //     required: true, //name是必要的
      //   },
      //   age: {
      //     type: Number,
      //     default: 99, //默认值
      //   },
      //   sex: {
      //     type:[Number,String],
      //     required: true,
      //   },
      // },
      //
    };
    

20.mixin

可以把多个组件共用的配置提取出来到 xxx.js中,其他组件可以引入使用,最好不要全局引入

  1. mixin.js

    export const hunhe = {
      methods: {
        showName() {
          alert(this.name);
        },
      },
      mounted() {
        console.log('你好啊');
      },
    }
    export const hunhe2 = {
      data() {
        return {
          x: 100,
          y: 200
        }
      }
    }
    
  2. 全局引入在main.js中引入,慎用,它会默认影响vm和所有vc

    import Vue from 'vue'
    import App from './App.vue'
    import { hunhe, hunhe2 } from './mixin'
    Vue.mixin(hunhe, hunhe2)
    new Vue({
      el: '#app',
      render: h => h(App)
    })
    
  3. 局部引入

    <template>
      <div>
        <h2 @click="showName">学生姓名:{{ name }}</h2>
        <h2>学生性别:{{ sex }}</h2>
        <h2>{{ x + y }}</h2>
      </div>
    </template>
    
    <script>
    import { hunhe, hunhe2 } from "../mixin";
    export default {
      name: "Student",
      data() {
        return {
          name: "刘总",
          sex: "男",
        };
      },
      mixins: [hunhe, hunhe2],
    };
    

21.插件

  1. 定义一个插件plugins.js,里面的功能vm和所有vc可以挑着用

  2. 本质是包含install方法的一个对象,第一个参数默认为Vue,第2个以后的参数是插件使用者传递的数据

    export default {
    	install(Vue, x, y, z) {
    		console.log(x, y, z)
    		//全局过滤器
    		Vue.filter('mySlice', function (value) {
    			return value.slice(0, 4)
    		})
    
    		//定义全局指令
    		Vue.directive('fbind', {
    			//指令与元素成功绑定时(一上来)
    			bind(element, binding) {
    				element.value = binding.value
    			},
    			//指令所在元素被插入页面时
    			inserted(element, binding) {
    				element.focus()
    			},
    			//指令所在的模板被重新解析时
    			update(element, binding) {
    				element.value = binding.value
    			}
    		})
    
    		//定义混入
    		Vue.mixin({
    			data() {
    				return {
    					x: 100,
    					y: 200
    				}
    			},
    		})
    
    		//给Vue原型上添加一个方法(vm和vc就都能用了)
    		Vue.prototype.hello = () => { alert('你好啊') }
    	}
    }
    
  3. main.js引入

    import Vue from 'vue'
    import App from './App.vue'
    // 引入插件
    import plugins from './plugins'
    Vue.use(plugins, 1, 2, 3)
    new Vue({
      el: '#app',
      render: h => h(App)
    })
    
  4. 其他组件可以直接使用

    <template>
      <div>
        <h2>学校名称:{{ name | mySlice }}</h2>
        <h2>学校地址:{{ address }}</h2>
        <input type="text" v-fbind:value="name" />
      </div>
    </template>
    
    

22.scoped样式

让样式在局部生效,防止冲突

23.自动生成id插件

npm i nanoid 
import { nanoid } from "nanoid";
export default {

  methods: {
    add(e) {
      // 校验数据
      if (!this.title.trim()) return alert("输入不能为空");
      // 将用户的输入包装成一个todo对象
      const todoObj = { id: nanoid(), title: e.target.value, done: false };
      this.addTodo(todoObj);
      this.title = "";

24.自定义事件子传父

如果简单的话直接写模板上,$event就是我们所传递的那个参数

this.$emit(“updata_followed”, !this.is_followed);

@updata_followed=“articles.is_followed = $event”

  1. App.vue

    <template>
      <div id="app">
        <h1>{{ msg }}</h1>
        <!-- 通过父组件给子组件传递函数类型的props实现:子给父传递数据 -->
        <School :getSchoolName="getSchoolName"></School>
        <!-- 通过父组件给子组件绑定一个自定义事件实现:子传父 -->
        <Student @atguigu.once="getStudentName"></Student>
        <!-- <Student ref="student"></Student> -->
      </div>
    </template>
    
    <script>
    import School from "./components/School.vue";
    import Student from "./components/Student.vue";
    export default {
      name: "App",
      components: {
        School,
        Student,
      },
      data() {
        return {
          msg: "你好啊!",
        };
      },
      methods: {
        getSchoolName(name) {
          console.log("App收到了学校名", name);
        },
        getStudentName(name) {
          console.log("App收到了学生们:", name);
        },
      },
      // mounted() {
      //   this.$refs.student.$on("atguigu", this.getStudentName);
      // },
    };
    
  2. student.vue

    <<template>
      <div class="student">
        <h2>学生姓名:{{ name }}</h2>
        <h2>学生年龄:{{ age }}</h2>
        <button @click="sendStudentName">把学生名给App</button>
        <button @click="unbind">解绑atguigu事件</button>
        <button @click="dead">注销组件</button>
      </div>
    </template>
    <script>
    export default {
      name: "Student",
      data() {
        return {
          name: "张三",
          age: 18,
        };
      },
      methods: {
        sendStudentName() {
          // 触发Student组件实例身上的atguigu事件
          this.$emit("atguigu", this.name);
          this.$emit("demo");
        },
        unbind() {
          this.$off("atguigu"); //解绑一个自定义事件
          this.$off(["atguigu", "demo"]); //解绑多个自定义事件
          this.$off(); //解绑所有的自定义事件
        },
        dead() {
          this.$destroy();
        },
      },
    };
    </script>
    <style lang="less" scoped>
    .student {
      background-color: pink;
      padding: 5px;
      margin-top: 30px;
    }
    </style>
    
    

25.事件总线

可以实现各组件共享数据,任意组件间通信

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-aBUFThc1-1669432222701)(D:新的开始mdVueimage事件总线.jpg)]

main.js
import Vue from 'vue'
import App from './App.vue'

Vue.config.productionTip = false
Vue.prototype.$bus = new Vue()
const app = new Vue({
  render: h => h(App),
  // beforeCreate() {
  //   Vue.prototype.$bus = this //安装全局事件总线
  //   console.log(this);
  // },
}).$mount('#app')
console.log(app === Vue);//false
console.log(app);
console.log(Vue);

全局要用this.$bus.$on
接收的那个组件销毁前要这样
 name: "School",
  data() {
    return {
      schoolName: "尚硅谷",
      address: "北京昌平",
    };
  },
  mounted() {
    this.$bus.$on("share", (val) => {
      console.log("我是school组件,拿到了student组件传过来的数据" + val);
    });
  },
  // 要记得销毁前解绑事件
  beforeDestroy() {
    this.$bus.$off("share");
  },
};
</script>
 name: "Student",
  data() {
    return {
      name: "张三",
      age: 18,
    };
  },
  methods: {
    sendStudentName() {
      this.$bus.$emit("share", this.name);
    },
  },
};

26.消息订阅与组件通信

功能与事件总线类似,且各个框架都能用

利用pubsub-js第3方库

先引入库 npm i pubsub-js

  1. 触发事件方(发送方)
<template>
	<div class="student">
		<h2>学生姓名:{{name}}</h2>
		<h2>学生性别:{{sex}}</h2>
		<button @click="sendStudentName">把学生名给School组件</button>
	</div>
</template>

<script>
	import pubsub from 'pubsub-js'
	export default {
		name:'Student',
		data() {
			return {
				name:'张三',
				sex:'男',
			}
		},
		methods: {
			sendStudentName(){
				// this.$bus.$emit('hello',this.name)
				pubsub.publish('hello',666)
			}
		},
	}
  1. 绑定方(接收方)

    template>
    	<div class="school">
    		<h2>学校名称:{{name}}</h2>
    		<h2>学校地址:{{address}}</h2>
    	</div>
    </template>
    
    <script>
    	import pubsub from 'pubsub-js'
    	export default {
    		name:'School',
    		data() {
    			return {
    				name:'尚硅谷',
    				address:'北京',
    			}
    		},
    		mounted() {
    			// console.log('School',this)
    			/* this.$bus.$on('hello',(data)=>{
    				console.log('我是School组件,收到了数据',data)
    			}) */
                //第一个形参默认为事件名
    			this.pubId = pubsub.subscribe('hello',(msgName,data)=>{
    				console.log(this)
    				// console.log('有人发布了hello消息,hello消息的回调执行了',msgName,data)
    			})
    		},
    		beforeDestroy() {
    			// this.$bus.$off('hello')
    			pubsub.unsubscribe(this.pubId)
    		},
    	}
    </script>
    
    

27.this.$nextTick()

可以保证页面结构一定是有的,经常和很多插件一起使用(都需要DOM存在了)

	handleEdit(todo){
                //要走完这些才会渲染到模板上,而走this.$refs.inputTitle.focus()的时候input还没有来到页面上,所以要用nextTick函数或者定时器
				if(todo.hasOwnProperty('isEdit')){
					todo.isEdit = true
				}else{
					// console.log('@')
					this.$set(todo,'isEdit',true)
				}
				this.$nextTick(function(){
                    
					this.$refs.inputTitle.focus()
				})
			},

28.axios

axios直接发起get和post请求

<button id="btnGET">GET</button>
  <button id="btnPOST">POST</button>

  <script src="./lib/axios.js"></script>
  <script>
    document.querySelector('#btnGET').addEventListener('click', async function () {
      /* axios.get('url地址', {
        // GET 参数
        params: {}
      }) */

      const { data: res } = await axios.get('http://www.liulongbin.top:3006/api/getbooks', {
        params: { id: 1 }
      })
      console.log(res)
    })

    document.querySelector('#btnPOST').addEventListener('click', async function () {
      // axios.post('url', { /* POST 请求体数据 */ })
      const { data: res } = await axios.post('http://www.liulongbin.top:3006/api/post', { name: 'zs', gender: '女' })
      console.log(res)
    })
  </script>
</body>

axios封装默认配置

import axios from 'axios'
const request = axios.create({
  // 指定请求的路径
  baseURL: 'https://www.escook.cn'
})

export default request
import api from "@/utils/request";
export default function request(_page, _list) {
  return api.get('/articles', {
    // 请求参数
    params: {
      _page,
      _list
    }
  })
}
------------------------------------------------------
import getArticle from "../../api/art.js";
 methods: {
    async init(update) {
      const { data: res } = await getArticle(this.page, this.list);

拦截器

import axios from "axios";
// axios的2次封装
// 引入进度条
import nprogress from 'nprogress';
// 引入进度条样式
import 'nprogress/nprogress.css'
console.log(nprogress);
const requests = axios.create({
  // 会自动拼接/api
  baseURL: '/api',
  // timeout: 5000
})
//2、配置请求拦截器
requests.interceptors.request.use(config => {
  //config内主要是对请求头Header配置
  //比如添加token

  //开启进度条
  nprogress.start();
  return config;
})
//3、配置相应拦截器
requests.interceptors.response.use((res) => {
  //成功的回调函数

  //响应成功,关闭进度条
  nprogress.done()
  return res.data;
}, (error) => {
  //失败的回调函数
  console.log("响应失败" + error)
  return Promise.reject(new Error('fail'))
})
//4、对外暴露
export default requests

29.前端跨域解决方案配置代理

如果后端API 接口没有开启CORS 跨域资源共享,接口则无法请求成功

通过proxy跨域代理解决接口的跨域问题

仅在开发调式阶段生效,,项目上线发布时,仍要后端开启cors跨域资源共享

module.exports = {
  devServer: {
    proxy: {
      '/api': {// 匹配所有以 '/api1'开头的请求路径
        target: 'http://gmall-h5-api.atguigu.cn',// 代理目标的基础路径
        changeOrigin: true,
        // pathRewrite: { '^/api': '' }
      },
    }
  }
}

Vue封装的过度与动画

  1. 作用:在插入、更新或移除 DOM元素时,在合适的时候给元素添加样式类名。

  2. 写法:

    1. 准备好样式:

      • 元素进入的样式:
        1. v-enter:进入的起点
        2. v-enter-active:进入过程中
        3. v-enter-to:进入的终点
      • 元素离开的样式:
        1. v-leave:离开的起点
        2. v-leave-active:离开过程中
        3. v-leave-to:离开的终点
    2. 使用<transition>包裹要过度的元素,并配置name属性:

      <transition name="hello">
      	<h1 v-show="isShow">你好啊!</h1>
      </transition>
      
    3. 备注:若有多个元素需要过度,则需要使用:<transition-group>,且每个元素都要指定key值。

vue脚手架配置代理

方法一

​ 在vue.config.js中添加如下配置:

devServer:{
  proxy:"http://localhost:5000"
}

说明:

  1. 优点:配置简单,请求资源时直接发给前端(8080)即可。
  2. 缺点:不能配置多个代理,不能灵活的控制请求是否走代理。
  3. 工作方式:若按照上述配置代理,当请求了前端不存在的资源时,那么该请求会转发给服务器 (优先匹配前端资源)

方法二

​ 编写vue.config.js配置具体代理规则:

module.exports = {
	devServer: {
      proxy: {
      '/api1': {// 匹配所有以 '/api1'开头的请求路径
        target: 'http://localhost:5000',// 代理目标的基础路径
        changeOrigin: true,
        pathRewrite: {'^/api1': ''}
      },
      '/api2': {// 匹配所有以 '/api2'开头的请求路径
        target: 'http://localhost:5001',// 代理目标的基础路径
        changeOrigin: true,
        pathRewrite: {'^/api2': ''}
      }
    }
  }
}
/*
   changeOrigin设置为true时,服务器收到的请求头中的host为:localhost:5000
   changeOrigin设置为false时,服务器收到的请求头中的host为:localhost:8080
   changeOrigin默认值为true
*/

说明:

  1. 优点:可以配置多个代理,且可以灵活的控制请求是否走代理。
  2. 缺点:配置略微繁琐,请求资源时必须加前缀。

实战

接口路径:http://gmall-h5-api.atguigu.cn/api/product/getBaseCategoryList
------------------------------------------------------------------------
  const requests = axios.create({
  // 发请求时候,路径当中会出现api
  baseURL: '/api',
  // timeout: 5000
})
------------------------------------------------------------------
module.exports = {
  devServer: {
    proxy: {
      '/api': {// 匹配所有以 '/api1'开头的请求路径
        target: 'http://gmall-h5-api.atguigu.cn',// 代理目标的基础路径
        changeOrigin: true,
        // pathRewrite: { '^/api': '' }
      },
    }
  }
}
----------------------------------------------------------------------
// 当前这个模块,API进行统一管理
import requests from "./request";
import mockRequests from './mockAjax'
export const reqCategoryList = () => {
  return requests({ url: 'product/getBaseCategoryList', method: 'get' })
}

最后

以上就是贤惠泥猴桃为你收集整理的Vue2知识点总结及学习心得1.模板语法2.el和data两种写法3.数据绑定4.MVVM模型5.Object.defineProperty6.事件处理⭐️7.method与computed的区别8.watch侦听器8.class和style9.条件渲染11.Vue监测数据⭐️12.收集表单数据13.过滤器14.指令15.生命周期⭐️16.非单文件组件17.Cli脚手架18.ref属性19.props属性父传子⭐️20.mixin21.插件22.scoped样式23.自动生成id插件24.自定义的全部内容,希望文章能够帮你解决Vue2知识点总结及学习心得1.模板语法2.el和data两种写法3.数据绑定4.MVVM模型5.Object.defineProperty6.事件处理⭐️7.method与computed的区别8.watch侦听器8.class和style9.条件渲染11.Vue监测数据⭐️12.收集表单数据13.过滤器14.指令15.生命周期⭐️16.非单文件组件17.Cli脚手架18.ref属性19.props属性父传子⭐️20.mixin21.插件22.scoped样式23.自动生成id插件24.自定义所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(67)

评论列表共有 0 条评论

立即
投稿
返回
顶部