Vue知识点

Vue知识点

Vue.component的缺点:

  • 全局定义: 强制要求每个component中的命令不重复
  • 字符串模板:缺乏语法高亮,在HTML有多行的时候,需要丑陋的\
  • 不支持CSS:意味着当HTML和JavaScript组件化时,CSS被明显遗漏
  • 没有构建步骤:限制只能使用HTML和ES5 JavaScript,而不能使用预处理器,如Pug(formerly Jade)和Babel

单文件组件

vue create my-app命令创建一个默认的项目
main.js文件中有如下的代码:

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

如何理解render: h => h(App),可参考:

首先需要了解这是 es 6 的语法,表示 Vue 实例选项对象的 render 方法作为一个函数,接受传入的参数 h 函数,返回 h(App) 的函数调用结果。

插槽

v-slot can only be used on components or <template>.

TotoItem.vue

<template>
  <li class="item">
    <input type="checkbox" v-model="checked"/>
    <slot name="item" v-bind="{checked}"></slot>
  </li>
</template>

<script> export default { props: ["item"], data () { return { checked: false } } }; </script>

<style scoped> .item { color: red; } </style>

App.vue

<template>
  <div id="app">
    {{ msg }}
    <div>
      <input type="text" v-model="info">
      <button v-on:click="handleClick">添加</button>
    </div>
    <ul>
      <todo-item v-for="item in list" :key="item" v-slot:item="itemProps">
        <!-- <template v-slot:item="itemProps"> <span :style="{fontSize: '20px', color: itemProps.checked ? 'red': 'blue'}">{{ item }}</span> </template> -->

        <span :style="{fontSize: '20px', color: itemProps.checked ? 'red': 'blue'}">{{ item }}</span>
      </todo-item>
    </ul>
  </div>
</template>

<script> import TodoItem from './components/TodoItem.vue' export default { data() { return { msg: "hello wz", info: "", list: [] }; }, methods: { handleClick() { this.list.push(this.info); this.info = ""; } }, components: { TodoItem } }; </script>

<style> </style>

自己的理解:

v-slot:item="itemProps"表示的是nameitemslotitemProps表示的是子组件中v-bind="{checked}传递给父组件的itemProps

参考:


1.对slot与slot-scope的理解

由于slot是一块模板,因此对于任何一个组件,从模板种类的角度来分,共实都可分为非插槽模板和插槽模板。其中非插槽模板指的是HTML模板(也就是HTML的一些元素,比如div、span等构成的),其显与否及怎么显示完全由插件自身控制;但插槽模板(也就是slot)是一个空壳子,它显示与否以及怎么显示完全是由父组件来控制。不过,插槽显示的位置由子组件自身决定,slot写在组件template的哪块,父组件传过来的模板将来就显示在哪块。著作权归作者所有。

slot-scope 的值将被用作一个临时变量名,此变量接收从子组件传递过来的 prop 对象

组件

组件01
组件的三大核心概念:属性、事件和插槽

组件02

单向数据流

单向数据流

所有的 prop 都使得其父子 prop 之间形成了一个单向下行绑定:父级 prop 的更新会向下流动到子组件中,但是反过来则不行。这样会防止从子组件意外改变父级组件的状态,从而导致你的应用的数据流向难以理解。
额外的,每次父级组件发生更新时,子组件中所有的 prop 都将会刷新为最新的值。这意味着你不应该在一个子组件内部改变 prop。如果你这样做了,Vue 会在浏览器的控制台中发出警告。

如何解决:

1.这个 prop 用来传递一个初始值;这个子组件接下来希望将其作为一个本地的 prop 数据来使用。在这种情况下,最好定义一个本地的 data 属性并将这个 prop 用作其初始值:

props: ['initialCounter'],
data: function () {
  return {
    counter: this.initialCounter
  }
}

2.这个 prop 以一种原始的值传入且需要进行转换。在这种情况下,最好使用这个 prop 的值来定义一个计算属性:

props: ['size'],
computed: {
  normalizedSize: function () {
    return this.size.trim().toLowerCase()
  }
}

如果在子组件中修改修改父组件的prop,会提示warn:

提示警告

事件

事件分类
可参考官方文档:事件处理

各种控价的input 和 change事件可参考https://jsfiddle.net/posva/oqe9e8pb/

<script src="https://unpkg.com/vue/dist/vue.js"></script>

<div id="app">
  <input type="text" @input="addEvent" @change="addEvent" />
  <input type="range" min="0" max="100" @input="addEvent" @change="addEvent" />
  <input type="checkbox" @input="addEvent" @change="addEvent" />
  <input type="radio" name="radio" value="1" @input="addEvent"  @change="addEvent" />
  <input type="radio" name="radio" value="2" @input="addEvent"  @change="addEvent" />
  <select @input="addEvent" @change="addEvent">
  <option value="1">1</option>
  <option value="2">2</option>
  </select>
  <ul>
    <li v-for="event in events">{{ eventText(event) }}</li>
  </ul>
</div>


new Vue({
  el: '#app',
  data: {
  	events: []
  },
  methods: {
  	addEvent ({ type, target }) {
      const event = {
          type,
          isCheckbox: target.type === 'checkbox',
          target: {
            value: target.value,
            checked: target.checked
          }
      }
    	this.events.push(event)
    },
    eventText (e) {
    	return `${e.type}: ${e.isCheckbox ? e.target.checked : e.target.value}`
		}
  }
})

插槽

可分为普通插槽和作用域插槽,但2.0之后就不再区分了

插槽

1.普通插槽:父->子,父组件传递数据/元素/组件给子组件,子组件定义<slot>占坑
2.作用域插槽:子->父,子组件<slot>绑定属性,传递(数据)给父组件,父组件通过slot-scope接收子组件传递属性
3.使用v-slot新语法,代替旧语法
4.多插槽时使用具名插槽方式(<slot name="header">),用于将数据绑定在指定的插槽

Slot.vue

<template>
  <div>
    <slot />
    <slot name="title" />
    <slot name="item" v-bind="{ value: 'vue' }" />
  </div>
</template>

<script>
export default {
  name: "SlotDemo"
};
</script>

使用

<h2>2.6 新语法</h2>
        <SlotDemo>
          <p>default slot</p>
          <template v-slot:title>
            <p>title slot1</p>
            <p>title slot2</p>
          </template>
          <template v-slot:item="props">
            <p>item slot-scope {{ props }}</p>
          </template>
        </SlotDemo>
        <br />
        <h2>老语法</h2>
        <SlotDemo>
          <p>default slot</p>
          <p slot="title">title slot1</p>
          <p slot="title">title slot2</p>
          <p slot="item" slot-scope="props">item slot-scope {{ props }}</p>
        </SlotDemo>

显示效果如下:
显示效果

计算属性和监听器

计算属性computed

  • 减少模板中计算逻辑
  • 数据缓存
  • 依赖固定的数据类型(响应式数据)

监听器

  • 更加灵活、通用
  • watch中可以执行任何逻辑,如函数节流、ajax异步获取数据、甚至操作dom

computed vs watch

  • computed能做的,watch都能做,反之则不行
  • 能用computed的尽量用computed

补充:

生命周期的应用场景和函数式组件

生命周期分为三个阶段:

  • 创建阶段
  • 更新阶段
  • 销毁阶段

生命周期的阶段

创建阶段

创建阶段

更新阶段

更新阶段

销毁阶段

销毁阶段

函数式组件

函数式组件

  • functional: true
  • 无状态、无实例、没有this上下文、无生命周期