您的位置:首页 > Web前端 > Vue.js

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

  1. 通过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

  1. 通过npm安装 [ol] 初始化环境
[/ol]
npm init -y
  1. 安装vue
cnpm i -D vue//-d的含义是开发模式添加到依赖
  1. 写第一个vue
    说实话怎么写着感觉有点像 art-template,但是比模板引擎的功能更强大。
<div id="box">
<p>{{msg}}</p>
</div>
<script>
var vm = new Vue({
el: '#box',
data: {
msg: 'hello world'
}
})
</script>

初识指令

  1. 数据双向绑定(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>
  1. 标签属性的设置(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>
  1. 标签内容的设置(v-text );
<div id="box">
<p v-text='msg'></p>
</div>
<script>
new Vue({
el:'#box',
data:{
msg:'这是一个文本'
}
})
</script>
  1. 标签内容的设置(v-html )
<div id="box">
<p v-html='msg'></p>
</div>
<script>
new Vue({
el:'#box',
data:{
msg:'<p>这是一个文本</p>'
}
})
</script>
  1. 监听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>
  1. 循环(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>
  1. 属性监听(属性改变数据跟着变化)
    案例购物车
<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>
  1. 插值表达式闪烁问题(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>
  1. 事件修饰符
    .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>
  1. 事件的冒泡和捕获 [ol] 原生js事件的冒泡和捕获
[/ol]
<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>
  1. 事件代理

应用为,你不知道你又多少个子元素需要加事件,或者有很多的子元素,
如果你一个一个加,不就很浪费资源。所以出现事件代理去解决

<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>
  1. 按键修饰符
    .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>
  1. 数据的过滤器 (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>
  1. watch(支持异步代码)handlar
watch: {//某数据改变时触发
check:{//要监听值的名称
handler(newName, oldName) {
this.fullName = newName + ' ' + this.lastName;
},
// 代表在wacth里声明了firstName这个方法之后立即先去执行handler方法
immediate: true
监听数值是不是要深度监听
deep: true,
},
  1. v-if和v-show
<p v-if="msg">{{msg}}</p>直接删除标签
<p v-show="msg">{{msg}}</p>不会删除标签。在标签上添加display属性
  1. 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>
  1. 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>
  1. vue的生命周期
    主要是四个钩子函数
    1,beforeCreate、created、 (创建=>)
    beforeMount、mounted、 (挂载=>)在挂载时会实时监听更新的状态
    beforeUpdate、updated、(更新=>)
    beforeDestroy、destroyed ,销毁,
  2. 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>
  1. 局部组件定义
<div id="box">
<hello></hello>
</div>
<script>
let hello = {
template : "<div>这里定义的是一个局部组件</div>",
created() {
console.log('这个是创建之后的钩子函数')
},
}
new Vue({
el: '#box',
data:{
},
components: {
hello,
}
})
</script>
  1. 组件嵌套
<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>
  1. 父组件向子组件传参
<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>
  1. 订阅发布模式
    先用原生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>
  1. 子组件向父组件传参
<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>
  1. 弹窗
<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>
  1. 写个中和案例,我就直接放在github上了。
    计划列表(数据持久化)点击前面的字就可以跳转

基础的vue学的差不多了。该学习路由,

follow me

Go! **

Vue-router

**
…正在一点点更正,欢迎大牛指点,小白学习。

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: