Vue框架,从基础入门到项目实战。看这一篇知识点全覆盖了
安装Vue介绍Vue 只关注视图层, 采用自底向上增量开发的设计。在了解Vue之前你需要了解HTMLCSSJavaScript安装Vue通过CDN方式使用示例<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.1.8/vue.min.js"></script>Staticfi...
##放在最前面,
github 重构vancl网站
https://github.com/pengboooo/VANCL 这是地址,有喜欢的希望给个免费的start,谢谢了
安装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安装
- 初始化环境
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>
- 事件的冒泡和捕获
- 原生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
**
…正在一点点更正,欢迎大牛指点,小白学习。
更多推荐
所有评论(0)