vue学习过程记录(一),笔记记录

322 阅读7分钟

1、插值表达式,{{ }}

可以插数据,计算式,方法函数fn(return),布尔值

<body>
    <!-- 插值表达式 
    1、支持表达式,不支持语句 if for 
    2、不能直接在属性值中插值使用 
    3、响应式,数据变化,视图自动更新
    -->
    <div id="app">
        {{msg}}
        <p>{{count}}</p>
        <p>{{nickname}}</p>
        <div>{{nickname.toUpperCase()}}</div>
        <div>{{nickname + '你好'}}</div>
        <p>{{age >= 18 ? '成年' : '未成年'}}</p>
        <div>{{friend.name + friend.desc}}</div>
    </div>
    <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
    <script>
        const app = new Vue({
            el: '#app',//指定vue管理的选择器
            data: {
                msg: 'hello 传智播客',
                count: 666,
                nickname: 'tony',
                age: 19,
                friend: {
                    name: 'pink',
                    desc: '热爱学习vue'
                }
            }
        })
    </script>
</body>

2、vue指令v-前缀,官网文档v-指令。v-XX="内联语句,计算,比较,函数名等"

<body>
  <!-- v-html功能相当于innerhtml,用来解析H5标签 -->
  <!-- v-show是通过控制css的display: none;来控制元素的显示和隐藏,用于频繁切换的场景 -->
  <!-- v-if是通过渲染来控制,用于不平凡的切换 -->
  <!-- v-on:事件绑定,v-on:可以替换为@。如@click -->
  <!-- v-bind: = :用于标签属性的动态传参,可以简写为:加属性名,如url等 -->
  <!-- v-for="(item,index)in 数组名" 遍历数组。 :key是用来给列表一个唯一标识正确排序,防止错误编码 -->
  <!-- v-model双向数据绑定,视图和数据双向绑定 -->
  <div id="app">
    <div v-html="msg"></div>
    <div v-show="flag" class="box">我是v-show控制的盒子</div>
    <div v-if="score >= 90" class="box">大于等于90</div>
    <div v-else-if="score >= 70" class="box">大于70</div>
    <div v-else class="box">小于70</div>
    <div class="box" v-show="flag">值为{{score}}</div>
    <button class="box" v-on:click="score++">+</button>
    <button class="box" @click="score--">-</button>
    <button class="box" @click="fn">值隐藏</button><br>
    <button @click="buy(5)">可乐5元</button>
    <button @click="buy(10)">咖啡10元</button>
    <img :src="imgUrl" v-bind:title="mmg" alt="">
    <ul>
      <li v-for="(item,index) in list">{{item}}--{{index}}</li>
    </ul>
    输入框<input type="text" v-model="username">
    <button @click="reset">清空</button>
  </div>

  <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
  <script>
    const app = new Vue({
      el: '#app',
      data: {
        mmg: '哈哈哈哈',
        msg: `<a href="#">学前端~来黑马!</a>`,
        flag: true,
        score: 92,
        imgUrl: './imgs/10-01.png',
        list: ['西瓜', '苹果', '香蕉'],
        username: '哈哈哈'
      },
      methods: {
        fn() {//this指向app,this.flag = app.flag
          this.flag = !this.flag
        },
        buy(a) {
          this.score -= a
        },
        reset() {
          this.username = ''
        }
      }
    })
  </script>

3、指令修饰符

1、事件绑定 @keyup.enter="add",监听键盘回车事件,@keyup.键盘="函数名" 2、v-model修饰符,v-model.number将填写内容字符串转化为数字,v-model.trim清除首尾空格

<input type="text" v-model.number="price" />
//这个判断条件的使用必须基于,v-model.number来判断,否则写入的是数字也无法通过
if (typeof this.price !== 'number') {
            alert('请输入正确的消费价格')
            return
          }

3、@事件名.stop阻止冒泡和@事件名.prevent。如:@click.stop="add"

4、v-bind操作class和style,后面是单引号

  <div class="box" :class="{ pink: true, big: x >= y }">黑马程序员</div>
  <div class="box" :class="['pink', 'big']">黑马程序员</div>
            注意这里style多个属性是用,连接的
  <div class="inner" 
  :style="{ width: percent + '%',height: percent + '%' }">
        <span>{{ percent }}%</span>
      </div>

5、计算属性 computed ,一定要return返回值

计算属性——>对内部的data值进行求和或计算,在return返回给vue
    <p>礼物总数:{{totalCount}} 个</p>
  </div>
  <script src="./vue.js"></script>
  <script>
    const app = new Vue({
      el: '#app',
      data: {
        // 现有的数据
        list: [
          { id: 1, name: '篮球', num: 1 },
          { id: 2, name: '玩具', num: 2 },
          { id: 3, name: '铅笔', num: 5 },
        ]
      },
      computed: {
      //与data统计
        totalCount() {
          //0是起始值,sum是累加的和
          let total = this.list.reduce((sum, item) => sum + item.num, 0)
          return total
        }
      }
    })
  </script>

6、计算机属性computed与方法methods的区别

computed不用调用可直接计算缓存下来,侧重数据的处理计算,只执行一次

7、计算属性的完整写法computed,get(),set()

  <div id="app">
    姓:<input type="text" v-model="first"><br>
    名:<input type="text" v-model="last"><br>
    <p>姓名:{{full}}</p>
    <button @click="chang">修改姓名</button>
  </div>
  <script src="./vue.js"></script>
  <script>
    const app = new Vue({
      el: '#app',
      data: {
        first: '刘',
        last: '备'
      },
      computed: {
        // full() {
        //   return this.first + this.last
        // }
        full: {
          get() {
            return this.first + this.last
          },
          set(v) {
            this.first = v.slice(0, 1)
            this.last = v.slice(1)
          }
        }
      },
      methods: {
        chang() {
          this.full = '吕小布'
        }
      }
    })
  </script>

8、watch监听器,执行异步操作或业务逻辑

    const app = new Vue({
      el: '#app',
      data: {
        // words: ''
        obj: {
          words: ''
        }
      },
      // 具体讲解:(1) watch语法 (2) 具体业务实现
      watch: {
        // 该方法会在数据变化时调用执行
        // newValue新值, oldValue老值(一般不用)
        // words (newValue) {
        //   console.log('变化了', newValue)
        // }
        'obj.words'(newValue) {
          // console.log('变化了', newValue)
          //防止一段时间内多次请求
          // 防抖: 延迟执行 → 干啥事先等一等,延迟一会,一段时间内没有再次触发,才执行
          clearTimeout(this.timer)
          this.timer = setTimeout(async () => {
            const res = await axios({
              url: 'https://applet-base-api-t.itheima.net/api/translate',
              params: {
                words: newValue
              }
            })
            this.result = res.data.data
            console.log(res.data.data)
          }, 300)
        }
      }
      }
    })

9、watch监听器的完整写法

    const app = new Vue({
      el: '#app',
      data: {
        obj: {
          words: '小黑',
          lang: 'italy'
        },
        result: '', // 翻译结果
      },
      watch: {
        obj: {
          deep: true, // 深度监视,可以监听对象中的所有属性
          immediate: true, // 立刻执行,一进入页面handler就立刻执行一次
          handler(newValue) {
            clearTimeout(this.timer)
            this.timer = setTimeout(async () => {
              const res = await axios({
                url: 'https://applet-base-api-t.itheima.net/api/translate',
                params: newValue
              })
              this.result = res.data.data
              console.log(res.data.data)
            }, 300)
          }
        }
      }
    })

10、生命周期:创建,挂载,更新,销毁(8个钩子函数,一个阶段两个)

关键的两个created(初始化操作),mounted(操作dom)

      //1、创建阶段
      beforeCreate() {
      },
      created() {
      //最重要请求渲染
      },
      //2、挂载阶段
      beforeMount() {
      },
      mounted() {
      //
      },
      //更新阶段
      beforeUpdate() {
      },
      update() {
      },
      //卸载阶段
      beforeDestroy() {
      },
      destroyed() {
      }

created使用发送请求

  <script>
    // 接口地址:http://hmajax.itheima.net/api/news
    // 请求方式:get
    const app = new Vue({
      el: '#app',
      data: {
        list: []
      },
      async created() {
        const res = await axios.get('http://hmajax.itheima.net/api/news')
        this.list = res.data.data
      }
    })
  </script>

mounted使用操作dom

  <script>
    const app = new Vue({
      el: '#app',
      data: {
        words: ''
      },
      mounted() {
        //dom渲染完成输入框获取焦点
        document.querySelector('#inp').focus()
      }
    })
  </script>

11、mounted操作Echarts页面图标的实时更新

methods:{
    async getlist() {
          //重新渲染请求函数
          const res = await axios.get('https://applet-base-api-t.itheima.net/bill', { params: { creator: '换行' } })
          this.list = res.data.data
          //那部分变了就更新哪部分
          this.myC.setOption({
            series: [
              {
                data: this.list.map(item => ({
                  value: item.price, name: item.name
                })
                )
              }
            ]
          })
        }
},
mounted() {
        //操作dom在页面上绘制出图标
        this.myC = echarts.init(document.querySelector('#main'))
        this.myC.setOption({
          title: { //大标题
            text: '消费列表',
            left: 'center'
          },
          tooltip: { //提示框
            trigger: 'item'
          },
          legend: { //图例的对其等
            orient: 'vertical',
            left: 'left'
          },
          series: [
            {
              name: '消费账单',
              type: 'pie',
              radius: '50%', //半径
              data: [
              ],
              emphasis: {
                itemStyle: {
                  shadowBlur: 10,
                  shadowOffsetX: 0,
                  shadowColor: 'rgba(0, 0, 0, 0.5)'
                }
              }
            }
          ]
        })
      }
    })

12、工程化开发模式&手脚架Vue CLI

1、vue create p-name
2、yarn serve 或 npm run serve (找package.json)

image.png

13、组件化开发&根组件

1、局部注册 组件的注册和使用

<template>
    <div class="App">
        <hmHeader />
        <hmMain></hmMain>
        <hmFooter></hmFooter>
    </div>
</template>

<script>
import hmHeader from './components/hmHeader.vue';
import hmMain from './components/hmMain.vue';
import hmFooter from './components/hmFooter.vue';
export default {
    components: {
        hmHeader: hmHeader,
        hmMain,
        hmFooter
    }
}
</script>

2、全局注册,后全局可直接使用

//main.js文件全局注册
import Vue from 'vue'
import App from './App.vue'
import HmButton from './components/HmButton.vue'

Vue.component('HmButton', HmButton);

Vue.config.productionTip = false

new Vue({
  render: h => h(App),
}).$mount('#app')

14、多个组件的样式冲突问题,加scoped来解决

<style scoped>

</style>

15、data(){ return {} }写成一个函数,防止多次调用同一组件的数据干扰

export default{
    data(){
        return {
            count: 188,
        }
    }
}

16、父子关系的组件通信,数据传递

image.png 1、父传子,props: [' ']

image.png 2、子传父,this.$emit('change','传的内容')

image.png

17、props的校验 props:{ 属性名: 类型 }

props: {
    w: {
      type: Number,
      required: true,//非空校验
      default: 30,//默认值,空值填为默认值
      validator(value) { //自定义校验
        if (value >= 0 && value <= 100) {
          return true
        } else {
          console.error('传入的值必须是0~100的数字')
          return false
        }
      }
    }
  }

18、非父子关系的组件通讯,event bus事件总线,一对多

image.png

19、v-model="value"的原理 :value=""和@input事件的合写

在组件通讯时,用:value接收传来的值

<input type="text" v-model="msg1" />   //相同功能
<input type="text" :value="msg2" @input="msg2 = $event.target.value" />

image.png

20、.sync修饰符对比v-model的通讯写法

两种简写都是对子组件有命名约束

image.png

21、ref和$refs获取dom对象,echarts实例

父组件调用子组件的方法 this.$refs.子组件名.子组件的方法()

<template>
  <div class="app">
    <h4>父组件 -- <button>获取组件实例</button></h4>
    <BaseForm ref="baseFrom"></BaseForm>
    <div>
      <button @click="getFormData">获取数据</button>
      <button @click="resetFormData">重置数据</button>
    </div>
  </div>
</template>

<script>
import BaseForm from './components/BaseForm.vue'
export default {
  components: {
    BaseForm,
  },
  methods: {
    getFormData() {
      console.log(this.$refs.baseFrom.getFormData())
    },
    resetFormData() {
      this.$refs.baseFrom.resetValues()
    }
  }
}
</script>

image.png 基于准备好的dom,初始化echarts实例

<template>
  <div ref="mychart" class="base-chart-box">子组件</div>
</template>

<script>
import * as echarts from 'echarts'

export default {
  mounted() {
    // 基于准备好的dom,初始化echarts实例
    // const myChart = echarts.init(document.querySelector('.base-chart-box'))
    const myChart = echarts.init(this.$refs.mychart)
    // 绘制图表
    myChart.setOption({
      title: {
        text: 'ECharts 入门示例',
      },
      tooltip: {},
      xAxis: {
        data: ['衬衫', '羊毛衫', '雪纺衫', '裤子', '高跟鞋', '袜子'],
      },
      yAxis: {},
      series: [
        {
          name: '销量',
          type: 'bar',
          data: [5, 20, 36, 10, 10, 20],
        },
      ],
    })
  },
}
</script>

<style scoped>
.base-chart-box {
  width: 400px;
  height: 300px;
  border: 3px solid #000;
  border-radius: 6px;
}
</style>

22、vue异步更新,用 this.$nextTick( () => { })

this.$nextTick( () => { })。等dom更新完成后,再立刻执行this.$nextTick( () => { })中的语句

1、自定义指令,v- 指令

全局注册指令,在main.js中注册
Vue.directive('focus', {
  inserted(el) { //组件插入页面时触发这个钩子
    el.focus()
  }
})
局部注册,组件内部自己使用
<template>
  <div>
    <h1>自定义指令</h1>
    <input v-focus type="text">
  </div>
</template>

<script>
export default {
  directives: {
    focus: {
      inserted(el) {
        el.focus()
      }
    }
  }
}
</script>
自定义指令的传参,数据的绑定,更新
<template>
  <div>
    <h1 v-color="color1">自定义指令1111</h1>
    <h1 v-color="color2">自定义指令2222</h1>
  </div>
</template>

<script>
export default {
  data() {
    return {
      color1: 'red',
      color2: 'green'
    }
  },
  directives: {
    color: {
      inserted(el, binding) { //渲染时的钩子
        el.style.color = binding.value
      },
      update(el, binding) {  //更新时的钩子
        el.style.color = binding.value
      }
    }
  }
}
</script>
常用自定义的指令,v-loading加载展示的指令

加载动画的实现效果

<template>
  <div class="main">
    <div class="box" v-loading="isLodaing"></div>
    <div class="box2" v-loading="is2"></div>
  </div>
</template>

<script>
// 安装axios =>  yarn add axios
import axios from 'axios'

export default {
  data() {
    return {
      list: [],
      isLodaing: true,
      is2: true
    }
  },
  async created() {
    const res = await axios.get('http://hmajax.itheima.net/api/news')
    setTimeout(() => {
      // 2. 更新到 list 中
      this.list = res.data.data
      this.isLodaing = false
    }, 2000)
  },
  directives: {
    loading: {
      inserted(el, binding) {
        binding.value ? el.classList.add('loading') : el.classList.remove('loading')
      },
      update(el, binding) {
        binding.value ? el.classList.add('loading') : el.classList.remove('loading')
      }
    }
  }
}
</script>

<style>
/* 伪类 - 蒙层效果 */
.loading:before {
  content: '';
  position: absolute;
  left: 0;
  top: 0;
  width: 100%;
  height: 100%;
  background: #fff url('./loading.gif') no-repeat center;
}

2、插槽,让组件的内部的一些结构支持自定义,(如文字,样式等)

1、定义,使用方法

image.png image.png

2、默认值,<solt>默认值</solt>后备内容

image.png

3、具名插槽,一个组件需要多个地方要定制,就要给<slot name="">定义名字

image.png

4、作用域插槽,定义slot的同时,是可以传递数据的

image.png

3、路由VueRouter的使用

在main.js中注册 image.png

image.png

1、自定义匹配的类名,高亮选择的类名

image.png

image.png

image.png

2、声明式导航跳转传参

image.png

image.png 记得加?号{ path: '/search/:words?', component: Search }, image.png

3、路由重定向,起始页面的配置,{path: '/',redirect: '/home'}

image.png

4、vue路由404,{path: '*',component: NotFind}

要建立NotFind.vue文件,展示此文件的页面 image.png

5、去出导航的#,转换为历史路由

image.png image.png

6、编程式导航-基本跳转-传参

image.png image.png image.png

7、二级路由,子路由,children: [{path: ,component: }]

image.png

8、返回上一页

image.png

9、动态传参

静态用query image.png image.png

4、@绝对路径,@/ = src/ 。 就是从src出发