Vue表单与组件

表单的数据绑定

文本:

<input v-model="message" placeholder="edit me">
<p>Message is: {{ message }}</p>

多行文本:

<!--white-space:pre 使得空格不会被解析-->
<p style="white-space: pre">{{ message }}</p>
<textarea v-model="message" placeholder="add multiple lines"></textarea>

复选框:

<!--如果就一个复选框-->
<input type="checkbox" id="checkbox" v-model="checked">
<label for="checkbox">{{ checked }}</label>

<!--如果有多个复选框,应该绑定到同一个数组-->
<input type="checkbox" id="jack" value="Jack" v-model="checkedNames">
<label for="jack">Jack</label>
<input type="checkbox" id="john" value="John" v-model="checkedNames">
<label for="john">John</label>
<span>Checked names: {{ checkedNames }}</span>
new Vue({
      el: '...',
      data: {
        checkedNames: []
      }
})

单选框:

<!--不需要数组,邦定到同一个data变量上即可-->
<input type="radio" id="one" value="One" v-model="picked">
<label for="one">One</label>
<br>
<input type="radio" id="two" value="Two" v-model="picked">
<label for="two">Two</label>
<br>
<span>Picked: {{ picked }}</span>

表单传值===选中后绑定的data变量的值

<!-- 当选中时,`picked` 为字符串 "a" -->
<input type="radio" v-model="picked" value="a">
<!-- `toggle` 为 true 或 false -->
<input type="checkbox" v-model="toggle">
<!-- 当选中时,`selected` 为字符串 "abc" -->
<select v-model="selected">
      <option value="abc">ABC</option>
</select>

<!--当然可以用v-bind:value 使得value也是动态的值-->
单选:
<input type="radio" v-model="pick" v-bind:value="a">
// 当选中时
vm.pick === vm.a

复选:
<input
  type="checkbox"
  v-model="toggle"
  v-bind:true-value="a"
  v-bind:false-value="b">

  // 当选中时
vm.toggle === vm.a
// 当没有选中时
vm.toggle === vm.b

列表:
<select v-model="selected">
    <!-- 内联对象字面量 -->
      <option v-bind:value="{ number: 123 }">123</option>
</select>
// 当选中时
typeof vm.selected // -> 'object'
vm.selected.number // -> 123

修饰符

<!-- 在 "change" 而不是 "input" 事件中更新 -->
<input v-model.lazy="msg" >

<!--自动将用户的输入值转为 Number 类型(如果原值的转换结果为 NaN 则返回原值)-->
<input v-model.number="age" type="number">

<!--自动过滤用户输入的首尾空格-->
<input v-model.trim="msg">

组件

基本使用

组件(Component)是 Vue.js 最强大的功能之一。组件可以扩展 HTML 元素,封装可重用的代码。在较高层面上,组件是自定义元素, Vue.js 的编译器为它添加特殊功能。在有些情况下,组件也可以是原生 HTML 元素的形式,以 is 特性扩展。

全局组件:

<div id="example">
      <my-component></my-component>
</div>
// 注册
Vue.component('my-component', {
      template: '<div>A custom component!</div>'
})
// 创建根实例
new Vue({
      el: '#example'
})

局部组件:仅实例/组件的作用域中可用:

var Child = {
template: ‘

A custom component!

}
new Vue({
components: {
// 将只在父模板可用
‘my-component’: Child,
App, // App组件 == ‘App’:App,
}
})
组件限制--is

源于<ul> , <ol>, <table> , <select> 限制其内部的元素
无效:
<table>
      <my-row>...</my-row>
</table>
有效:
<table>
      <tr is="my-row"></tr>
</table>

应当注意,如果您使用来自以下来源之一的字符串模板,这些限制将不适用:

<script type="text/x-template">
JavaScript内联模版字符串
.vue 组件

组件的使用。要确保在初始化根实例 之前 注册了组件

data 必须是函数

Vue.component('simple-counter', {
      data: function () {
        return {}
      }
})

每个组件都用它自己的data属性,互不干扰,除非组件共用外部的变量

<div id="example-2">
      <simple-counter></simple-counter>
      <simple-counter></simple-counter>
</div>
var data = { counter: 0 }
Vue.component('simple-counter', {
      template: '<button v-on:click="counter += 1">{{ counter }}</button>',
      // 但是我们为每一个组件返回了同一个对象引用
      data: function () {
        //return data   //两个组件的值一起变
        return {counter:0} //互不干扰
      }
})

组件间通信

父组件通过 props 向下传递数据给子组件,子组件通过 emit 给父组件发送消息。

props

常规使用

<!--注意属性值用‘-’   这里是静态的hello-->
<child my-message="hello!"></child>
Vue.component('child', {
      // 声明 props
      props: ['myMessage'],
      // 就像 data 一样,prop 可以用在模板内
      // 同样也可以在 vm 实例中像 “this.message” 这样使用
      template: '<span>{{ myMessage }}</span>'
})

<!--属性props动态值传递需要 v-bind -->
<!-- 传递实际的数字1,也可以是变量(例如data里的变量) -->
<comp v-bind:some-prop="1"></comp>

props需要默认值或验证
验证不通过也会正常显示,只是在后台报错,主要是给其他使用组件的朋友看的

Vue.component('example', {
      props: {
        // 基础类型检测 (`null` 意思是任何类型都可以)
        propA: Number,
        // 多种类型
        propB: [String, Number],
        // 必传且是字符串
        propC: {
              type: String,
              required: true
        },
        // 数字,有默认值
        propD: {
              type: Number,
              default: 100
        },
        // 数组/对象的默认值应当由一个工厂函数返回 *******必须是函数*****
        propE: {
              type: Object,
              default: function () {
                return { message: 'hello' }
              }
        },
        // 自定义验证函数
        propF: {
              validator: function (value) {
                return value > 10
              }
        }
      }
})

emit向父组件传递数据

<div id="counter-event-example">
      <p>{{ total }}</p>
              <!--组件的increment事件出发后执行实例的incrementTotal方法-->
      <button-counter v-on:increment="incrementTotal"></button-counter>

      <!--组件使用.native说明使用的是原生click事件不是绑定的事件-->
      <!--<my-component v-on:click.native="doTheThing"></my-component>-->

</div>
Vue.component('button-counter', {
                //1,组件内btn点击触发函数increment
      template: '<button v-on:click="increment">{{ counter }}</button>',
      data: function () {
        return {
              counter: 0
        }
      },
      methods: {
        increment: function () {
              this.counter += 1
              // 2,函数执行后触发组件的increment事件 //带了数据出去
              this.$emit('increment','传递的数据')
        }
      },
})
new Vue({
      el: '#counter-event-example',
      data: {
        total: 0,
        str='',
      },
      methods: {
          //实例方法执行,成功获取到组件内部传递的数据  //注意有参
        incrementTotal: function (a) {
              this.total += 1
              this.str = a  //this.str = '传递的数据'
        }
      }
})

插槽Slots–分发内容

slot标签中的任何内容都被视为备用内容。备用内容在子组件的作用域内编译,并且只有在宿主元素为空,且没有要插入的内容时才显示备用内容。

单个插槽:

//component组件
<div>
      <h2>I'm the child title</h2>
      <slot>如果没有分发内容则显示我。</slot>
</div>

//html
<div>
      <h1>I'm the parent title</h1>
      <my-component>
        <p>插入的内容</p>
      </my-component>
</div>

//渲染结果:
<div>
      <h1>I'm the parent title</h1>

      <div>
          <h2>I'm the child title</h2>
          <p>插入的内容</p>
    </div>
      <h2>I'm the child title</h2>
</div>

多个slot:用name分配:

//组件
<div class="container">
      <header>
            <slot name="header"></slot>
      </header>
     <main>
        <slot></slot>
      </main>
      <footer>
        <slot name="footer"></slot>
      </footer>
</div>

//html
<app-layout>
      <h1 slot="header">header</h1>
      <p>A paragraph for the main content.</p>
      <p slot="footer">footer</p>
</app-layout>

//渲染结果
<div class="container">
      <header>
        <h1>header</h1>
      </header>

      <main>
        <p>A paragraph for the main content.</p>
      </main>

      <footer>
        <p>footer</p>
      </footer>
</div>

切换组件显示

var vm = new Vue({
      el: '#example',
      data: {
        currentView: 'home'
      },
      components: {
            home: { /* ... */ },
        posts: { /* ... */ },
        archive: { /* ... */ }
      }
})
//keep-alive切换出去的组件保留在内存中,可以保留它的状态或避免重新渲染。
<keep-alive>
    <component v-bind:is="currentView">
      <!-- 组件在 vm.currentview 变化时改变! -->
    </component>
</keep-alive>

子组件索引

—获取其他不相关的组件并加以控制器内部实现
<div id="parent">
      <user-profile ref="profile"></user-profile>
</div>

var parent = new Vue({ el: '#parent' })
// 访问子组件
var child = parent.$refs.profile;

//然后就可以控制child的内部实现--
    如child.a=..
    child.fn();

尽管在 Vue 中渲染 HTML 很快,不过当组件中包含大量静态内容时,可以考虑使用 v-once 将渲染结果缓存起来

–注意使用v-once后内部值或者变量都只会执行一次,后续不会再变动,包括子节点

先到这里OVER