Vue

Vue.js

vue.js前端主流框架,一套用于构建用户界面的渐进式框架,研发者尤雨溪
vue.js的引入
在这里插入图片描述


构建用户界面:ui html css 静态页面
渐进式框架:延伸出来有五部分
   1.模板引擎 类似于pug nunjucks
   2.组件(核心功能之一),增加页面的复用性
   3.路由
   4.状态管理器(统筹管理属性-可伸缩性)
   5.自动化构建


#模板引擎

三个核心:
  1.el 挂载点
  2.template 模板(最终形成用户界面的原始结构)
  3.data 数据
vue将data和template相结合,最后添加到挂载点上

  new Vue({
                el: '#app',
                template:`

                    <h1>{{title}}</h1>
                `,
                data:{
                    title:'未来可期'
                }
            })

1.在模板生成后,会替换掉挂载点指定的元素

  new Vue({
            el:'#app',
            template:`
            <div id="app">
                <h1>未来可期</h1>
                </div>
            `,
        })

2.每个独立的模板有且只能有一个顶级的根节点

 new Vue({
            el:'#app',
            template:`
            <div id="app">
                <h1>未来可期</h1>
                </div>
                <h1>{{name}}</h1>
            `,
        })

3.如果有指定的el而没有template,那么el中的outerHTML将作为template
 如果有template,则会优先选择template中的内容

new Vue({
            el:'#app',
            data:{
                name:'dsadd'
            }
        })

vue渲染
template→加载到VDOM(虚拟dom,与dom规则一致)→将结果返还给html页面

vue的render函数
 渲染的方式有两种,template和render
 render是字符串模板的代替方案,允许我们发挥JavaScript最大的编程能力,该写法相对复杂
 该渲染函数接收一个 createElement方法作为第一个参数用来创建Vnode
 这个createElement名字可自定义,它就是上面所说的虚拟DOM
 createElement()有三个参数
   参数1:元素或标签名
   参数2:属性
   参数3:内容 可以是一个数组也可以是一个字符串

 new Vue({
            el:'#app',
            render(i){
                // return i('h1','1906');
                return i('div',{attrs:{id:'app'}},[
                        I('h1',{attrs:{id:'h'}},'1906')
                ]);
            }
        });

render依然会覆盖掉挂载点el,可通过重新创建一个一样的元素来解决这个问题

延迟挂载
实例化Vue时没有设置el挂载点的挂载方式
指定挂载点
1.el 挂载点不能是body和html
2.当实例被挂载以后,实例对象上就会有一个 e l 的 属 性 , 这 个 属 性 中 存 的 内 容 就 是 挂 载 的 元 素 3. v u e 实 例 上 的 内 置 属 性 都 是 以 el的属性,这个属性中存的内容就是挂载的元素 3.vue实例上的内置属性都是以 el,3.vue或者_开头的,加上会被认为是内置属性

 let app= new Vue({
             template:`
                    <div id="app">
                        <h1>未来可期</h1>
                        </div>
                    `,
         })
            
         //指定挂载点
         // 1.el 挂载带点 不是能body 和 html 
         // 2.当实例化被以后,实例化对象上就会有一个$el 的属性,这个属性中存的内容,就是挂载的元素
         // 3.vue 实例上的内置属性都是以$或——开头的
         app.$mount('#app');

data
1.在当前模板中可以直接使用(不需要去使用this一类的关键字)
2.data中的数据命名不要使用$或_开头
 因为Vue解析data以后,会把当前data中的数据加载到 实例对象中

   new Vue({
            el:'#app',
            template:`
            <div id="app">
                <h1>未来可期</h1>
                </div>
             
            `,
        })

这里是引用视图更新
 响应数据的变化(原理是数据驱动视图)
 数据的变化会自动更新视图 根据数据劫持

let app = new Vue({
                el: '#app',
                data:{
                    title:'未来可期'
                }
            })

数据劫持
 Object.defineProperty() 该方法只能监听某个对象中的某个属性
  参数1:被监听的对象
  参数2:被监听对象的属性
  参数3:被监听的属性发生改变时调用的方法,以对象的形式传入set(){}和get(){}
      每当数据发生改变时将新的值赋值给被监听的属性,但因为方法问题,会陷入死循环
      所以需要一个数据,来代替被监听对象
 流程:当被监听的属性发生改变时,会赋值给替代数据,然后渲染视图,渲染视图时会去找被监听的属
    性,运行get()事件

  let $data = {x:1}
            //数据劫持一变相数据监听
            Object.defineProperty(obj,'x',{
                set(i){
                    $data.x = i;
                    render();
                },
                get(){
                    return  $data.x ;
                }
            });

无法对新增的属性进行监听
 只有更新已有属性时,才能更新未被监听的属性

      
     let app = document.querySelector('#app');
        
     function render(){
         console.log('渲染开始-');
         app.innerHTML = obj.x + "/" + obj.age;
     }
            let obj ={
                x :1
            }

            //问题 无法对新增的属性进行监听(之能监听一个)
            Object.defineProperty(obj,'age',{
                set(i){
                    $data.age = i;
                    render();
                },
                get(){
                    return  $data.age ;
                }
            });

在模板中,如果我们使用了一个不存在的数据,需要一个方法来添加这个属性
Vue.set()或实例.$set()方法可以添加属性并监听该属性

<body>
    <div id="app">
        <h1>x: {{obj.x}}</h1>
        <h1>y: {{obj.y}}</h1>
    </div>

    <script>
         let app =new Vue({
             el:"#app",
             data:{
                 obj:{
                     x:1
                 },
             }
         })
         app.$set(app.obj,'y','2');
    </script>
</body>

以下的操作中并不会触发监听拦截
  属性新增属性
  数组方法:push、pop、shift、unshift、splice、sort、reverse
  数组新增值:[ ]
  数组 length 属性
vue 对数组中的 push、pop 等方法进行重新包装,所以在 vue 中调用这些方法,可以对数组的修改进行监听拦截

<body>
    <div id="app">
        <h1>x: {{obj.x}}</h1>
        <h1>y: {{obj.y}}</h1>
        <p>{{arr}}</p>
    </div>

    <script>
         let app =new Vue({
             el:"#app",
             data:{
                 obj:{
                     x:1
                 },
                 arr:[1,2,3]
             }
         })
         app.$set(app.obj,'y','2');
    </script>
</body>
  • 指令

表达式的值除了可以出现内容中,也可以使用在其它位置,比如:属性。但是不能使用 {{}} 语法,而是需要 指令
 在 vue 中,指令是一个带有 v- 前缀的属性,与普通属性不一样的地方在于,指令的值是引号括起来的 表达式,不同的指令有不同的作用,vue 内置了一些常用的指令,后期我们还可以自定义属于自己的指令
 常用指令:内容输出,循环,逻辑,属性绑定,事件,其它
 指令格式: v-指令名称 = 表达式(而不是普通的字符串)

内容输出
1.v-text
这个方法有一个弊端,他会替换掉所有的内容,相当于innerHTML

						<div id="app" v-text="x">
					     	<div>{{}}</div>
					    </div>
					     <script>
			       
					        new Vue({
					            el:'#app',
					            data:{
					         		x:123
					            }
					        })
					    </script>

2.v-html 它会将内容当作一个html标签来解析
 为了防止 xss 攻击,默认情况下输出是不会作为 html 解析的,通过 v-html 可以让内容作为 html 进行解析

		 <div id="app"">
		 		<div>{title}}</div>
		        <h1 v-text = 'title'></h1>
		        <p v-html='title'></p>
		    </div>
				 <script>
				      new Vue({
				            el:'#app',
				            data:{
				                x:123,
				  			    title:'<div>是我</div>',       
				            }
				        })
				    </script>

3.v-cloak 不需要表达式
 这个指令保持在元素上直到关联实例结束编译
 编译结束时效果失效
4.v-once 不需要表达式
 只渲染元素和组件一次,后期的更新不再渲染,会被视为静态内容并跳过
 用于优化更新性能


					 <div id="app"">
					 		<div>{x}}</div>
					       <div v-once>{{x}}</div>
					    </div>
					 <script>
				      new Vue({
				            el:'#app',
				            data:{
				                x:123,
				  			         
				            }
				        })
				    </script>

5.v-pre 不需要表达式
 忽略这个元素和它子元素内容的编译,显示原始的标签
 跳过大量没有指令的节点会加快编译

					<div id="app">
					 	<div>猜猜我是谁{x}}</div>
					    <div v-pre>2222222{{x}}</div>
					</div>
					 <script>
				      new Vue({
				            el:'#app',
				            data:{
				                x:"冲",    
				            }
				        })
				    </script>

逻辑处理

v-show

根据表达式的值(布尔值),切换元素的显示与隐藏(display 属性)
适用于状态切换比较频繁的情况

    <div id="app">
        <div v-show='islogin'>隐藏数据</div>
    </div>
    
    <script>
        let app = new Vue({
            le:'#app',
            data:{
                islogin:false
            }
        })
    </script>

v-if

根据表达式的值(布尔值),创建或销毁元素

v-else / v-else-if

v-else 配合

    <div id="app">
        <!-- v-if与v-else以及v-else-if之间必须是链接的,中间不能出现其他元素 -->
        <!-- vif改变的是元素的结构 (渲染或者删除)适用于状态切换不频繁的场景 --->
        <div v-if='islogin'>数据暴漏</div>
        <div v-else>please login</div>
    </div>

循环与列表

v-for

根据数据循环渲染 v-for 指令所在的元素及其子元素

可以循环的数据:Array | Object | number | string | Iterable (2.6 新增)

    <!-- 指令中的循环 -->
    <div id="app">       
        <ul>
            <!-- 也可以使用in作为连接词,两者在vue中无区别   -->
            <li v-for = 'user of users'>
                 <input type="checkbox">
                {{user.id}} - {{user.name}}
            </li>
        </ul>
    </div>
    <script>
        let app = new Vue({
            el:'#app',
            data:{
                users:[
                    {id:1,name:'犯罪@嫌疑人——张三'},
                    {id:2,name:'卑微@受害者——张四'},
                    {id:3,name:'隔壁@单身汉——王五'},
                    {id:4,name:'邻居@帅帅帅——八块'},
                ],
            }
        })
    </script>

:key

默认情况下,在渲染 DOM 过程中使用 原地复用 ,这样一般情况下会比较高效,但是对于循环列表,特别是依赖某种状态的列表,会有一些问题,我们可以通过 :key 属性,来给每个循环节点添加一个标识

   <!-- 指令中的循环 -->
    <div id="app">
        <ul>
            <li v-for = 'user of users' :key='user.id'>
                 <input type="checkbox">
                {{user.id}} - {{user.name}}
            </li>
        </ul>
        <div v-for='(val,name,index) in object'>
            <span>索引值:{{index}}</span>
            <span>属性名:{{name}},值:{{val}} </span>>
        </div>
    </div>
		  let app = new Vue({
            el:'#app',
            data:{
                users:[在这里插入代码片
                    {id:1,name:'犯罪@嫌疑人——张三'},
                    {id:2,name:'卑微@受害者——张四'},
                    {id:3,name:'隔壁@单身汉——王五'},
                    {id:4,name:'邻居@帅帅帅——八块'},
                ],
                object:{
                    x:'a',
                    y:'b',
                    z:'c'
                }
            }
        })

属性绑定

v-bind

绑定数据(表达式)到指定的属性上,<div v-bind:参数="值/表达式"></div>,这里的参数就是指定的属性名称

    <div id="app">
        <div v-bind:class="myclass"></div>
        <div :id="Id"></div>
    </div>
    <script>
            v-指令参数: 参数= '指令的值'
            简写:
             :=> v-bind
        let app =new Vue({
            el:"#app",
            data:{
                myclass:"box",
                Id:'haha'
            }
        });
    </script>

属性绑定 v-bind

绑定数据(表达式)到指定的属性上,<div v-bind:参数="值/表达式"></div>,这里的参数就是指定的属性名称

样式 tyle

针对样式属性,v-bind 值有一些特殊的写法
原生普通写法

    <div id="app">

        <!-- 原生写法 -->
        <!-- <div style = "width: 100px ;height: 100px;"></div> -->

          <!-- v-bind -->
        <div :style='style1'></div>

        <!-- 数组写法
        :style 获取的是具体的样式
        :class  获取的是类名 -->

        <div :class="box"></div>
        <div :style='[style1,style2]'></div>
            <!-- 对象写法 -->
        <div :class="{'box1' : new_box,'box2':two_box}"></div>

    </div>
    <script>
						let app = new Vue({
						    el:"#app",
						    data:{
						        style1:{
						            width:'100px',
						            height:'100px',
						            background:'red'
						        },
						       style2:{
						            // width:'100px',
						            // height:'100px',
						           border: "1px solid black"
						       },
						       box:"dahua",
						       new_box:false,
						       nwo_box:false
						    }
						    
						})
    </script>

单向数据流

通过上面的知识点和案例,我们可以看到,当数据更新的时候,页面视图就会更新,但是页面视图中绑定的元素更新的时候,对应的数据是不会更新的

单项数据流
v-bind 单向数据绑定 数据到视图

        v-model: 双向数据绑定: 数据=> 视图 , 视图=>数据
    
        不上=是所有的标签(组件)都支持 v-model
                --默认 交互元素 (input textarea,)
            不是所有的属性都支持 v-model
            -- v-model 只能绑定一个指定好的属性
            input :value
            textarea ;value
            select :selected

        非交互 ; div  p  img 等静态类标签(不需要统计信息的)
			   <div id="app">
			        <!-- 双向绑定 -->
			        <input type="text" v-model="msg">
			        <div>{{msg}}</div>
			        <br>
			        <br>
			        <!-- 单项绑定 -->
			        <input type="text" v-model="msg2">
			        <div>{{msg2}}</div>
			    </div>
				 <script>
				  let app = new Vue({
			            el:"#app",
			            data:{
		                msg:"123",
		                msg2:"abc"
		            }
		        });
		    </script>

v-on
用法:
 绑定事件监听器 事件类型由参数指定
 表达式可以是一个方法的名字或一个内联语句,如果没有修饰符也可以省略
修饰符:
 .stop - 调用 event.stopPropagation()。
  .prevent - 调用 event.preventDefault()。
  .capture - 添加事件侦听器时使用 capture 模式。
  .self - 只当事件是从侦听器绑定的元素本身触发时才触发回调。
  .{keyCode | keyAlias} - 只当事件是从特定键触发时才触发回调。
  .native - 监听组件根元素的原生事件。
  .once - 只触发一次回调。
  .left - (2.2.0) 只当点击鼠标左键时触发。
  .right - (2.2.0) 只当点击鼠标右键时触发。
  .middle - (2.2.0) 只当点击鼠标中键时触发。
  .passive - (2.3.0) 以 { passive: true } 模式添加侦听器

指令修饰符

格式:指令名称:参数.修饰符=值
v-model的修饰符:
  .lazy    取代 input 监听 change 事件
  .number  将用户输入的值转换为number类型
  .trim    输入首尾空格过滤
不同的指令有不同的参数,也有不同的修饰符
注意事项:1.不同的指令下,有不同的修饰符,需要使用时,看api中对应的指令

自定义指令
一、为什么允许注册自定义指令
 vue2.0中,代码复用和抽象的主要形式是组件,但是有的情况下,仍然需要对普通dom元素进行底层操作,这是就会用到自定义指令
二、自定义指令分为全局指令和局部指令
  1.注册一个全局指令需要使用directive()方法
  
       //参数1:  指令名称
        //参数2:  配置对象(方法名不是自定义)
        Vue.directive("focus",{
        //当被绑定的元素插入到DOM 中时触发
          inserted: function (el) {
            //  console.log("我被触发了");
             el.focus();
          }
        });


	

2.注册一个局部指令

			let  app = new Vue({
			         	el:"#app",
			         	directives:{
			         	foncus:{
			         	inserted:function(el){
			         	el.focus()
				}}
		}

三、钩子函数
 存在的意义:可以让开发者灵活控制指令功能执行的时间
 一个指令定义对象可以提供如下几个钩子函数 (均为可选)
  1.bind:只调用一次,指令第一次绑定到元素时调用。在这里可以进行一次性的初始化设置。
  2.inserted:被绑定元素插入父节点时调用 (仅保证父节点存在,但不一定已被插入文档中)。
  3.update:所在组件的 VNode 更新时调用,但是可能发生在其子 VNode 更新之前。指令的值可能发生了改变,也可能没有。但是你可以通过比较更新前后的值来忽略不必要的模板更新
  4.componentUpdated:指令所在组件的 VNode 及其子 VNode 全部更新后调用。
  5.unbind:只调用一次,指令与元素解绑时调用。

 2.binding 一个对象,包含以下属性
    name:指令名,不包括 v- 前缀。
    value:指令的绑定值,
    oldValue:指令绑定的前一个值,仅在 update 和 componentUpdated 钩子中可用。无论值是否改变都可用。
    expression:字符串形式的指令表达式。
 	 arg:传给指令的参数,可选。
    modifiers:一个包含修饰符的对象。
	.oldVnode 上一个虚拟节点,仅在 update 和 componentUpdated 钩子中可用
	自定义修饰符
	自定义修饰符用于节省自定义指令的数量,以及提高适用性
	两个功能相类似,但是存在部分差异时,使用自定义修饰符

事件

通过指令v-on(简写@)来实现
 v-on:事件名称.修饰符=“执行的函数或表达式”
注意点:
 1.事件执行的函数,需要在methods中定义
 2.事件绑定时的执行函数,有无小括号都是调用
 3.this指向:methods对象中的函数,this指向永远是当前的Vue实例
 4.事件对象:event 储存着事件所有信息
  事件绑定函数中的第一个参数默认为 event 对象
  当执行函数带小括号以及有其它参数时,event需要手动传入,名称为$event
  模板中的 $event是规定死的
methods
  在组件选项中,提供了一个 methods 选项,用来存放组件中使用的函数方法,且存放在 methods 中的函数方法可以通过组件实例(this)进行访问

过滤器

对内容或数据进行过滤或二次处理的一种方式
过滤器的使用:类似于管道流
管道流:将第一个的结果,以参数(第一位)的形式传递给下一个,以此类推
| : 管道符,表示数据从左至右通过管道符进行传递
过滤器可以有多个,执行顺序从左至右,过滤器函数第一个参数的值就是其管道符前一个的结果。

			 <div id="app">
			    <ul>
			        <li v-for='item of items'>
			            <span>名称:{{item.name}}</span>
			            <span>-</span>
			            <span>{{rmb(item.price,"$")}}</span>
			
			        </li>
			    </ul>
			    </div>
				
				let app = new Vue({
				            el:'#app',
				            data:{
				                items:[
				                    {id:1,name:'iphone',price:'88888'},
				                    {id:1,name:'ipad',price:'777777'},
				                    {id:1,name:'imac',price:'666666'}
				                ]
				            },

这里是引用局部过滤器
Vue.component(‘组件’, {
 …,
 filters: {
  ‘过滤器名称’: 过滤器函数
 }
})

 new Vue({
    el: '#app',
    data: {
      time: Date.now()
    },
    filters: { //过滤器的配置项
      'timeFilter': function ( val,type ){
        var date = new Date ( val )
        return date.getFullYear() + type + ( date.getMonth() + 1 ) + type + date.getDate()
      }
    }
  })

computed

在实际的应用中,我们会有一些原始数据,同时在应用中又会有一些数据是根据某些原始数据派生出来的,针对这样的一种情况,vue 定义了一个专门用来处理这种派生数据的选项:computed

computed
 1.储存被修改过或逻辑处理过的数据
 2.computed是一个对象,类似于data而不是methods,素以称为计算属性(如果数据需要被二次或多次处理,就属于计算属性)
 3.computed中的属性可以像data中存放的数据一样去使用
 4.它的结构类似(defineProperty 数据劫持),getter,setter
 5.计算属性的值同时还会根据它所依赖的数据的变化而自动变化

 <div id="app">
       <div>
        <button :class="{active: gender ===''}" @click = "gender =''">全部</button>
        <button :class="{active: gender ==='男'}" @click = "gender ='男'"></button>
        <button :class="{active: gender ==='女'}" @click = "gender ='女'"></button>
       </div>

  let users =[
                    {id:1,username:'iphone',gender:'男'},
                    {id:2,username:'ipad',gender:'女'},
                    {id:3,username:'imac',gender:'男'},
                    {id:4,username:'ipad7',gender:'男'},
                    {id:5,username:'imac8',gender:'女'},
                    {id:6,username:'ipad9',gender:'女'},
                ];

        let app = new Vue({
            el:"#app",
            data:{
                users,  
                // showUsers:users
                gender:""
            },
            computed:{
                showUsers:{
                    //当showUsers 这个数据被获取时,触发
                    get(){
                        if(this.gender === ""){
                            return this.users
                        }else{
                             return this.users.filter(user => user.gender === gender);
                        }
                    }
                }
            }
        });

6.计算属性的值,在依赖的属性未发生改变时/或没有依赖数据
  会自动缓存到应用中,下次获取时,不重新计算,直接获取上一次计算的值(Vue提升性能方法之一)

 <div id="app">
        <p v-if='showDate'>{{getNow()}}</p>
        <p v-if="showDate">{{now}}</p>
        <button @click="showDate=!showDate">check here</button>
    </div>
        
</body>
<script>
    let app = new Vue({
        el:"#app",
        data:{
            showDate:true
        },
        methods:{
            getNow(){
                return Date.now();
            }
        },
        computed:{
                return Date.now();
            }
         }

    })

7.如果某个计算属性只需要处理get方法,那么可以简写

        computed:{ 
        //  now:{
        //     get(){
        //         return Date.now();
        //         }
        //     },
            now(){
                return Date.now();
            }
         }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值