Vue框架

第1章 Vue基础语法

创建一个Vue实例

把vue.js放在head标签里用script标签引入,避免放在body里引起抖屏。

1552395200.jpg

引入vue.js库,用new Vue()函数创建一个实例
- el:让vue实例去接管页面上哪一个元素
- data:vue实例的数据放在这里面

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Vue入门</title>
    <script src="./vue.js"></script>
</head>
<body>
    <div id="root">{{msg}}</div>

    <script>
        new Vue({
            el:"#root",
            data:{
                msg:'hello world'
            }
        })
    </script>
</body>
</html>

挂载点,模板与实例

  • 挂载点
    挂载点就是vue里的el属性对应的dom节点。
    div标签称为vue实例的挂载点,因为el正好和div标签的id对上,vue只会处理挂载点下面的内容。
  • 模板
    挂载点内部的内容都叫模板内容。
    <div id="root">
        <h1>hello {{msg}}</h1>//模板内容
    </div>

模板除了可以放在挂载点后面写之外,还可以放在vue实例里面写:

    <script>
        new Vue({
            el:"#root",
            template:'<h1>hello {{msg}}</h1>',//模板内容
            data:{
                msg:'world'
            }
        })
    </script>

Vue实例中的数据,事件与方法

  • 插值表达式
<h1>hello {{msg}}</h1>
{{mynumber}}//插值表达式
  • v-text(会进行一次转义输出纯文本)
    语法:v-text="",双引号是划定界限的符号。
<h1 v-text="mynumber"> </h1>

h1的内容由mynumber这个变量决定,v-text是vue的一个指令
,告诉h1要显示的就是mynumber这个变量。

    <div v-text='msg'></div>

    </div>
    <script>
        new Vue({
            el:"#root",
            data:{
            msg:"<h1>hello</h1>"
v-text显示内容
  • v-html(不会转义)
    语法:v-html="",双引号是划定界限的符号。
    <div id="root">
        <h1 v-text="msg"></h1>
    </div>
    
    <script>
        new Vue({
            el:"#root",
            data:{
                msg:"<h1>hello</h1>"
            }
        })
    </script>

显示内容


v-html显示的内容
  • v-on模板指令
    语法:v-on:事件名称="函数(方法)",v-on:可以简写为@,给模板上的标签绑定事件。
//点击hello,hello变成world
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Vue入门</title>
    <script src="./vue.js"></script>
</head>
<body>

    <div id="root">
        <h1 v-text="content" @:click="handleClick"></h1>
        /*给标签绑定一个handleClick事件*/
    </div>
    
    <script>
        new Vue({
            el:"#root",
            data:{
                content:"hello"
            },
            methods:{//把函数定义在vue实例的methods属性下
                handleClick: function(){
                    this.content = 'world'
                }
            }
        })
    </script>
</body>
</html>

Vue中的属性绑定和双向数据绑定

  • v-bind:指令简写为“:”,把div标签的title属性和title数据项绑定
    语法:v-bind:属性="数据项"

    注意:""里面放的不再是字符串,而是JS表达式(里面可以放字符串也可放变量)。
<script src="./vue.js"></script>
</head>
<body>

    <div id="root">
        <div v-bind:title="mydata">hello world</div>
    </div>
    
    <script>
        new Vue({
            el:"#root",
            data:{
                mydata:"this is hello world",
            }
        })
    </script>
  • v-model双向数据绑定
    语法:v-model=""
    单向绑定:数据决定页面的显示,页面无法决定数据里的内容。
    双向绑定:互相决定
    <script src="./vue.js"></script>
</head>
<body>

    <div id="root">
        <div :title="title">hello world</div>
        <input v-model="content"/>
        <div>{{content}}</div>
    </div>
    
    <script>
        new Vue({
            el:"#root",
            data:{
                title:"this is hello world",
                content:"this is a content"
            }
        })
    </script>
image.png

Vue中的计算属性和侦听器

  • computed计算属性

  • watch监听数据变化
    监听数据或者属性的变化

    <script src="./vue.js"></script>
</head>
<body>

    <div id="root">
        姓:<input v-model="firstName">
        名:<input v-model="lastName">
        <div>{{fullName}}</div>
fullName定义在Vue实例computed属性中,是一个计算属性,通过别的属性
计算出来的 
好处是若计算该属性的属性没有改变,每一次使用该属性的时候,会使用试一
次的缓存结果
fistName和lastName没变,重新使用fullName的时候不会重新计算,而是
使用上一次的缓存结果
        <div>{{count}}</div>
    </div>
    
    <script>
        new Vue({
            el:"#root",
            data:{
                firstName:'',
                lastName:'',
                count:0
            },
            computed:{
                fullName:function(){
                    return this.firstName+' '+this.lastName
                }
            },
监听某一个数据的变化,一旦数据发生变化,就可以在
侦听器里执行相应的逻辑
            watch:{
                firstName:function(){
                    this.count ++
                },
                lastName:function(){
                    this.count ++
                }
            }
        })
    </script>

v-if,v-show与v-for指令

  • v-if 控制dom存在与否,一次性操作选v-if
    语法:v-if="数据"
  • v-show控制dom显示与否,多次操作选v-show
  • v-for控制一组数据,循环显示在页面上
    语法:v-for=“(item,index) of items” :key="index"
    一般 js for in 是遍历 key, 而 for of 遍历 value。在 vue 里面应该没区别
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>v-if,v-show,v-for 指令</title>
    <script src="./vue.js"></script>
</head>
<body>
    <div id="root">
v-if控制div标签删除与否,当show为true时删除dom结构,不显示hello
        <div v-if="show">hello world</div>
        <button @click="handleClick">tonggle</button>
        <ul>
v-for循环显示出list列表里的值,:key值能更好的渲染,每次的key
值不能相同
<li v-for="(item,index) of list" :key="index">{{item}}</li>
        </ul>
    </div>
    <script>
        new Vue({
            el:"#root",
            data:{
                show: false,
                list:[1,2,3]
            },
            methods:{
                handleClick:function(){
                    this.show = !this.show;
                }
            }
        })
    </script>
</body>
</html>

第1章总结

Vue模板指令 语法 用处
v-text v-text=" ",双引号是划定界限的符号 把数据作为文本输出
v-html v-html=" " 不转义数据并输出
v-on v-on:事件名称="函数(方法)",v-on:可以简写为@, 给模板上的标签绑定事件
v-bind v-bind:属性="数据项",简写为“:” 进行属性绑定
v-model v-model="" 双向数据绑定
v-if v-if="数据" 控制dom存在与否,一次性操作选v-if
v-show v-show="数据" 控制dom显示与否,多次操作选v-show,
v-for v-for=“(item,index) of items” :key="index" js for in 是遍历 key, 而 for of遍历value。在 vue 里面应该没区别 控制一组数据,循环显示在页面上

Vue属性 格式 用处
el el: 指定挂载点
data data:{} 存放vue实例的数据
methods methods:{} 定义函数,它需要手动调用才能执行,而不像computed那样,可以自动执行预先定义的函
computed computed:{} 计算属性是以Vue的依赖追踪机制为基础的,其试图处理这样的一件事情:当某一个数据(依赖数据)发生变化的时候,所有依赖这个数据的相关数据会自动发生变化,也就是自动调用相关的函数去实现数据的变动
watch watch:{} 监听数据或者属性的变化

第2章、Vue中的组件

TodoList功能开发

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
    <script src="./vue.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:'',
                list:[]
            },
            methods:{
                handleSubmit: function(){
调用push方法让list中增加一个数据
                    this.list.push(this.inputValue)
                    this.inputValue=""
                }
            }
        })
    </script>
</body>
</html>
image.png

TodoList中的组件拆分

  • 组件:页面中的某一部分
  • 创建全局组件
    把<li>标签拆分成组件进行管理
  1. 通过Vue.component创建的组件叫做全局组件。在任何地方的模板里都可以使用
  2. 调用全局组件的时候可以通过属性传参,属性的名字可以随便取,不一定非得叫content,此处的属性等于循环的每一项内容item,通过此法,可以把content传给todoitem组件,传了之后不能直接使用,子组件必须先接受,用props接受从外部传进来的属性。如下:
<todo-item v-for="(item,index) of list" :key="index" :content="item"></todo-item>
        <ul>
            <todo-item></todo-item>//在此用组件
        </ul>
    Vue.component('todo-item',{
        props:['content'],
        template:'<li>{{content}}</li>'
    })
  • 创建局部组件
    不能直接在父组件的模板里调用,必须在Vue实例中通过components先声明
//var TodoItem里有个对象,对象里有个模板。
    var TodoItem={
        template:'<li>item</li>'
    }
new Vue({
            el:"#root",
            components:{
                'todo-item':TodoItem
            },
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
    <script src="./vue.js"></script>
</head>
<body>
    <div id="root">
        <div>
            <input v-model="inputValue" />
            <button @click="handleSubmit">提交</button>
        </div>
        <ul>
            <todo-item 
                v-for="(item ,ndex) of list" 
                :key="index"
                :content="item"
                ><!-- //父组件通过属性的形式给子组件todo-item传参 -->
            </todo-item>
        </ul>
    </div>

    <script>

//创建组件的方法,通过Vue.component定义的组件叫做全局组件,
//在任何地方模板里都可以使用
        Vue.component("todo-item", {
            props: ['content'],
//组件接受从外部传进来的一个叫content的属性
            template: '<li>{{content}}</li>'
//定义一个组件叫todo-item,其内容是item
        })


//局部组件,如果想在Vue实例模板里调用,需要在最外层的Vue
//实例里通过components声明
        // var TodoItem = {
        //  template: "<li>item</li>"
        // }



        new Vue({
            el:"#root",
            // components:{
            //  'todo-item':TodoItem
            // },
            data:{
                inputValue:'',
                list:[]
            },
            methods:{
                handleSubmit: function(){
                    // 调用push方法让list中增加一个数据
                    this.list.push(this.inputValue)
                    this.inputValue=""
                }
            }
        })
    </script>
</body>
</html>

组件与实例的关系

每一个vue的组件又是一个Vue的实例,组件就是实例,实例就是组件。所以任何一个Vue项目都是由千千万万个Vue实例组成的

     Vue.component('todo-item',{
        props:['content'],
         template:'<li @click="handleClick">{{content}}</li>',
         methods:{
            handleClick:function(){
                alert('clicked')
            }
         }
     })

实现效果:


1552570175(1).jpg

每一个组件里可以写methods等,证明每一个组件都是vue的实例

实现TodoList的删除功能

在Vue中父组件向子组件传值是通过属性进行的。要实现子组件的删除,必须在父组件里,把子组件对应的数据删除。vue里通过发布订阅模式实现子组件和父组件的通信。
父组件循环显示子组件的时候,可以额外在加一个参数等于循环的下标

<todo-item v-for="(item,index) of list" 
:key="index" 
:content="item" 
:myindex="index"></todo-item>

子组件在content之后再加一个myindex,意思是除了从父组件接受到content之外还可以接受到下标。

Vue.component('todo-item',{
        props:['content','myindex'],
         template:'<li @click="handleClick">{{content}}</li>',
         methods:{
            handleClick:function(){
                            }
         }
     })

当子组件被点击的时候,通知父组件,通过调用this.$emit(' ')方法,触发一个自定义的delete事件,事件中携带了下标值。

         methods:{
            handleClick:function(){
            this.$emit('delete',this.myindex)
            }
         }

父组件监听子组件向外触发的事件,监听到之后,执行handleDelete函数,函数中可以接收到一个传递过来的参数子组件传递过来的下标,在父组件中写一个handleDelete函数,把父组件list对应的下标内容删除,通过this.list.splice(myindex,1)从对应下标位置删除掉一项。

        new Vue({
            el:"#root",
            data:{
                inputValue:'',
                list:[]
            },
            methods:{
                handleSubmit:function(){
                    this.list.push(this.inputValue),
                    this.inputValue=''
                },
                handleDelete:function(myindex){
                    this.list.splice(myindex,1)
                }
            }
        })

全代码

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Todolist</title>
    <script src="./vue.js"></script>
</head>
<body>
    <div id="root">
        <div>
            <input v-model="inputValue"/>
            <button @click="handleSubmit">提交</button>
        </div>
        <ul>
            <todo-item v-for="(item,index) of list" 
            :key="index" 
            :content="item" 
            :myindex="index"
            @delete="handleDelete"
            ></todo-item>
        </ul>
    </div>
    <script>



     Vue.component('todo-item',{
        props:['content','myindex'],
         template:'<li @click="handleClick">{{content}}</li>',
         methods:{
            handleClick:function(){
            this.$emit('delete',this.myindex)
            }
         }
     })

        new Vue({
            el:"#root",
            data:{
                inputValue:'',
                list:[]
            },
            methods:{
                handleSubmit:function(){
                    this.list.push(this.inputValue),
                    this.inputValue=''
                },
                handleDelete:function(myindex){
                    this.list.splice(myindex,1)
                }
            }
        })
    </script>
</body>
</html>

总结

父组件通过属性的方式向子组件传递参数;子组件通过发布订阅模式的方式向父组件传递参数。##

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,907评论 6 506
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,987评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,298评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,586评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,633评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,488评论 1 302
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,275评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,176评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,619评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,819评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,932评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,655评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,265评论 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,871评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,994评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,095评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,884评论 2 354

推荐阅读更多精彩内容

  • 这里有基类Animal和子类Dog,现在执行下列代码: 在这种情况下,a是无法直接访问color字段的,而d1可以...
    Rimson阅读 116评论 0 0
  • “哎你怎么在这里?”就像被打翻了五味瓶一样,其实我更想说“你特么为什么当初不告而别你知道我多伤心吗你大爷的二舅子的...
    梦若尘阅读 364评论 1 0