vue.js

2019-05-25  本文已影响0人  Bonucci

[vuejs挂载点,模板与实例的关系]

<body>
  <div id='root'>
    <h1>{{msg}}</h1>
  </div>
  <script>
    new Vue({
      el:'#root',
      data:{
        msg:'hello world'
      }
    })
  </script>
</body>

挂载点:element对应的标签

上面的html中{{msg}}去掉

<div id='root'></div>

这个标签就称之为vue实例的挂载点,因为下面的el,也就是element正好与上面的标签的id对应的上

模板:挂载点内部的内容

<h1>{{msg}}</h1>

这个就是模板,模板也可以有多种方式

new Vue({
  el:'#root',
  template:'<h1>{{msg}}</h1>',
  data:{
    msg:'hello world'
  }
})

这种写在实例里面也可以,所以模板就是挂载点内部的内容,模板可以写在挂载点内部,也可以写在实例里面template属性里面

首先我们知道vue中有很多自定义指令,以v- 开头,例如:v-text,v-bind,v-model, v-if,等

在这些指令中,部分指令之间是很容易被混淆,所以今天决定自己总结一下以下几个相似指令之间的异同:



<!--区别:v-text打印出来包含标签 v-html不包含标签-->

<div class="root" v-text="number"></div>

<div class="root1" v-html="number"></div>

<!--点击事件用v-on方法-->

<div id="root" v-on:click="tomyclick">{{number}}</div>

<!--点击事件用@方法-->

<div id="root1" @click="tomyclick">{{number}}</div>

<script>

new Vue({

        el:".root",

        data:{

                number:"<h1>这是v-text方法</h1>"

      },

})

 

new Vue({

        el:".root1",

        data:{

                number:"<h1>这是v-html方法</h1>"

        },

})

 

new Vue({

        el:"#root",

        data:{

                number:"这是v-on:click方法"

        },

        methods:{

                tomyclick : function(){

                this.number = "点击之后的效果用v-on方法"

      }

}

})

 

new Vue({

         el:"#root1",

        data:{

                  number:"这是v-on:click方法"

        },

        methods:{

              tomyclick : function(){

                      this.number = "点击之后的效果用@方法"

              }

        }

})

</script>

</body>

image.png image.png image.png

1、属性绑定

v-bind :


<div id="root">
        <div v-bind:title="title">hello world</div>
</div>
<script>
    new Vue({
        el:"#root",
        data:{
           title:"this is hello world"
        }
    })
</script>

v-bind可以缩写为“:”

即<div v-bind:title="title">hello world</div>可以写为
<div :title="title">hello world</div>

单向绑定:数据决定页面的显示,但页面不能决定数据的内容

双向绑定:数据决定页面的显示,但页面也能修改数据的内容

用v-model实现双向绑定


<div id="root">
    <input type="text" v-model:value="content">//当修改input的值时,content的值也会做相应修改
    <div>{{content}}</div>
</div>
<script>
    new Vue({
        el:"#root",
        data:{
            content: "this is content"
             },
       
    })
</script>

image.png

2、vue中的计算属性和侦听器

2.1计算属性computed:一个属性通过其他属性计算而来

fullName由firstName和lastName计算而来.

当firstName和lastName不发生变化时,fullName不会重新计算而是调用缓存值,提高了程序效率。

 <div id="root">
        姓:<input type="text" v-model:value="firstName">
        名:<input type="text" v-model:value="lastName">
        <div>{{fullName}}</div>
        <div>{{count}}</div>
    </div>
    <script>
        new Vue({
            el: "#root",
            data: {
                firstName: '',
                lastName: '',                
            },
            //计算属性
            computed:{ 
                fullName: function () {
                    return this.firstName+" "+this.lastName
                }
            },                     
        })
    </script>

image.png

2.1侦听器watch:监听某个数据的变化,一旦数据发生变化,就可以在侦听器中进行逻辑计算


<div id="root">
        姓:<input type="text" v-model:value="firstName">
        名:<input type="text" v-model:value="lastName">
        <div>{{fullName}}</div>
 
    </div>
    <script>
        new Vue({
            el: "#root",
            data: {
                firstName: '',
                lastName: '',
                fullName: ''
            },           
            watch:{
                firstName:function () {
                    this.fullName=this.firstName+" "+this.lastName;
                },
                lastName: function () {
                    this.fullName=this.firstName+" "+this.lastName;
                }
            }
        })
    </script>

image.png

计算属性computed的getter和setter:


<div id="root">
    {{fullName}}
</div>
<script>
    var vm=new Vue({
        el: "#root",
        data: {
            firstName: 'Dell',
            lastName: 'Lee',
            fullname: 'Dell Lee'
        },
        computed:{
            fullName:{
                get: function () {
                    return this.firstName+" "+this.lastName
                },
                set: function (value) {
                    var arr=value.split(" ");
                    this.firstName=arr[0];
                    this.lastName=arr[1];
                }
            }
        }
     
    })
image.png

[vuejs里面v-if,v-show和v-for]

<div id='root'>
  <div v-if='show'>helle world</div>
  <button @click='handleClick'>toggle</button>
</div>
<script>
  new Vue({
    el:'#root',
    data:{
      show:true
    },
    methods:{
      handleClick:function(){
        this.show = !this.show;
      }
    }
  })
</script>

v-if,里面这个show是个变量,如果是true就是显示,如果是false就不显示,这里是移除了dom

<div id='root'>
  <div v-show='show'>helle world</div>
  <button @click='handleClick'>toggle</button>
</div>
<script>
  new Vue({
    el:'#root',
    data:{
      show:true
    },
    methods:{
      handleClick:function(){
        this.show = !this.show;
      }
    }
  })
</script>

v-show,把v-show替换掉v-if,表现形式一样,但是和v-if不同的是,v-show只是将dom隐藏,显示,并没有移除dom,只是把display的样式变了

如果显示的频率大,v-show比v-if要性能高一些,因为不会去销毁dom,和创建dom,如果显示的频率不是那么大,只要一次显示隐藏,那么v-if是更好的选择

<div id='root'>
  <ul>
    <li v-for='item of list' :key='item'>{{item}}</li>
  </ul>
</div>
<script>
  new Vue({
    el:'#root',
    data:{
      list:[1,2,3]
    }
  })
</script>

当你给元素标签加key值得时候, vue会知道它是页面上唯一的一个元素,如果两个key不一样,vue不会复用


v-for,当某个数据需要循环显示的时候,可以用v-for,这里需要注意加:key,可以提升性能,但是这个item变量要是唯一的,如果数组是[1,1,3],这个item就不能作为key值,需要将
v-for='item of list'
改成
v-for='(item,index) of list',
将索引index作为key值,这样是唯一的,但是index作为key值,在对列表排序等操作的时候可能存在问题
一个简单的todolist

<script type="text/javascript" src="https://cdn.staticfile.org/vue/2.2.2/vue.min.js"></script>
</head>
<body>
<div id="root">
    <div>
        <input v-model = "inputValue"/>
        <button @click = "handleSubmit">提交</button>
    </div>

    <ul>
        <li v-for = "(item , index) of list" :key = "index">{{item}}</li>

    </ul>

</div>
<script>
    new Vue({
        el:"#root",
        data:{
            inputValue:'999',
            list:[]
        },
        methods:{
            handleSubmit:function(){
                this.list.push(this.inputValue),
                this.inputValue = ''
          }
        }

    })
</script>

运用组件化的概念进行整改

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>vue学习</title>

<script type="text/javascript" src="./vue.js"></script>
</head>
<body>
    <div id = "app">
        <input type="text" v-model = "interValue"/>
        <button v-on:click = "handleBtnClick">提交</button>
        <ul>
            <!-- <li v-for = "item in list">{{item}}</li> -->
            <todo-item v-bind:content="item" v-for = "item in list"></todo-item>
        </ul>
        </button>
    </div> 
    <script>

        Vue.component("TodoItem",{
            props : ["content"],
            template : "<li>{{content}}</li>",
        })

        var app = new Vue ({
            el : '#app',
            data :{
                
                list : [],
                interValue : '' 
                
            },
            methods : {
                handleBtnClick : function(){
                    this.list.push(this.interValue)
                    this.interValue = ''
                }
            }
        })  

        setTimeout(function()  {
            app.$data.content = '我要改变'
            // app.content = '我要改变';

        }, 2000)
    </script>
</body>
</html>

需要注意四点就是
1.Vue.component 这样使用的是全局组件
2.TodoItem 到节点运用就成了todo-item
3.v-bind:content="item" 父组件把值传给子组件

  1. props : ["content"]这样接受

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>vue学习</title>

<script type="text/javascript" src="./vue.js"></script>
</head>
<body>
    <div id = "app">
        <input type="text" v-model = "interValue"/>
        <button v-on:click = "handleBtnClick">提交</button>
        <ul>
            <!-- <li v-for = "item in list">{{item}}</li> -->
            <todo-item v-bind:content="item"
            v-bind:index="index"
             v-for = "(item, index) in list"
             @delete = "handleItemDelete"
             ></todo-item>
        </ul>
        </button>
    </div> 
    <script>

        // Vue.component("TodoItem",{
        //     props : ["content"],
        //     template : "<li>{{content}}</li>",
        // })
        var TodoItem = {
            props : ["content","index"],
            template : "<li @click = 'handleItemClick'>{{content}}</li>",  
            methods : {
                handleItemClick : function(){
                    this.$emit('delete',this.index)
                },
            }
        }

        var app = new Vue ({
            el : '#app',
            components :{
                TodoItem : TodoItem,
            },
            data :{
                
                list : [],
                interValue : '' 
                
            },
            methods : {
                handleBtnClick : function(){
                    this.list.push(this.interValue)
                    this.interValue = ''
                },
                handleItemDelete : function(index){
                    this.list.splice(index,1)
                }
            }
        })  

        setTimeout(function()  {
            app.$data.content = '我要改变'
            // app.content = '我要改变';

        }, 2000)
    </script>
</body>
</html> 

需要注意四点就是
1var TodoItem 这样使用的是局部组件,创建了一对象
2.components :{
TodoItem : TodoItem,
},
把局部组件注册到根实例里面。
3.template : "<li @click = 'handleItemClick'>{{content}}</li>", 这里是列表cell添加点击事件
4.@delete = "handleItemDelete" 这里父组件在创建子组件的时候进行监听

  1. this.emit('delete',this.index) 子组件像父组件传递被删除的信号 6.this.list.splice(index,1)从下标进行删除1 7.v-bind:index 可以简写为 :index 8.v-on:click 可以简写为 @click 9,凡是以开头的都是vue的实例属性跟实例方法

生命周期函数就是vue的实例在某一个时间点会自动执行的函数。生命周期函数并不在methosd,单独写在实例里。
init-->beforeCreate -->created--> beforeMount -->mounted -->beforeDestroy -- >destroyed


image.png
image.png image.png

大图解析,


image.png

v-xxx=""后面的字符串是js表达式。可以+操作


var vm = new Vue({
    el: '#example',
    data: {
        message: 'Hello'
    },
    computed: {
        reversedMessage: function () {
            // `this` 指向 vm 实例
            return xxxx
        }
    }
});

关于计算属性优点就是他能缓存,提高性能,页面重新渲染的,计算属性依赖的值给没有发生改变,这个时候计算属性就不会计算,提高性能.用方法的形式也可以实现计算的结算,但是页面只要渲染方法就会调用,用监听器也可以实现这个功能,也会有缓存。


image.png
<!DOCTYPE html>
<html lang="en">
<head>
    <meta content="text/html; charset=utf-8" />
    <title>Vue</title>
    <script src="./vue.js"></script>
</head>
<body>
    <div id="root">{{fullName}}</div>

    <script>
        var vm = new Vue({
            el : '#root',
            data :{
                firstName : 'Dell',
                lastName : 'Lee'
            },
            computed :{
                fullName : {
                    get :function (){
                        return this.firstName + " " +this.lastName
                    },
                    set :function(value){
                        console.log(value);
                        var array = value.split(" ");
                        this.firstName = array[0];
                        this.lastName = array[1];
                    }
                }

            }

        })
    </script>
</body>
</html>

计算属性跟set跟get方法


<!DOCTYPE html>
<html lang="en">
<head>
    <meta content="text/html; charset=utf-8" />
    <title>Vue</title>
    <script src="./vue.js"></script>
    <style>
        .acivated{
            color: red
        }
    </style>
</head>
<body>

    <div id="root" :class = "[acivated]" @click = "handleClick">{{content}}</div>
    <script>
        var vm = new Vue({
            el : '#root',
            data : {
                content : '我是内容',
                acivated : ''
            },
            methods : {
                handleClick : function(){
                    this.acivated = this.acivated === "acivated" ? "" : "acivated";
                }
            }
        })
    </script>
</body>
</html>

知识点
1.:class = "[acivated]" 这里主要是表示class这块的东西,这是一个数组可以添加多个,样式就有这个数组里面的东西决定。


image.png

同样的东西,这里是style的用法,可以在 :style = "[styleObj {fontSize : '20px'}]"



如果是按照数组下标的方法进行操作数组,页面没有及时渲染,想要及时渲染,要用系统提供的七个方法。
push pop shift unshift splice sort reverse

当然你也可以直接替换数据的引用地址,这样也能改变渲染。

还有一个方法就是用set修改,也可数据改变之后页面也改变

Vue.set(vm.userInfo,1,5)


一个比较重要的模板占位符 template 可以包裹 元素,但是 渲染的时候并不会真正的渲染到页面中。


image.png image.png

直接修改vm.userInfo.name = "Dell Lee"可以在页面中立刻渲染
但是想添加 vm.userInfo.address = "beijing" 这样数据是添加进去了,但是不能立即渲染。
想立即改变要直接改变数据引用地址,就是直接改好数据,直接把引用引到新数据下面。
其实用set方法修改,也能让数据改变之后页面也立刻改变。
例如 Vue.set(vm.userInfo,"address","beijing")

vue遇到问题解析
1.有些时候自定义的标签在使用起来发现出问题了,table--> tbody -->tr就是tbody下面必须是tr标签,要不就就会出问题,这个时候要做的是用 is=“”来处理


image.png

2.子组件的data必须是一个函数不能是一个对象.


image.png
3,添加ref 添加引用,便于操作dom节点
<!DOCTYPE html>
<html lang="en">
<head>
    <meta content="text/html; charset=utf-8" />
    <title>Vue</title>
    <script src="./vue.js"></script>
</head>
<body>

    <div id="root">
        <couter ref = "one" @change = "handeleChange"></couter>
        <couter ref = "two" @change = "handeleChange"></couter> 
        <div>{{total}}</div>  
    </div>
    <script>
        Vue.component('couter',{
            template : '<div @click = "handleClick">{{number}}</div>',
            data :function(){
                return {
                    number : 0
                }
            },
            methods :{
                handleClick : function(){
                    this.number ++;
                    this.$emit('change')
                }
            }

        })


        var vm = new Vue({
            el : '#root',
            data : {
                total : 0
            },
            methods : {
                handeleChange : function(){
                    this.total = this.$refs.one.number + this.$refs.two.number
                }
            }
        })
    </script>
</body>
</html>

涉及到父子组件传值的概念
单向数据流:父组件给子组件传递参数,传递过得参数可以随意修改,但是子组件不能修改父组件传递过来的内容。原因传递过来的数据如果是引用数据类型的数据,如果你修改了 数据就是修改了原始数据。

校验器


image.png

@click.nataive 这个就是监听的原生的click事件,并非自定义的

非父子组件进行传值


image.png

created:在模板渲染成html前调用,即通常初始化某些属性值,然后再渲染成视图。
mounted:在模板渲染成html后调用,通常是初始化页面完成后,再对html的dom节点进行一些需要的操作。
var this_ = this 是因为作用域发生了变化,有一个function,this变成了function了
,要保存一下


插槽语法,方便插入dom元素,还可以定义默认内容 ,还能给插槽给一个name,这样可以对应,根据name变换插槽


image.png

动态组件

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Vue 测试实例 - 动态组件</title>
<script src="https://cdn.bootcss.com/vue/2.2.2/vue.min.js"></script>
</head>
<body>
<div id="app">
    <button @click='toShow'>点击显示子组件</button>
    <!----或者<component v-bind:is="which_to_show" keep-alive></component>也行----->
    <keep-alive>
    <component v-bind:is="which_to_show" ></component>
    </keep-alive>
</div>
 
<script>
 
// 创建根实例
new Vue({
  el: '#app',
  data:{
      which_to_show:'first'
  },
    methods:{
        toShow:function(){
            var arr = ["first","second","third"];
            var index = arr.indexOf(this.which_to_show);
            if(index<2){
                this.which_to_show = arr[index+1];
            }else{
                this.which_to_show = arr[0];
            }  console.log(this.$children); 
        }
    },
    components:{
        first:{
            template:'<div>这是子组件1<div>'
        },
        second:{
            template:'<div>这是子组件2<div>'
        },
        third:{
            template:'<div>这是子组件3<div>'
        },
    }
})
</script>
</body>
</html>


image.png

v-once 指令,可以让把组件第一次被渲染之后会放到内存里面


image.png image.png
image.png

这个东西很有意思,这边整体解释一下动画的东西,首先就是fade-enter 跟fade-enter-active在动画开始的第一帧就已经存在,然后第二帧的时候 fade-enter 被干掉,增加fade-enter-to ,到结束之后这个时候fade-enter-active,fade-enter-to被干掉。与opacity:0这个被去掉,恢复原有的默认属性,为1.此时,监听到opacity变化,fade-enter-active开始运行,会做一个渐变。

上一篇下一篇

猜你喜欢

热点阅读