Vue框架,从基础入门到项目实战。看这一篇知识点全覆盖了
2019-08-12 22:02
295 查看
版权声明:本文为博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/qq_36131502/article/details/99303398
安装Vue
介绍
Vue 只关注视图层, 采用自底向上增量开发的设计。
在了解Vue之前你需要了解
- HTML
- CSS
- JavaScript
安装Vue
- 通过CDN方式使用
示例<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.1.8/vue.min.js"></script>
-
Staticfile CDN(国内) : https://cdn.staticfile.org/vue/2.2.2/vue.min.js
-
unpkg:https://unpkg.com/vue/dist/vue.js, 会保持和 npm 发布的最新的版本一致。
-
cdnjs : https://cdnjs.cloudflare.com/ajax/libs/vue/2.1.8/vue.min.js
- 通过npm安装 [ol] 初始化环境
npm init -y
- 安装vue
cnpm i -D vue//-d的含义是开发模式添加到依赖
- 写第一个vue
说实话怎么写着感觉有点像 art-template,但是比模板引擎的功能更强大。
<div id="box"> <p>{{msg}}</p> </div> <script> var vm = new Vue({ el: '#box', data: { msg: 'hello world' } }) </script>
初识指令
- 数据双向绑定(v-model)
<div id="box"> <p v-text = 'msg'></p> <input type="text" v-model ="msg" > <!--双向绑定,只需要填写v-model --> </div> <script> var vm = new Vue({ el:'#box', data:{ msg:'王五' }, }) </script>
- 标签属性的设置(v-bind || :)
<div id="box"> <!-- 思考,如果我想渲染多个属性呢 --> <div v-bind:class='msg'></div>//可以简写为<div :class='msg'></div> </div> <script> var cls = ["div1","div2","div3"] cls.toString = function(){ return this.join(' ');//这里填什么都没有影响,只处理数组 } console.log(cls); var vm = new Vue({ el:'#box', data:{ msg:cls } }) </script>
- 标签内容的设置(v-text );
<div id="box"> <p v-text='msg'></p> </div> <script> new Vue({ el:'#box', data:{ msg:'这是一个文本' } }) </script>
- 标签内容的设置(v-html )
<div id="box"> <p v-html='msg'></p> </div> <script> new Vue({ el:'#box', data:{ msg:'<p>这是一个文本</p>' } }) </script>
- 监听DOM事件(v-on || @)
<div id="div"> <button v-on:click='setCon'>{{msg}}</button>//可以这样简写<button @click='setCon'>{{msg}}</button> </div> <script> new Vue({ el:'#div', data:{ msg:'5' }, methods:{ setCon:function(e){ this.msg++ } } }) </script>
- 循环(v-for)
<div id="box"> <ul> <li v-for='(item,index) in msg'>{{item+' '+index}}</li><!--循环数组支持多参数 --> <li v-for='(item,key,index) in obj'>{{item+' '+ key +' '+ index}}</li><!--循环对象支持多参数 --> </ul> </div> <script> new Vue({ el:'#box', data:{ msg:[1,2,3,1,4,5,4], obj:{ name:"张三", age:'18', } } }) </script>
7.computed(依赖缓存数据)与methods(不依赖缓存,每次都计算)
当data数据发生变化时就会变化
<div id="box"> {{yesNum()}} {{yesNum()}} {{yesNum1}} {{yesNum1}} {{yesNum1}} </div> <script> var conts =1; var vm = new Vue({ el:'#box', data:{ msg:'vue' }, methods:{//这个每个都要重新计算一遍 yesNum:function(){ conts++; console.log(this.msg.split('').reverse().join('')); return conts+' '+ this.msg.split('').reverse().join('')//返回字符串反转内容 } }, computed:{//这个会有缓存,之前有了不再计算直接输出 yesNum1:function(){ conts++; console.log(this.msg.split('').reverse().join(''),'se'); return conts+' '+ this.msg.split('').reverse().join('') } } }) </script>
- 属性监听(属性改变数据跟着变化)
案例购物车
<div id="app"> <table> <tr> <th>序号</th> <th>商品名称</th> <th>商品价格</th> <th>购买数量</th> <th>操作</th> </tr> <tr v-for="iphone in Ip_Json"> <td>{{ iphone.id }}</td> <td>{{ iphone.name }}</td> <td>{{ iphone.price }}</td> <td> <!-- disabled="iphone.count === 0" 里面是个表达式,当为true时禁用按钮,就不能0以下了 --> <button v-bind:disabled="iphone.count === 0" v-on:click="iphone.count-=1">-</button> {{ iphone.count }} <button v-on:click="iphone.count+=1">+</button> </td> <td> <button v-on:click="iphone.count=0">移除</button> </td> </tr> </table> 总价:${{totalPrice()}} </div> <script> var app = new Vue({ el: '#app', data: { Ip_Json: [{ id: 1, name: 'iphone 8', price: 5099, count: 1 }, { id: 2, name: 'iphone xs', price: 8699, count: 1 }, { id: 3, name: 'iphone xr', price: 6499, count: 1 } ] }, methods: { totalPrice: function () { var totalP = 0; for (var i = 0, len = this.Ip_Json.length; i < len; i++) { totalP += this.Ip_Json[i].price * this.Ip_Json[i].count; } return totalP; } } }) </script>
- 插值表达式闪烁问题(v-clock)
<style> [v-clock]{ display: none !important; } </style> <div id="box" > <div v-clock >{{msg}}</div> </div> <div id="box" > <div v-text='msg' ></div>//这样写没有闪烁问题 </div>
- 事件修饰符
.stop (阻止冒泡或者捕获,后面的不触发) .prevent(阻止默认行为).capture (事件捕获).self(阻止自身) .once(只触发一次)
<div id="boxs"> <div id="box" @click.capture='box1'><!--设置捕获 --> <div id="box2" @click.self='box2'> <!-- 阻止自身的捕获 --> <div id="box3" @click.stop='box3'><!--阻止冒泡 --> </div> </div> </div> <button @click.once='one'>once</button> <!--只触发一次 --> <a href="www.baidu.com" @click.prevent='alert("弹出跳转")'>跳转</a> <!--阻止默认行为 --> </div> <script> new Vue({ el:'#boxs', methods:{ box3(){ console.log('触发了3'); }, box2(){ console.log('触发了2'); }, box1(){ console.log('触发了1'); }, one(){ console.log('执行了'); } } }) </script>
- 事件的冒泡和捕获 [ol] 原生js事件的冒泡和捕获
<div class="grandfather"> <div class="father"> <div class="son"> </div> </div> </div> <script> var grandfather = document.querySelector(".grandfather") var father = document.querySelector(".father") var son = document.querySelector(".son") grandfather.addEventListener("click", function() { console.log("grandfather冒泡阶段") }, false) father.addEventListener("click", function() { console.log("father冒泡阶段") }, false) // 如果某一个元素是目标阶段,谁先注册谁先执行!!! son.addEventListener("click", function() { console.log("son冒泡阶段") }, false) grandfather.addEventListener("click", function() { console.log("grandfather捕获阶段") }, true) father.addEventListener("click", function() { console.log("father捕获阶段") }, true) son.addEventListener("click", function() { console.log("son捕获阶段") }, true) </script>
- 事件代理
应用为,你不知道你又多少个子元素需要加事件,或者有很多的子元素,
如果你一个一个加,不就很浪费资源。所以出现事件代理去解决
<ul id="ul"> <li>1</li> <li>2</li> <li>3</li> ............我就省略重复的了 <li>98</li> <li>99</li> <li>100</li> </ul> <script> // removeEventListener('click', 函数) // 事件委托? 通过冒泡事件,给父元素绑定事件。s var ul = document.getElementById('ul'); ul.onclick = function(event) { console.log(event); console.log(event.target.innerHTML) } </script>
- 按键修饰符
.enter => // enter键
.tab => // tab键
.delete (捕获“删除”和“退格”按键) => // 删除键
.esc => // 取消键
.space => // 空格键
.up => // 上
.down => // 下
.left => // 左
.right => // 右
<div id="box"> <input type="text" @keyup='enters'>//或者@keyup.某个修饰符 </div> <script> new Vue({ el:'#box', methods:{ enters(e){ console.log(e.keyCode); } } }) </script> 也可以固定某一个按键,这样写 <div id="box"> <input type="text" @keyup.enter='enters'>//或者@keyup.某个修饰符 </div> <script> new Vue({ el:'#box', methods:{ enters(e){ console.log(e.keyCode); } } }) </script>
- 数据的过滤器 (filters)
<div id="box">{{msg | num | num2}}</div> <script> new Vue({ el:'#box', data:{ msg:15, }, filters:{ num:function(val){ console.log(val); return val+1 }, num2:function(val){ console.log(val); return val+1 } } }) </script>
- watch(支持异步代码)handlar
watch: {//某数据改变时触发 check:{//要监听值的名称 handler(newName, oldName) { this.fullName = newName + ' ' + this.lastName; }, // 代表在wacth里声明了firstName这个方法之后立即先去执行handler方法 immediate: true 监听数值是不是要深度监听 deep: true, },
- v-if和v-show
<p v-if="msg">{{msg}}</p>直接删除标签 <p v-show="msg">{{msg}}</p>不会删除标签。在标签上添加display属性
-
template模板标签,只支持v-if 和v-else
有三种写法
//第1种模板 写在构造器里
//template:<h1 style="color:red">我是选项模板2</h1>
//第2种模板 写在<template>标签里 //template:'#demo3' //第3种模板 写在<script type="x-template">标签里
<template v-if="loginType === 'username'"> <label>Username</label> <input placeholder="Enter your username" key="username-input"> </template> <template v-else> <label>Email</label> <input placeholder="Enter your email address" key="email-input"> </template>
如果你想继续使用里面的内容,可以用slot
<body> <div id="box"> <Hello-world> <p slot="p1">1</p> <p>2</p> <p>3</p> <p>4</p> <p>5</p> <p>6</p> <p>7</p> <p>8</p> <p>9</p> <p>10</p> </Hello-world> </div> <template id="temp"> <div> <p>把这里的内容全部替换掉</p> <slot></slot> <slot name='p1'></slot> </div> </template> <script> // 自定义组件 let HelloWorld = { template: "#temp", } new Vue({ el: '#box', data: { msg: true }, components: { HelloWorld //添加组件 }, /* 这是第一种写法 template: '<p>#box中的全部替换掉</p>', //这里是模板名称,要替换#box里所有的内容, */ /** * 这是第二种写法,需要在页面中添加 * template:'#temp' * <template id="temp"> <div > <p>把这里的内容全部替换掉</p> </div> </template> * * */ }) </script>
- ref
设置在标签上,就可以获取dom对象
<div id="box"> <p ref="element"></p> </div> <script> let vm = new Vue({ el:"#box", data:{ msg:"张山" } }) console.log( vm.$refs.element); </script>
- vue的生命周期
主要是四个钩子函数
1,beforeCreate、created、 (创建=>)
beforeMount、mounted、 (挂载=>)在挂载时会实时监听更新的状态
beforeUpdate、updated、(更新=>)
beforeDestroy、destroyed ,销毁,
- nextTick 原理mutationObserver(监视dom渲染完毕后执行nextTick)
原理就是使同步的api,变为异步执行,添加到队列中。
nextTick行为利用了microtask队列, 先使用 Promise.resolve().then(nextTickHandler)来将异步回调
放入到microtask中,Promise 和 MutationObserver都可以使用,但是 MutationObserver 在IOS9.3以上的
WebView中有bug,因此如果满足第一项的话就可以执行,如果没有原生Promise就用 MutationObserver。
.我把JavaScript在浏览器中运行主要分为以下几种类型的任务:
- 同步任务(MainTask) :同步任务是指JavaScript按照正常顺序执行的代码,比如:函数调用,数值运算等等,只要是执行后立即能够得到结果的就是同步任务。
- 宏任务 (MacroTask):setTimeout、setInterval、I/O、UI渲染
- 微任务 (MicroTask) :Promise、Object.obsever、MutationObsever
- 用户交互事件(User Interaction Event):点击事件onclick、键盘事件onkeywodn、鼠标事件onmouseover等等
**
执行顺序
**
24. 全局组件定义
<div id="box"> <hello></hello> </div> <script> //定义全局组件 Vue.component('hello',{//注册全局,其实就是挂载到vue的构造函数中 template:'<div>这是一个模板<div>', created() { console.log('这是创建之后钩子函数') }, }) new Vue({ el:'#box', data() { return { } }, }) </script>
- 局部组件定义
<div id="box"> <hello></hello> </div> <script> let hello = { template : "<div>这里定义的是一个局部组件</div>", created() { console.log('这个是创建之后的钩子函数') }, } new Vue({ el: '#box', data:{ }, components: { hello, } }) </script>
- 组件嵌套
<div id="box"> <grandfather></grandfather> </div> <script> /** 分析,组件的嵌套,最终是将所有组件放到一个父组件中,所以页面写的是一个组件的名字 写在最后一层的需要最先定义,因为只有定义的才能使用 */ let son ={ template: '<div>这是儿子的组件</div>' } let father ={ template:'<div>这是父亲的组件<son></son></div>', components:{ son } } let grandfather = { template:'<div>这是爷爷的组件<father></father></div>',//注册完需要写在爷爷的模板中渲染 components:{ father, } } new Vue({ el:'#box', components:{ grandfather, } }) </script>
- 父组件向子组件传参
<div id="box"> <father></father> </div> <script> //父向子传递,需要子元素绑定一个属性,然后子元素接收 // //新建子组件 let son = { template: '<div>父亲传递过来的值{{manoe}}<input type="text" v-model:value="manoe"> </div>', props: ['manoe'] } //新建父组件 let father = { // data:{ // m:20 // }, data() {//组件嵌套时就需要写成对象返回值方式 return { m: 20, } }, template: '<div class="father">这是父亲的块{{m}}<son class="son" :manoe="m"></son></div>', components: { son, } } new Vue({ el: '#box', components: { father } }) </script>
- 订阅发布模式
先用原生js写一遍订阅发布模式
<script> // 女生失恋 吃火锅 买包包 看电影 function Girl() { this._events = {} } Girl.prototype.on = function(eventName, handler) { // _events.shilian if(this._events[eventName]) { this._events[eventName].push(handler) }else { // 如果说events.shilian没有的话,则将handler加入空数组中 // this._events.shilian = [handler] this._events[eventName] = [handler] } } Girl.prototype.emit = function(eventName) { if(this._events[eventName]) { this._events[eventName].forEach((item)=> { item() }) } } var g1 = new Girl(); // 订阅事件 g1.on('shilian', function() { console.log("吃火锅") }) g1.on('shilian', function() { console.log("买包包") }) g1.on('shilian', function() { console.log("看电影") }) //[fn1, fn2, fn3] // 发布事件!!! g1.emit('shilian') </script>
再用vue中bus模式写同级相互传参
<div id="box"> <son1></son1> <son2></son2> </div> <script> let bus = new Vue();//使用bus方法创建一个空的总线。让组件去通信 //新建兄弟组件 let son1 = { template: '<div class="son">父亲传递过来的值{{msg}} </div>', data() { return { msg: '' } }, created() { bus.$on("a", (msg) => { this.msg = msg; }) } } //新建兄弟2组件 let son2 = { data() { return { m: 10 } }, template: '<div class="father">这是父亲的块 <button @click="sendMsg">向另外一个兄弟组件传值</button></div>', methods: { sendMsg() { bus.$emit('a', this.m) } }, } new Vue({ el: '#box', components: { son2, son1 } }) </script>
- 子组件向父组件传参
<div id="box"> <father></father> </div> <script> //突然感觉这种方式在小项目中很好用啊,可以跨级组件传递。 var bus = new Vue(); //子组件 let son ={ data() { return { msg:10 } }, template:'<div>这是子组件<button @click="faya">发送</button></div>', methods: { faya(){ bus.$emit('name',this.msg) } }, } //父组件 let father = { data() { return { num:'' } }, template:'<div class="father">这是一个父组件的值{{num}}<son class="son"></son></div>', components:{ son }, created() { bus.$on('name',(msg)=>{ console.log("触发了"); this.num = msg }) }, } new Vue({ el:'#box', components:{ father } }) </script>
- 弹窗
<div id="box"> <button @click="brother">显示弹窗</button> <brothers ref ="boxs"></brothers> </div> <template id="boxs"> <div class="whet" v-if="init"> <div class="net"> <button @click='hide'> 关闭 </button> </div> </div> </template> <script> let brothers ={ template:'#boxs', data() { return { init:false } }, methods: { hide(){ this.init =!this.init } }, } new Vue({ el:'#box', methods: { brother(){ this.$refs.boxs.init =!this.$refs.boxs.init } }, components:{ brothers } }) </script>
- 写个中和案例,我就直接放在github上了。
计划列表(数据持久化)点击前面的字就可以跳转
基础的vue学的差不多了。该学习路由,
follow me
Go! **
Vue-router
**
…正在一点点更正,欢迎大牛指点,小白学习。
相关文章推荐
- 最新Vue2.x 入门项目实战-包括Vuex、MintUi、ElementUi基础教程(28讲)
- 2018最全Vue2.5开发去哪儿网App 从零基础入门到实战项目
- Yii2.0基础框架从入门到精通项目实战(完整)
- 2018年最新 Vue2.5开发去哪儿网App 从零基础入门到实战项目
- 2018年Vue2.5开发去哪儿网App 从零基础入门到实战项目最全
- vue2.0项目实战(1)基础入门
- vue入门视频教程 vue基础到项目实战
- 某课Vue2.5开发去哪儿网App 从零基础入门到实战项目(10章全)
- 2018年最最新Vue2.5开发去哪儿网App 从零基础入门到实战项目
- 2018年最全Vue2.5开发去哪儿网App 从零基础入门到实战项目
- 最新Vue2.5开发去哪儿网App 从零基础入门到实战项目完整版
- 最新Vue2.5从零基础入门到去哪儿网App实战项目开发全套
- Vue2.5从零基础入门到去哪儿网App实战项目开发分享
- 2018年最新Vue从基础入门到项目实战视频教程网盘学习地址
- Vue2.5开发去哪儿网App 从零基础入门到实战项目百度网盘免费下载
- Vue2.5开发去哪儿网App 从零基础入门到实战项目(最新最全)
- vue项目框架结构入门 及 vue基础
- 2018最新Vue2.5开发去哪儿网App 从零基础入门到实战项目
- 2018最新Vue2.5开发去哪儿网App 从零基础入门到实战项目
- 2018目前最新Vue2.5开发去哪儿网App+从零基础入门到实战项目