【Vue】组件部分知识+.sync修饰符原理+v-model原理

1.脚手架引用组件

全局应用在main.js中

import children from './components/children.vue'
Vue.component("children",children)

局部引用在对应的vue文件中

<children></children>

import children from "@/components/children.vue";
export default {
  components: {
    children
  },
}

2.组件中data必须是函数

js中对象类型变量保存的实际上是对象的引用,存在多个组件会共享数据,导致一个组件中数据的改变会引起其他组件数据的改变。

而使用一个返回对象的函数,每次使用组件都会创建一个新的对象,这样就不会出现共享数据的问题了。

3.属性Prop

3.1prop的大小写

html中的attribute对大小写不敏感,所有浏览器会把大写解析成小写,使用时驼峰命名的prop名要使用等价的短横线分割命名

// 使用时短横线分隔符
<children :prop-a=""></children>

// 组件中驼峰定义
props: ["propA", "propB"]

3.2静态动态prop

静态传递直接传入静态值,动态传递用v-bind

3.3单向数据流

父子prop之间形成单行下行绑定:父级prop更新会向下流动到子组件中,反过来则不行。

每次父组件发生更新,子组件中所有的prop都将会刷新为最新的值。意味这你不应该在一个子组件内部改变prop,否则控制台会警告。

注意:

1.父组件传递的属性是引用类型,在子组件中更改相应的属性会导致父组件相应属性的更改

2.父组件传递的属性是基本类型时,在子组件中更改这个属性会报错。正确的做法是在父组件中绑定属性时时加上.sync修饰符,然后在子组件中改变相应的属性。无论直接改变还是加了修饰符后改变控制台都会报错:

3.如果希望在子组件对传入的prop进行操作,建议在组件中data或computed创建新属性并以传递进来的值进行初始化,而引用类型避免影响父组件中相应数据最后进行深复制。

3.4.sync修饰符的原理

.sync实现双向绑定,即可以把子组件的改变传递到父组件

子组件

    <footer @click="change">{{str}}</footer>
    change(){
      this.$emit('update:str','change')
    }

父组件

    <children :str="str" @update:str="str=$event"></children>

为了方便提供了一个缩写模式,即.sync修饰符

父组件
<text-document :title.sync="doc.title"></text-document>
子组件
this.$emit('update:title',2)

注意.sync修饰符的v-bind不能和表达式一起使用列如:title.sync=“doc.title+'!”。你只能提供你想要绑定的属性名类似于v-model。

3.5.prop验证

  props: {
    typePropA: String, //基础类型检查
    typePropB: [String, Number, Boolean, Function, Object, Array, Symbol, Date] // 多个可能的类型
    // 必传
    requiredProp:{
        type:String,
        required:true,     
    },
    // 默认值
    defaultProp:{
        type:String,
        default:1  
    },
    // 对象或数组默认值必须从一个工厂函数获取
    obj: {
      type: Object,
      default() {
        return { message: "hello" };
      }
    },
    // 自定义验证函数
    validatorProp: {
      type: Number,
      validator: function(value) {
        return value > 10;
      },
      default: 12
    }
  },

prop的type可以是原生构造函数中的一个,也可以自己自定义构造函数使用,并且通过instanceof来进行检查确认

String, Number, Boolean, Function, Object, Array, Symbol, Date

3.6.非prop类型的attribute

也可以像在html标签中添加data-开头的自定义属性一样,给自定义组件添加任意的属性。这样做的话vue会把这个属性放在自定义组建的根元素。自定义组件的模板只能有一个根元素。

父组件向子组件的非prop属性传值则会覆盖,如果是class和style则才用合并。

4.子向父传递事件

//子
this.$emit('myclick',data1,data2)

//父
<my-component @myclick="functionName"></my-component>

此时不应该传进任何参数,否则子组件暴露出的数据就无法获取了

5.父绑定原生事件,用.native修饰v-on

<my-component @click.native="functionName"></my-component>

6.子组件阻止事件冒泡用.stop修饰

7.组件的切换:is

<component :is="currentTabComponent"></component>

8.缓存组件的状态keep-alive

<keep-alive>
  <component v-bind:is="currentTabComponent"></component>
</keep-alive>

9.异步组件

在大型应用我们将应用分割成一些小的代码块,并且只在需要的时候才从服务器加载。为了简化,Vue允许你以一个工厂函数的方式定义你的组件,这个工厂函数会异步保存解析你的组件定义。Vue只有在这个组件需要被渲染的时候才会触发该工厂函数,且会被结构缓存起来供未来重渲染。

Vue.component('async-example', function (resolve, reject) {
  //setTimeout是为了演示,如何获取组件取决于你自己
setTimeout(function () { // 向 `resolve` 回调传递组件定义 resolve({ template: '<div>I am async!</div>' }) }, 1000) })

可以调用rehect(reason)来表示加载失败。

推荐做法是将异步组件和webpack的code-splitting功能配合使用:

Vue.component('async-webpack-example', function (resolve) {
  // 这个特殊的 `require` 语法将会告诉 webpack
  // 自动将你的构建代码切割成多个包,这些包
  // 会通过 Ajax 请求加载
  require(['./my-async-component'], resolve)
})

也可以在工厂函数中返回Promise,把webpack2和ES2015语法加载一起,可以写成这样

Vue.component(
  'async-webpack-example',
  // 这个 `import` 函数会返回一个 `Promise` 对象。
  () => import('./my-async-component')
)

路由中有相类似的行为

 

 局部注册可以使用:

new Vue({
  // ...
  components: {
    'my-component': () => import('./my-async-component')
  }
})

处理加载状态,也可以返回一个如下格式的对象

const AsyncComponent = () => ({
  // 需要加载的组件 (应该是一个 `Promise` 对象)
  component: import('./MyComponent.vue'),
  // 异步组件加载时使用的组件
  loading: LoadingComponent,
  // 加载失败时使用的组件
  error: ErrorComponent,
  // 展示加载时组件的延时时间。默认值是 200 (毫秒)
  delay: 200,
  // 如果提供了超时时间且组件加载也超时了,
  // 则使用加载失败时使用的组件。默认值是:`Infinity`
  timeout: 3000
})  

10.组件中使用v-model

<input v-model="searchText">

v-model原理

<input
  :value="searchText"
  @input="searchText = $event.target.value"
>

用在组件上即如下:

父组件

<children2 :value="value" @input="getInput"></children2>

子组件内的input必须1.将其value特性绑定到props上;2.input触发时将新值抛出

<template>
  <div>
    <div>
      <input :value="value" @input="$emit('input',$event.target.value)" />
    </div>
  </div>
</template>
<script>
export default {
  props: ["value"],
  data() {
    return {};
  }
};
</script>

11.边界情况

this.$root访问根元素

this.$parent子组件用来访问父组件

用ref赋予id引用,this.$refs拿到对指定元素的访问

<base-input ref="usernameInput"></base-input>

this.$refs.input.focus()
posted @ 2020-01-19 10:23  把我当做一棵树叭  阅读(694)  评论(0)    收藏  举报