Vue的组件和表单

 一.表单输入绑定

1.数据的双向绑定  

  v-model  指令在表单 <input><textarea> 及 <select> 元素上创建双向数据绑定

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
<div id="app">
    <label for="username">用户名:</label>
    <input type="text" v-model="msg" id="username">
    <p>{{ msg }}</p>
    <textarea placeholder="add multiple lines" v-model='msg'></textarea>

    <input type="checkbox" id="checkbox" v-model="checked">
    <label for="checkbox">{{ checked }}</label>
    <br>
    <!--多个复选框 使用列表保存-->
    <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>
    <input type="checkbox" id="mike" value="Mike" v-model="checkedNames">
    <label for="mike">Mike</label>
    <br>
    <span>Checked names: {{ checkedNames }}</span>
    <br>
    <select v-model="selected">
        <option disabled value="">请选择</option>
        <option>A</option>
        <option>B</option>
        <option>C</option>
    </select>
    <span>Selected: {{ selected }}</span>
    <!--懒监听-->
    <input v-model.lazy="msg" >
    <!--数字显示-->
    <input v-model.number="age" type="number">
    <!--清除前后空格-->
    <input v-model.trim="msg">

</div>
<script src="vue.js"></script>
<script>
    new Vue({
        el: '#app',
        data() {
            return {
                msg: 'alex',
                checked: false,
                checkedNames: [],
                selected:'',
                age:0
            }

        }
    })

</script>
</body>
</html>
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
<div id="app">
    <input type="text" :value="msg" @input = 'changeHandler'>
    <p>{{ msg }}</p>
</div>
<script src="vue.js"></script>
<script>

    //Object.definePropty()
    new Vue({
        el:'#app',
        data(){
            return {
                msg:'alex'
            }

        },
        methods:{
            changeHandler(e){
               this.msg =  e.target.value
            }
        }
    })

</script>
</body>
</html>
双向数据绑定

二.组件

1.全局组件使用

Vue.component('全局组件的名字',{
 跟new Vue() 实例化对象中的options是一样,但是要注意:
 不管是公共组件还是局部组件 data必须是个函数 函数一定要返回 {}
})
  <slot> 元素作为承载分发内容的出口

2.局部组件的使用

  油诗: 声子 挂子 用子

  声子

let App = {
    data(){
        return {
            
        }
    },
    template:`<div>
        
        
        </div>`
}

   挂子

    挂载哪个组件,这个组件就是我的父组件

    template中的模板一定要有一个根元素

{
 ....
 template:`<App/>`
 components:{
     //挂子
     App
 }
}
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
<div id="app">
    {{ msg }}
</div>
<script src="vue.js"></script>
<script>
    //如果仅仅是实例化vue对象中 既有el 又有template,如果template中定义模板的内容
    //        那么template模板的优先级大于el

//    App   header aside  content
//    1.声子  Vue中 组件的名字 首字母要大写 跟标签区分 组件中的data必须是个函数 一定要有返回值
    let App = {
        data(){
            return {
               text:"我是日天"
            }

        },
        template:`
            <div id="a">
                <h2>{{ text }}</h2>
            </div>
        `,
        methods:{

        }
    }

    new Vue({
        el: '#app',
        data() {
            return {
                msg:'alex'
            }
        },
        //3 用子
        template: `
                <div class="app">

                 <App></App>
                </div>

            `,
        components:{
            //2.挂子
            //如果key和value一样 可以只写一个
            //App:App
            App
        }
    })

</script>
</body>
</html>
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
<div id="app">
    <App></App>
</div>
<script src="vue.js"></script>
<script>
    //如果仅仅是实例化vue对象中 既有el 又有template,如果template中定义模板的内容
    //        那么template模板的优先级大于el
    //第一个参数是组件的名字,第二个参数 options参数 它是全局组件
//     <slot></slot>  slot是vue中提供的内容组件  它会去分发 内容
    Vue.component('VBtn',{
        data(){
            return {

            }
        },
        template:`<button>
            <slot></slot>

</button>`
    })

//    App   header Vaside  Vcontent
//    1.声子  Vue中 组件的名字 首字母要大写 跟标签区分 组件中的data必须是个函数 一定要有返回值




    let Vheader = {
        data(){
            return {

            }
        },
        //template定义模板的内容
//        Component template should contain exactly one root element
        template:`
            <div>
                <h2>日天</h2>
                <h2>日天</h2>
                <VBtn>登录</VBtn>
                <VBtn>注册</VBtn>
                <VBtn>按钮</VBtn>
                <VBtn>提交</VBtn>

            </div>
        `
    }


    let App = {
        data(){
            return {
               text:"我是日天"
            }

        },
        template:`
            <div id="a">
                <h2>{{ text }}</h2>
                <Vheader></Vheader>
                 <VBtn>删除</VBtn>
                 <br>

            </div>
        `,
        methods:{

        },
        components:{
            Vheader
        }
    }

    new Vue({
        el: '#app',
        data() {
            return {
                msg:'alex'
            }
        },
        template:`<App />`,
        components:{
            //2.挂子
            //如果key和value一样 可以只写一个
            //App:App
            App
        }
    })

</script>
</body>
</html>
局部组件的使用更改

3.父子组件传值

  父向子传值

    1.在子组件中 使用props声明 可以直接在子组件中任意使用

    2.父组件 要定义自定义的属性

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
<div id="app">
    <App></App>
</div>
<script src="vue.js"></script>
<script>
    Vue.component('VBtn', {
        data() {
            return {}
        },
        template: `<button>
            {{ id }}

        </button>`,
        props:['id']
    })
    let Vheader = {
        data() {
            return {}
        },
        //只要声明了父组件的属性,就可以使用
        props: ['msg', 'post'],
        template: `
            <div class="child">
                <h2>日天</h2>
                <h2>{{ msg }}</h2>
                <h3>{{ post.title}}</h3>
                <VBtn v-bind:id = 'post.id'></VBtn>
            </div>
        `
    }


    let App = {
        data() {
            return {
                text: "我是父组件的数据",
                post: {
                    id: 1,
                    title: 'My Journey with Vue'
                }
            }

        },
        template: `
            <div id="a">

                <Vheader :msg = 'text' v-bind:post = 'post'></Vheader>
            </div>
        `,
        methods: {},
        components: {
            Vheader
        }
    }

    new Vue({
        el: '#app',
        data() {
            return {
                msg: 'alex'
            }
        },
        template: `<App />`,
        components: {

            App
        }
    })

</script>
</body>
</html>  

  子向父传值

    1、子组件中 通过$emit()触发父组件中自定义的事件

    2、父组件中声明自定义的事件介绍

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
<div id="app">
    <App></App>
</div>
<script src="vue.js"></script>
<script>
    Vue.component('VBtn', {
        data() {
            return {}
        },
        template: `<button @click = 'clickHandler'>
            {{ id }}

        </button>`,
        props:['id'],
        methods:{
            clickHandler(){
                //每个组件中的this指的是当前组件对象
                console.log(this);
                this.id++;
//                this.$emit('父组件声明自定义的事件','传值');
                this.$emit('clickHandler',this.id);


            }
        }
    })
    let Vheader = {
        data() {
            return {}
        },
        //只要声明了父组件的属性,就可以使用
        props: ['msg', 'post'],
        template: `
            <div class="child">
                <h1>我是header组件</h1>
                <h2>日天</h2>
                <h2>{{ msg }}</h2>
                <h3>{{ post.title}}</h3>
                <VBtn v-bind:id = 'post.id' @clickHandler="clickHandler"></VBtn>
            </div>
        `,
        methods:{
          clickHandler(val){
              alert(val);
              this.$emit('fatherHandler',val)
          }
        },
         created(){
          console.log(this);
        },
    }


    let App = {
        data() {
            return {
                text: "我是父组件的数据",
                post: {
                    id: 1,
                    title: 'My Journey with Vue'
                }
            }

        },
        template: `
            <div id="a">
                我是父组件的 {{post.id}}
                <Vheader :msg = 'text' v-bind:post = 'post' @fatherHandler = 'father_handler'></Vheader>
            </div>
        `,
        methods: {
            father_handler(val){
                console.log(val);

                this.post.id = val;
            }
        },
        components: {
            Vheader
        },
         created(){
          console.log(this);
        },
    }

    new Vue({
        el: '#app',
        data() {
            return {
                msg: 'alex'
            }
        },
        created(){
          console.log(this);
        },
        template: `<App />`,
        components: {

            App
        }
    })

</script>
</body>
</html>

4.平行组件传值

  使用$on()和$emit() 绑定的是同一个实例化对象

  A===>B组件传值

  1、B组件中要使用$on(‘事件的名字’,function(){})

  2、A组件中使用$emit('事件的名字',值)

<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
<div id="app">
    <App/>
</div>
<script src="vue.js"></script>
<script>
    let bus = new Vue();
    //A===》B   B要声明事件  $on('事件的名字',function(val){})  A要触发事件 $emit('A组件中声明的事件名','值')

    //前提 这两个方法必须绑定在同一个实例化对象(bus)
    Vue.component('Test2', {
        data() {
            return {
                text:''
            }
        },
        template: `
            <h2>{{ text }}</h2>
        `,
        methods: {

        },
        created(){
            bus.$on('testData', (val)=> {
                alert(val);
                this.text = val;
            })
        }
    })
    Vue.component('Test', {
        data() {
            return {
                msg: '我是子组件的数据'
            }
        },
        props:['txt'],
        template: `
            <button @click = 'clickHandler'>{{ txt }}</button>
        `,
        methods: {
            clickHandler() {

                bus.$emit('testData',this.msg)
            }
        }
    })

    let Vheader = {
        data() {
            return {
                txt:'wusir'
            }

        },
        template: `
            <div class="header">

                <Test :txt = 'txt'/>
                <Test2 />

            </div>
        `
    }
    let App = {
        data() {
            return {}

        },
        template: `
            <div class="app">

                 <Vheader />

            </div>
        `,
        components: {
            Vheader
        }
    }
    new Vue({
        el: '#app',
        data() {
            return {}
        },
        components: {
            App
        }
    })

</script>
</body>
</html>
原文地址:https://www.cnblogs.com/chenxi67/p/10032208.html