vue 前端数据库 组件 组件间信息交互

一、todolist留言板案例

# 前端数据库

悬浮小手  首增尾增  前端分割切分      

"""
1) 留言就是往留言数组中添加数据,删除留言就是从留言数组中移除数据

2) 前台数据库:localStorage 和 sessionStorage
    localStorage永久保存数据
    sessionStorage临时保存数据(当所属页面标签被关闭,数据被清空)
    
3) 前台localStorage 和 sessionStorage数据库存储的值是字符串类型,所以要存放arr、dic等复杂数据需要JSON参与
"""
<!DOCTYPE html>
<html lang="zh">
<head>
    <meta charset="UTF-8">
    <title></title>
    <style>
        li:hover {
            color: red;
            cursor: pointer; 
        } 
    </style>
</head>
<body>
    <div id="app">
        <p>
            <input type="text" v-model="userMsg">
            <button type="button" @click="sendMsg">留言</button>
        </p>

        <ul>
            <li v-for="(msg, index) in msgs" @click="deleteMsg(index)">  
                {{ msg }}
            </li>
        </ul>

    </div>
</body>
<script src="js/vue.js"></script>
<script>
    new Vue({
        el: '#app',
        data: {
            msgs: localStorage.msgs ? JSON.parse(localStorage.msgs) : [],  // 这是所有留言,页面需要用的时候循环msgs,如果数据库有值则渲染,无值为空列表
            userMsg: '',  // 留言框用户留言,默认为空
        },
        methods: {
            sendMsg() {  // 留言事件
                // 尾增
                // this.msgs.push(this.userMsg);
                // 首增
                // this.msgs.unshift(this.userMsg);

                let userMsg = this.userMsg;  //获取输入框中留言内容
                if (userMsg) {  //判断留言框是否为空,有内容才会继续
                    this.msgs.unshift(userMsg);  // 塞入所有留言列表
                    localStorage.msgs = JSON.stringify(this.msgs);  // 同步到数据库
                    this.userMsg = '';  // 清空留言框
                }
            },
            deleteMsg(index) {
                // 三个参数:开始索引  操作长度  操作的结果们(例如:(0,0,1,2,3)就是说从零位操作零位,结果变成1,2,3,点一下增加三个数)
                //这里两个参数的意思是从索引开始操作一位结果变成空,就是删除一个数的意思
                this.msgs.splice(index, 1)
            }
        }
    })
</script>

<script>

   //测试前端数据库  // localStorage['num'] = 10; // sessionStorage.num = 888; // console.log(localStorage.num); // localStorage.msgs = JSON.stringify(['1111', '2222']); // console.log(JSON.parse(localStorage.msgs)); // console.log(JSON.parse(localStorage.msgs)[0]); </script> </html>

二、组件

1.组件认识

// 1) 组件:一个包含html、css、js独立的集合体,这样的集合体可以完成页面解构的代码复用,后端没有组件概念,前端才有
// 2) 分组分为根组件、全局组件与局部组件
1.根组件:所有被new Vue()产生的组件,在项目开发阶段,一个项目只会出现一个根组件,因为根组件和根组件之间不能直接进行信息交互
2.全局组件:不用注册,就可以成为任何一个组件的子组件
3.局部组件:必须注册,才可以成为注册该局部组件的子组件 // 3) 每一个组件都有自身的html结构,css样式,js逻辑
1.每一个组件其实都有自己的template,就是用来标识自己html结构的
2.template模板中有且只有一个根标签
3.根组件一般不提供template,就由挂载点的真实DOM提供html结构 // 4) 除根组件的其他组件,数据要有局部作用域,保证组件复用时,各组件间数据的独立性 // 5) 在多组件共处时,在哪个组件模板中出现的变量,由当前组件组件提供
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        span{color: yellowgreen;}
    </style>
</head>
<body>
<!--组件是有html模板,有CSS样式,有js逻辑的集合体,这里先这样写,后期会分成三部分,分开写-->
<!--挂载点不能用html,也不能用body,因为会被组件会被template替换掉,也就是说如果你用了body或者html他们会被替换掉,也就是说他们不再存在,这显然不合理-->
<!--挂载点必须有,但是里面的p标签可有可无,因为后期会被替换,挂载点div类似占位符,先用该div渲染出真实DOM后面用template内部的虚拟DOM把这里的真实DOM替换掉-->
<div id="app01"> 
    <p><h1>组件的概念</h1></p>
</div>
    
</body>
<script src="js/vue.js"></script>
<script>
    new Vue({
        el:'#app01',
        template:`
        <div style="color: red">     css样式
            <h1>组件渲染的模板</h1>
            <span @click="lll">点我</span>
        </div>
        `,
        data:{},
        methods:{
            lll:function () {  //js逻辑
                alert(123)
            }
        }
    })
</script>
</html>

这就是组件的最终格式,有自己的HTML模板,有css样式,还有自己的js逻辑的代码块,然后我们在实际开发中肯定会有好多好多的组件,这就需要用到了全局子组件和局部子组件,然后我们的template只在局部组件中使用,根组件直接使用挂载点的模板就好

2、局部组件

注意在使用局部组件的时候一定要注册,在components中

 每个组件模板只能拥有一个根标签

// 1) 创建局部组件
// 2) 在父组件中注册该局部组件
// 3) 在父组件的template模板中渲染该局部组件

1.创建局部组件

 let localTag = {
        template: `
        <div class="box">
            <img src="img/666.jpg" alt="">
            <h3>凤哥</h3>
            <p>马叉虫❤马叉虫</p>
        </div>
        `
    };
 2. 在父组件中注册该局部组件
new Vue({
        el: '#app',
        components: {
            // mcc: localTag,  #这里冒号前什么名字,渲染的时候就用什么
            // localTag,
            'local-tag': localTag,
        }
    })
3. 在父组件的template模板中渲染该局部组件
<div id="app">
    <!--<mcc></mcc>-->
    <local-tag></local-tag> #这里渲染的时候会将大写转换成小写,就会报错,要不就名字直接写小写,如果采取省略写法这里就加下划线也可以等价于驼峰体
    <local-tag></local-tag>
</div>
<!DOCTYPE html>
<html lang="zh">
<head>
    <meta charset="UTF-8">
    <title></title>
    <style>
        .box {
            box-shadow: 0 3px 5px 0 #666;
            width: 240px;
            height: 300px;
            text-align: center;
            padding: 20px 0;
            float: left;
            margin: 5px;
        }
        .box img {
            width: 200px;
        }
    </style>
</head>
<body>
    <div id="app">
        <!--<mcc></mcc>-->
        // 3) 在父组件的template模板中渲染该局部组件
        <local-tag></local-tag>
        <local-tag></local-tag>
    </div>
</body>
<script src="js/vue.js"></script>
<script>
    // 创建一个局部组件

    // 1) 创建局部组件
    let localTag = {
        template: `
        <div class="box">
            <img src="img/666.jpg" alt="">
            <h3>凤哥</h3>
            <p>马叉虫❤马叉虫</p>
        </div>
        `
    };

 // 2) 在父组件中注册该局部组件
    new Vue({
        el: '#app',
        components: {
            // mcc: localTag,
            // localTag,
            'local-tag': localTag,
        }
    })
</script>
</html>
View Code

3、全局组件

 Vue.component('全局组件名',{
        在该字典中书写代码块
    })

全局组件与局部组件的区别是全局组件不需要注册,局部组件需要注册,我们自己在使用的时候,用全局组件会多一些,但是在一个项目 开发中使用局部组件会多!

<!DOCTYPE html>
<html lang="zh">
<head>
    <meta charset="UTF-8">
    <title></title>
    <style>
        .box {
            box-shadow: 0 3px 5px 0 #666;
            width: 240px;
            height: 300px;
            text-align: center;
            padding: 20px 0;
            float: left;
            margin: 5px;
        }
        .box img {
            width: 200px;
        }
    </style>
</head>
<body>
    <div id="app">
        <global-tag></global-tag>
        <global-tag></global-tag>
        <global-tag></global-tag>
    </div>
</body>
<script src="js/vue.js"></script>
<script>
    // 1) 创建全局组件
    // 2) 在父组件的template模板中直接渲染该全局组件
    Vue.component('global-tag', {
        template: `
        <div class="box" @click="action">
            <img src="img/666.jpg" alt="">
            <h3>凤哥</h3>
            <p>马叉虫❤{{ num }}</p>
        </div>
        `,
        data () {
            return {
                num: 0
            }
        },
        methods: {
            action() {
                this.num++;
            }
        }
    });

    // 数据局部化分析导入
    //如果这里直接是 a=10|b1=a|b2=a|b3=a  那么当b1或者b2或b3任意一个改变,a会改变,也就是说所有的数都改变
    
    //采用下面的函数,每一次实例化出一个a,有自己的名称空间,互不干扰
    // a = function () {
    //     return {num: 10}
    // };
    // b1 = a();
    // b2 = a();
    // b3 = a();

    new Vue({
        el: '#app',
    })
</script>
</html>
点击哪个哪个加一

三、组件间信息交互

知道了组件之后,我们实际中会有多个组件存在,多个组件中拿到的数据有可能是从根组件提供的,如何从根组件那里拿到数据,或者说从子组件那里拿到数据给根组件,这就是组件之间的信息交互,和我们学过的进程间通信是比较像的,我们下面来学习书写

1.父传子

父传子重点就是找对信息交互的点,就是子组件的渲染标签,

该标签是子组件的,属性也就是子组件的,但是属性值由父组件提供,

子组件中通过props反射将这个值取出就拿到了数据,渲染成功

// 数据交互 - 父传子 - 通过绑定属性的方式
// 1) 子组件的标签,父组件提供数据
// 2) 在父组件模板中,为子组件标签设置自定义属性,绑定的值由父组件提供
// 3) 在子组件实例中,通过props反射实例成员获得自定义属性

 

 

 

<!DOCTYPE html>
<html lang="zh">
<head>
    <meta charset="UTF-8">
    <title></title>
    <style>
        .info {
            text-align: center;
            width: 200px;
            padding: 3px;
            box-shadow: 0 3px 5px 0 pink;
            float: left;
            margin: 5px;
        }
        .info img {
            width: 200px;
        }
    </style>
</head>
<body>
    <div id="app">
        <info v-for="info in infos" :key="info.image" :myinfo="info"></info>
    </div>
</body>
<script src="js/vue.js"></script>
<script>
    // 伪代码:模拟数据从后台请求
    /*
    let infos = '';
    document.onload = function () {
        $.ajax({
            url: '/images/',
            type: 'get',
            success (response) {
                infos = response.data
            }
        })
    };
     */

    let infos = [
        {
            image: 'img/001.png',
            title: '小猫'
        },
        {
            image: 'img/002.png',
            title: '蛋糕'
        },
        {
            image: 'img/003.png',
            title: '蓝糕'
        },
        {
            image: 'img/004.png',
            title: '恶犬'
        },
    ];

    let info = {
        template: `
        <div class="info">
            <img :src="myinfo.image" alt="">
            <p><b>{{ myinfo.title }}</b></p>
        </div>
        `,
        // 3) 在子组件实例中,通过props实例成员获得自定义属性
        props: ['myinfo']
    };

    // 数据交互 - 父传子 - 通过绑定属性的方式
    // 1) 父组件提供数据
    // 2) 在父组件模板中,为子组件标签设置自定义属性,绑定的值有父组件提供
    // 3) 在子组件实例中,通过props实例成员获得自定义属性
    new Vue({
        el: '#app',
        components: {
            info,
        },
        data: {
            infos,
        }
    })
</script>
</html>
View Code

2.子传父

父级先产生,然后加载子级,父级产生的信息传给子级,子级完成了一系列的数据操作之后传给父级,那就是钩子思想的运用,在子级通过emit定义一个事件,只要触发了就传给父级
// 组件交互-子传父
// 1) 数据由子组件提供
// 2) 子组件内部通过触发系统事件,发送一个自定义事件,将数据携带出来
// 3) 父组件位子组件标签的自定义属性通过方法实现,就可以通过参数拿到子组件传递处理的参数

<!DOCTYPE html>
<html lang="zh">
<head>
    <meta charset="UTF-8">
    <title></title>
    <style>
        .close:hover {
            cursor: pointer;
            color: red;
        }
    </style>
</head>
<body>
    <div id="app">
        <p>
            <input type="text" v-model="userMsg">
            <button @click="sendMsg">留言</button>
        </p>
        <ul>
            <msg-li @remove_msg="removeAction" v-for="(msg, i) in msgs" :msg="msg" :index="i" :key="msg"></msg-li>
        </ul>
    </div>
</body>
<script src="js/vue.js"></script>
<script>
    let msgLi = {
        template: `
        <li>
            <span class="close" @click="deleteMsg(index)">x </span>
            <span>第{{ index + 1 }}条:</span>
            <span>{{ msg }}</span>
        </li>
        `,
        props: ['msg', 'index'],
        methods: {
            // 系统的click事件
            deleteMsg(i) {
                // $emit('自定义事件名', 参数们)
                this.$emit('remove_msg', i);
                this.$emit('myclick', 1, 2, 3, 4, 5)
            }
        }
    };
    // 组件交互-子传父
    // 1) 数据由子组件提供
    // 2) 子组件内部通过触发系统事件,发送一个自定义事件,将数据携带出来
    // 3) 父组件位子组件标签的自定义属性通过方法实现,就可以通过参数拿到子组件传递处理的参数

    new Vue({
        el: '#app',
        data: {
            msgs: [],
            userMsg: ''
        },
        methods: {
            sendMsg() {
                if (this.userMsg) {
                    this.msgs.push(this.userMsg);
                    this.userMsg = "";
                }
            },
            removeAction(i) {
                this.msgs.splice(i, 1)
            }
        },
        components: {
            msgLi
        }
    })
</script>
</html>
留言板案例 插件版

 

posted @ 2019-11-16 15:09  www.pu  Views(2417)  Comments(0Edit  收藏  举报