置身世外只为暗中观察!!!Hello你们好,我是魔王哪吒!重学巩固你的Vuejs知识体系,若是有哪些知识点遗漏,还望在评论中说明,让我能够及时更新本篇内容知识体系。欢迎点赞收藏!javascript
谈谈你对MVC、MVP和MVVM的理解?css
什么是组件化,Vue组件化开发思想前端
axios的使用vue
vuejs原理相关:响应式原理,源码。html5
对于基础知识须要掌握,简单写写✍java
直接CDN引入:node
代码:<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
react
代码:<script src="https://cdn.jsdelivr.net/npm/vue@2.6.11"></script>
linux
代码:
# 最新稳定版
$ npm install vue
复制代码
声明式编程:
代码:
<!DOCTYPE html>
<!-- 魔王哪吒 -->
<html>
<head>
<meta charset="utf-8">
<title></title>
<script src="vue.js" type="text/javascript" charset="UTF-8"></script>
<!-- <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> -->
</head>
<body>
<div id="app">
{{ a }}
</div>
<script type="text/javascript">
// 咱们的数据对象
var data = { a: 1 };
// 该对象被加入到一个 Vue 实例中
var vm = new Vue({
el: "#app",
data: data
});
// data.a = "dada"
vm.a = "qianduan";
data.a == vm.a;
</script>
</body>
</html>
复制代码
methods
,该属性是用于Vue
对象中定义的方法。@click
,该指令是用于监听某个元素的点击事件,而且须要指定当发生点击时,执行的方法。代码:
<div id="app">
<h1>当前计数{{counter}}</h1>
<button @click="increment">+</button>
<button @click="decrement">-</button>
</div>
<script src="../js/vue.js"></script>
<script>
let app = new Vue({
el: '#app',
data: {
counter: 0
},
methods: {
increment(){
this.counter++
},
decrement(){
this.counter--
},
}
})
</script>
复制代码
MVVM的思想
它们之间是如何工做的呢?
el
:类型:string | HTMLElement
DOM
data
:类型:Object | Function
methods
:类型:{[key:string]:Function}
生命周期:☞ 事物从诞生到消亡的整个过程
release
稳定版本debug
版本v-once
指令的使用
<div id="app">
<h1>{{message}}</h1>
<h2 v-once>{{message}}</h2>
</div>
复制代码
v-once
:
v-html
:
当咱们从服务器请求到的数据自己就是一个HTML代码时
{{}}
来输出,会将HTML
格式进行解析,而且显示对应的内容。v-html
指令string
类型string
的html
解析处理而且进行渲染<h1 v-html="url"></h1>
复制代码
v-text
的做用和Mustache
比较类似,独使用于将数据显示在界面中,通常状况下,接受一个string
类型。
<div id="app">
<h2 v-text="message"></h2>
<h2>{{message}}</h2>
</div>
<script src="../js/vue.js"></script>
<script>
let vm = new Vue({
el: '#app',
data: {
message: '你好'
}
})
</script>
复制代码
v-pre
用于跳过这个元素和它子元素的编译过程,用于显示本来的Mustache
语法。
<div id="app">
<p v-pre>{{message}}</p>
</div>
<script src="../js/vue.js"></script>
<script>
let app = new Vue({
el: '#app',
data: {
message: 'hello'
}
})
</script>
复制代码
v-cloak
斗篷的意思。
<div id="app">
<h2 v-cloak>hello{{name}}</h2>
</div>
<script>
setTimeout(()=>{
let app = new Vue({
el: '#app',
data: {
name: 'web'
}
})
},10000)
</script>
<style>
[v-cloak] {
display: none;
}
</style>
复制代码
v-bind
用于绑定一个或多个属性值,或者向另外一个组件传递props
值。
<div id="app">
<a v-bind:href="link">vuejs</a>
<img v-bind:src="url" alt="">
</div>
<script>
let app = new Vue({
el: '#app',
data: {
}
})
复制代码
v-bind
语法糖
v-bind
有一个对应的语法糖,就是简写方式
<div id = "app">
<a :href="link">vuejs</a>
<img :src="longURL" alt="">
</div>
复制代码
v-bind
动态绑定class
<style>
.active{
color: red;
}
</style>
<div id="app">
<h1 class="active">{{message}}</h2>
</div>
<script>
const app = new Vue({
el: '#app',
data: {
message: 'hello'
}
})
</script>
复制代码
绑定class
有两种方式:
对象语法:
用法一:直接经过{}绑定一个类
<h2 :class="{'active': isActive}">hello</h2>
用法二,传入多个值
<h2 :class="{'active': isActive, 'line': isLine}">hello</h2>
用法三:
<h2 class="title" :class="{'active': isActive}"></h2>
用法四:
能够放在一个methods或者computed中
<h2 class="title" :class="classes">hello</h2>
复制代码
v-bind
动态绑定class,数组语法
<div id="app">
<h2 class="title" :class="[active, line]">{{mesg}}</h2>
<h2 class="title" :class="getClasses()">{{mesg}}</h2>
</div>
<script>
const app = new Vue({
el: '#app',
data: {
message: 'hello',
active: 'aaa',
line: 'bbb',
},
methods: {
getClasses: function() {
return [this.active, this.line]
}
}
})
</script>
复制代码
v-bind
动态绑定style
对象语法和数组语法两种绑定。
绑定方法:对象语法:
:style="{ color: currentColor, fontSize: fontSize + 'px' }"
复制代码
style
后面跟的是一个对象类型,对象的key
是css
属性名称,对象的value
是具体赋的值,值能够来自于data
中的属性。
绑定方法:数组语法:
<div v-bind:style="[baseStyles, overStyles]"></div>
复制代码
style
后面跟的是一个数组的类型,多个值,分割便可。
计算属性,写在实例的computed
选项中:
<div id="app">
<h2>{{firstName}}{{lastName}}</h2>
</div>
<script>
const vm = new Vue({
el: '#app',
data: {
firstName: 'web',
lastName: 'it',
}
})
</script>
复制代码
<div id="app">
<h2>{{fullName}}</h2>
</div>
<script>
const vm = new Vue({
el: '#app',
data: {
firstName: 'jeskson',
lastName: 'it',
},
computed: {
fullName() {
return this.firstName + ' ' + this.lastName
}
}
})
</script>
复制代码
计算属性的缓存:
为何使用计算属性这个东西?
缘由:计算属性会进行缓存,若是屡次使用时,计算属性只会调用一次。
每一个计算属性都包含一个getter和一个setter
<div id="app">
<div>{{fullName}}</div>
<div>{{firstName}}</div>
<div>{{lastName}}</div>
</div>
<script>
let vm = new Vue({
el: '#app',
data: {
firstName: 'web',
lastName: 'it',
},
computed: {
fullName: {
get() {
rturn this.firstName+" "+this.lastName
},
set(newValue){
const names = newValue.split(' ')
this.firstName = names[0]
this.lastName = names[1]
}
}
}
})
</script>
复制代码
computed: {
fullName: function() {
return this.firstName+" "+this.lastName
}
// 计算属性通常是没有set方法,只读属性。
fullName: {
get: function() {
return this.firstName + " " + this.lastName
}
}
}
复制代码
const的使用,在JavaScript中使用const修饰的标识符为常量,不能够再次赋值。
在es6开发中,优先使用const,只有须要改变一个标识符的时候才使用let。
在使用cost定义标识符,必须进行赋值。
常量的含义是指向的对象不能修改,可是能够改变对象内部的属性。
何时使用const呢?
当咱们修饰的标识符不会被再次赋值时,就可使用const来保证数据的安全性。
const的使用:
const a=20;
a = 10; // 错误:不能够修改
const name; // 错误,const修饰的标识符必须赋值
复制代码
let和var
块级做用域:
JS中使用var来声明一个变量,变量的做用域主要是和函数的定义有关。
对于其余块定义来讲是没有做用域的,好比if/for等,开发中每每会引起一些问题。
// 监听按钮的点击
var btns = document.getElementsByTagName('button');
for(var i=0; i<btns.length; i++) {
(function(i){
btns[i].onclick = function(){
alert('点击了'+i+"个")
}
})(i)
}
复制代码
let btns = document.getElementsByTagName('button');
for(let i=0;i<btns.length;i++){
btns[i].onclick = function(){
alert('点击了'+i+'个')
}
}
复制代码
变量做用域:变量在什么范围内是可用的。
var func;
if(true) {
var name = 'web';
func = function() {
console.log(name); // web
}
func(); // web
}
// name = 'it'
func(); // web -> it
console.log(name); // web -> it
复制代码
没有块级做用域引发的问题,for的块级
var btns = document.getElementsByTagName('button');
for(var i=0; i<btns.length; i++) {
btns[i].addEventListener('click', function(){
console.log('第'+i+'个按钮被点击');
})
}
复制代码
闭包:
var btns = document.getElementsByTagName('button');
for(var i=0; i<btns.length;i++){
(function(i){
btns[i].addEventListener('click', function(){
console.log('第'+i+'个按钮');
})
})(i)
}
复制代码
为何闭包能够解决问题,由于函数是一个做用域。
属性初始化简写和方法的简写:
// 属性的简写
// es6前
let name = 'web'
let age = 12
let obj1 = {
name: name,
age: age,
}
console.log(obj1);
// es6后
let obj2 = {
name, age
}
console.log(obj2)
复制代码
// 方法的简写
// es6以前
let obj1 = {
test: function() {
console.log('obj1')
}
}
obj1.test();
// es6后
let obj2 = {
test() {
console.log('obj2')
}
}
obj2.test();
复制代码
v-on:click="counter++"
<div id="app">
<h2>点击次数:{{counter}}</h2>
<button v-on:click="counter++">按钮点击</button>
<button v-on:click="btnClick">按钮点击2</button>
</div>
let app = new Vue({
el: '#app',
data: {
counter: 0
},
methods: {
btnClick(){
this.counter++
}
}
})
复制代码
v-on修饰符的使用
<div id="app">
<div @click="divClick">
web
<button @click.stop="btnClick">按钮</button>
</div>
复制代码
Vue提供了一些修饰符:
.stop 调用event.stopPropagation()
.prevent 调用event.preventDefault()
.native 监听组件根元素的原生事件
.once 只触发一次回调
复制代码
// 中止冒泡
<button @click.stop="doThis"></button>
// 阻止默认行为
<button @click.prevent="doThis"></button>
// 阻止默认行为,没有表达式
<form @submit.prevent></form>
// 串联修饰符
<button @click.stop.prevent = "doThis"></button>
// 键修饰符,键别名
<input @keyup.enter="onEnter">
// 键修饰符,键代码
<input @keyup.13="onEnter">
// 点击回调智慧触发一次
<button @click.once="doThis"></button>
复制代码
简单使用:
<div id="app">
<p v-if="score>=90">优秀</p>
<p v-else-if="score>=80">良好</p>
<p v-else-if="score>=60">及格</p>
<p v-else="score<60">不及格</p>
</div>
复制代码
登陆切换:
<div id="app">
<span v-if="type==='username'">
<label>用户帐号:</label>
<input placeholder="用户帐户">
</span>
<span v-else>
<label>邮箱地址:</label>
<input placeholder="邮箱地址">
</span>
<button @click="handleToggle">切换类型</button>
</div>
<script>
let app = new Vue({
el: '#app',
data: {
type: 'username'
},
methods: {
handleToggle(){
this.type = this.type === 'email' ? 'username' : 'email'
}
}
})
</script>
复制代码
<div id="app">
<span v-if="isUser">
<label for="username">用户帐户</label>
<input type="text" id="username" placeholder="用户帐户">
</span>
<span v-else>
<label for="email">用户邮箱</label>
<input type="text" id="email" placeholder="用户邮箱">
</span>
<button @click="isUser=!isUser">切换类型</button>
</div>
<script>
const app = new Vue({
el: '#app',
data: {
isUser: true
}
})
</script>
复制代码
<div id="app">
<ul>
<li v-for="(value, key, index) in info">
{{value}}-{{key}}-{{index}}
</li>
</ul>
</div>
<script>
let app = new Vue({
el: '#app',
data: {
info: {
name: 'web',
age: 12,
}
}
})
</script>
复制代码
使用v-for时,给对应的元素或组件添加上一个:key
属性。
key的做用主要是为了高效的更新虚拟dom。
数组中哪些方法是响应式的
push()
pop() 删除数组中的最后一个元素
shift() 删除数组中的第一个元素
unshift() 在数组最前面添加元素
splice()
sort()
reverse()
复制代码
<div id="app">
<table>
<thead>
<tr>
<th></th>
<th>书籍名称</th>
<th>出版日期</th>
<th>价格</th>
<th>购买数量</th>
<th>操做</th>
</tr>
</thead>
<tbody>
<tr v-for="item in books">
<td v-for="value in item">{{value}}</td>
</tr>
</tbody>
</table>
</div>
复制代码
vue中使用v-model指令来实现表单元素和数据的双向绑定。
<div id="app">
<input type="text" v-model="message">
<h2>{{message}}</h2>
</div>
复制代码
reduce做用对数组中全部的内容进行汇总。
JavaScript reduce() 方法
var numbers = [65, 44, 12, 4];
function getSum(total, num) {
return total + num;
}
function myFunction(item) {
document.getElementById("demo").innerHTML = numbers.reduce(getSum);
}
复制代码
定义和用法
reduce() 方法接收一个函数做为累加器,数组中的每一个值(从左到右)开始缩减,最终计算为一个值。
reduce() 能够做为一个高阶函数,用于函数的 compose。
注意:
reduce()
对于空数组是不会执行回调函数的。
语法
array.reduce(function(total, currentValue, currentIndex, arr), initialValue)
复制代码
<input type="text" :value="message" @input="message = $event.target.value">
<script>
const app = new Vue({
el: '#app',
data: {
message: '你好啊'
},
methods: {
valueChange(event){
this.message = event.target.value;
}
}
})
</script>
复制代码
v-model
是语法糖,本质:
v-bind
绑定一个value
属性v-on
指令给当前元素绑定input
事件代码:
<input type="text" v-model="message">
<input type="text" v-bind:value="message" v-on:input="message = $event.target.value">
复制代码
复选框分为两种状况,单个勾选框和多个勾选框。
单个勾选框:
v-model
即为布尔值。input
的value
并不影响v-model
的值。
多个复选框:
当是多个复选框时,对应的data
中属性是一个数组。
当选中某一个时,就会将input
的value
添加到数组中。
<div id="app">
<label for="check">
<input type="checkbox" v-model="checked" id="check">赞成协议
</label>
<label><input type="checkbox" v-model="hobbies" value="篮球">篮球</label>
<label><input type="checkbox" v-model="hobbies" value="台球">台球</label>
</div>
复制代码
select
分单选和多选两种状况
单选:只能选中一个值,多选:能够选择多个值。
v-model
结合select
类型和checkbox
同样,select
分单选和多选两种状况。
单选,只能选择一个值,v-model
绑定的是一个值。当咱们选中option
中的一个时,会将它对应的value
赋值到mySelect
中。
多选,能够选中多个值。v-model
绑定的是一个数组。当选中多个值时,就会将选中的option
对应的value
添加到数组mySelects
中。
// 选择一个值
<select v-model="mySelect">
<option value="web">web</option>
<option value="it">it</option>
</select>
<p>您最喜欢的{{mySelect}}</p>
// 选择多个值
<select v-model="mySelects" multiple>
<option value="web">web</option>
<option value="it">it</option>
</select>
<p>您最喜欢的{{mySelects}}</p>
复制代码
<label v-for="item in origin">
<input type="checkbox" :value="item" v-model="hobbies">
{{item}}
</label>
复制代码
lazy
修饰符:
v-model
默认是在input
事件中同步输入框的数据的。data
中的数据就会自动发生改变。lazy
修饰符可让数据在失去焦点或者回车时才会更新。number
修饰符:
number
修饰符可让在输入框中输入的内容自动转成数字类型。trim
修饰符:
trim
修饰符能够过滤内容左右两边的空格示例:
<div id="app">
<input type="text" v-model.lazy="message">
<h2>{{message}}</h2>
</div>
复制代码
注册组件的基本步骤:
示例:
调用Vue.extend()方法建立组件构造器
调用Vue.component()方法,注册组件
在Vue实例的做用范围内使用组件
复制代码
组件示例:
<div id="app">
<my-cpn></my-cpn>
</div>
<script src="../js/vue.js"></script>
<script>
// 建立组件构造器
const myComponent = Vue.extend({
template: `
<div>
<h2>组件标题</h2>
<p>组件段落</p>
</div>`
});
// 注册组件
Vue.component('my-cpn',myComponent);
</script>
复制代码
Vue.extend()
调用Vue.extend()
建立一个组件构造器。template
表明咱们自定义组件的模板。html
代码。Vue2.x
的文档几乎看不到了。Vue.component()
是将刚才的组件构造器注册为一个组件,而且给它起一个组件的标签名称。示例:
组件标题
<div id="app">
<my-cpn><my-cpn>
<div>
<my-cpn><my-cpn>
</div>
</div>
复制代码
示例:
<div id="app1">
<my-cpn></my-cpn>
</div>
<div id="app2">
<my-cpn></my-cpn>
</div>
<script src="../js/vue.js"></script>
<script>
// 建立组件构造器
const myComponent = Vue.extend({
template: `
<div>
<h2>web</h2>
</div>
`
})
// 注册组件
Vue.component('my-cpn',myComponent);
let app1 = new Vue({
el: '#app1'
})
let app2 = new Vue({
el: '#app2'
})
复制代码
<div id="app1">
<my-cpn></my-cpn>
</div>
<div id="app2"> // 没有被渲染出来
<my-cpn></my-cpn>
</div>
<script src="../js/vue.js"></script>
<script>
// 建立组件构造器
const myComponent = Vue.extend({
template: `
<div>
<h2>web</h2>
</div>
`
})
let app1=new Vue({
el: '#app1',
components: {
'my-cpn': myComponent
}
})
let app2 = new Vue({
el: '#app2'
})
</script>
复制代码
组件树
示例:
<div id="app">
<parent-cpn></parent-cpn>
</div>
<script src="../js/vue.js"></script>
<script>
// 建立一个子组件构造器
const childComponent = Vue.extend({
template: `
<div>我是子组件的内容</div>
`
})
// 建立一个父组件的构造器
const parentComponent = Vue.extend({
template: `
<div>
我是父组件的内容
<child-cpn></child-cpn>
</div>
`
components: {
'child-cpn': childComponent
}
})
let app = new Vue({
el: '#app',
components: {
'parent-cpn': parentComponent
}
})
复制代码
注册组件的语法糖
示例:全局组件
<div id="app">
<cpn1></cpn1>
</div>
<script>
// 全局组件注册的语法糖
// 注册组件
Vue.component('cpn1', {
template: `
<div>
<h2>web</h2>
</div>
`
})
const app = new Vue({
el: '#app',
data: {
message: 'web',
}
})
</script>
复制代码
<div id="app">
<cpn2></cpn2>
</div>
// 注册局部组件的语法糖
const app = new Vue({
el: '#app',
data: {
message: 'web'
},
components: {
'cpn2': {
template: `
<div>
<h1>web</h1>
</div>
`
}
}
})
</script>
复制代码
vue
简化了注册组件的方式,提供了注册的语法糖。
vue
提供了两种定义html
模块内容:
<script>
标签<template>
标签示例:
<div id="app">
<my-cpn></my-cpn>
</div>
<script type="text/x-template" id="myCpn">
<div>
<h2>web</h2>
</div>
</script>
<script src="../js/vue.js"></script>
<script>
let app = new Vue({
el: '#app',
components: {
'my-cpn': {
template: '#myCpn'
}
}
})
</script>
复制代码
template
标签
<template id="cpn">
<div>
<h2>web</h2>
</div>
</template>
// 注册一个全局组件
Vue.component('cpn', {
template: '#cpn'
})
复制代码
组件能够访问vue实例数据吗
组件是一个单独的功能模块封装,有属于本身的html
模板和本身的数据data
。
组件对象有一个data
属性,methods
属性,这个data
属性必须是一个函数,函数返回一个对象,对象内部保存着数据。
<div id="app">
<my-cpn></my-cpn>
</div>
<template id="myCpn">
<div>{{message}}</div>
</template>
<script src="..."></script>
<script>
let app = new Vue({
el: '#app',
components: {
'my-cpn': {
template: 'myCpn',
data() {
return{
message: 'web'
}
}
}
}
})
复制代码
如何进行父子组件间的通讯呢?
props
向子组件传递数据
props
基本用法
在组件中,使用props
来声明从父级接收到的数据
props
的值:
camelCase
(驼峰命名法) 的 prop
名须要使用其等价的 kebab-case
(短横线分隔命名) 命名:
Vue.component('blog-post', {
// 在 JavaScript 中是 camelCase 的
props: ['postTitle'],
template: '<h3>{{ postTitle }}</h3>'
})
<!-- 在 HTML 中是 kebab-case 的 -->
<blog-post post-title="hello!"></blog-post>
复制代码
重申一次,若是你使用字符串模板,那么这个限制就不存在了。
prop
各自的名称和类型:
props: {
title: String,
likes: Number,
isPublished: Boolean,
commentIds: Array,
author: Object,
callback: Function,
contactsPromise: Promise // or any other constructor
}
复制代码
<!-- 动态赋予一个变量的值 -->
<blog-post v-bind:title="post.title"></blog-post>
<!-- 动态赋予一个复杂表达式的值 -->
<blog-post
v-bind:title="post.title + ' by ' + post.author.name"
></blog-post>
<!-- 即使 `42` 是静态的,咱们仍然须要 `v-bind` 来告诉 Vue -->
<!-- 这是一个 JavaScript 表达式而不是一个字符串。-->
<blog-post v-bind:likes="42"></blog-post>
<!-- 用一个变量进行动态赋值。-->
<blog-post v-bind:likes="post.likes"></blog-post>
复制代码
传入一个对象的全部属性
若是你想要将一个对象的全部属性都做为 prop 传入,你可使用不带参数的 v-bind (取代 v-bind:prop-name)
:
post: {
id: 1,
title: 'My Journey with Vue'
}
<blog-post v-bind="post"></blog-post>
<blog-post
v-bind:id="post.id"
v-bind:title="post.title"
></blog-post>
复制代码
一个简单的props
传递:
<div id="app">
<child-cpn :message="message"></child-cpn>
</div>
<template id="childCpn">
<div> 显示信息:{{message}}</div>
</template>
<script>
let app = new Vue({
el: '#app',
data: {
message: 'hello'
},
components: {
'child-cpn': {
templte: '#childCpn',
props: ['message']
}
}
})
</script>
复制代码
在 Vue
中,父子组件的关系
props
向下传递,事件向上传递。
父组件经过 props
给子组件下发数据,子组件经过事件给父组件发送消息。
props
支持的数据类型:
String
Number
Boolean
Array
Object
Date
Function
Symbol
复制代码
示例:
Vue.component('my-component',{
props: {
// 基础的类型检查
propA: Number,
// 多个可能的类型
propB: [String, Number],
// propC: {
type: String,
required: true
},
// 带有默认值的数字
propD: {
type: Number,
default: 100
},
// 带有默认值的对象
propE: {
type: Object,
default: function(){
return {message: 'web'}
}
},
// 自定义验证函数
propF: {
vfunc: function(value) {
return value > 1
}
}
}
})
复制代码
子传父
代码:
this.$emit('item-click',item)
复制代码
props
用于父组件向子组件传递数据,还有一种比较常见的是子组件传递数据或事件到父组件中。
自定义事件:
$emit()
来触发事件。v-on
来监听子组件事件。自定义事件代码:
<div id="app">
<child-cpn @increment="changeTotal" @decrement="changeTotal"></child-cpn>
<h2>点击次数</h2>
</div>
<template id="childCpn">
<div>
<button @click="increment">+1</button>
<button @click="decrement">-1</button>
</div>
</template>
let app = new Vue({
el: '#app',
data: {
total: 0
},
methods: {
changeTotal(counter) {
this.total = counter
}
},
components: {
'child-cpn': {
template: '#childCpn',
data(){
return{
counter: 0
}
},
methods: {
increment(){
this.counter++;
this.$emit('increment', this.counter)
},
decrement(){
this.counter--;
this.$emit('decrement',this.counter)
}
}
}
}
})
复制代码
$children
有时候须要父组件直接访问子组件,子组件直接访问父组件,或者是子组件访问父组件。
$children
或者$refs
$parent
对于$children
的访问:
this.$children
是一个数组类型,它包含全部子组件对象。message
状态。示例:
<div id="app">
<parent-cpn></parent-cpn>
</div>
// 父组件template
<template id="parentCpn">
<div>
<child-cpn1></child-cpn1>
<child-cpn2></child-cpn2>
<button @click="showChildCpn">显示全部子组件信息</button>
</div>
</template>
// 子组件
<template id="childCpn1">
<h2>我是子组件1</h2>
</template>
// 子组件
<template id="childCpn2">
<h2>我是子组件2</h2>
</template>
Vue.component('parent-cpn',{
template: '#parentCpn',
methods: {
showChildCpn(){
for(let i=0; i<this.$children.length; i++){
console.log(this.$children[i].message)
}
}
}
})
复制代码
$parent
子组件中直接访问父组件,能够经过$parent
$parent
来访问父组件,可是尽可能不要这样作父子组件的访问方式
$refs
$children
的缺陷:
$children
访问子组件,是一个数组类型,访问其子组件要经过索引值。$refs
$refs
的使用:
$refs
和ref
指令一般一块儿使用ref
给某个子组件绑定一个特定的id
this.$refs.id
能够访问到该组件示例:
<child-cpn1 ref="child1"></child-cpn1>
<child-cpn2 ref="child2"></child-cpn2>
<button @click="show">经过refs访问子组件</button>
show() {
console.log(this.$refs.child1.message);
console.log(this.$refs.child2.message);
}
复制代码
看看一个
.vue
文件项目
<template>
<div class="xxx">
<div class="xxx"
:class="{active: currentIndex === index}"
@click="itemClick(index)"
v-for="(item,index) in titles">
<span>{{item}}</span>
</div>
</div>
</template>
<script>
export default {
name: 'xxx',
props: {
titles: {
type: Array,
default() {
return []
}
}
},
data: function() {
return {
currentIndex: 0
}
},
}
</script>
<style scoped>
.xxx {
xxx: xxx;
}
</style>
复制代码
三层部分:
vue
中的代码slot
是什么呢,它叫插槽,<slot>
元素做为组件模板之中的内容分发插槽,传入内容后<slot>
元素自身将被替换。
v-slot
用法:
slot
以及slot-scope
的用法:子组件编写,父组件编写默认插槽
子组件:
// 子组件
<template>
<div class="content">
// 默认插槽
<content-box class="text">
<slot>默认值</slot>
<content-box>
</div>
</template>
复制代码
slot
基本使用
<slot>
能够为子组件开启一个插槽。子组件定义一个插槽:
<slot>
中的内容表示,若是没有在该组件中插入任何其余内容,就默认显示改内容。示例:
<div id="app">
<my-cpn></my-cpn>
<my-cpn>
<p>web</p>
</my-cpn>
</div>
<template id="myCpn">
<div>
<slot>我是谁</slot>
</div>
</template>
<script>
Vue.component('my-cpn',{
template: '#myCpn'
})
let app = new Vue({
el: '#app'
})
</script>
复制代码
使用具名插槽
slot
元素添加一个name
属性<slot name="web"></slot>
示例:
<div id="app">
// 没有任何内容
<my-cpn></my-cpn>
// 传入某个内容
<my-cpn>
<span slot="left">left</span>
</my-cpn>
<my-cpn>
<span slot="left">left</span>
<span slot="center">center</span>
<span slot="right">right</span>
</div>
<template id="myCpn">
<div>
<slot name="left">1</slot>
<slot name="center">2</slot>
<slot name="right">3</slot>
</div>
</template>
<script>
Vue.component('my-cpn', {
template: '#myCpn'
})
let app = new Vue({
el: '#app'
})
</script>
复制代码
编译做用域
Vue
实例属性:
父组件模板的全部东西都会在父级做用域内编译,子组件模板的全部东西都会在子级做用域内编译。
父组件替换插槽的标签,可是内容由子组件来提供。
什么是模块化,将一组模块以正确的顺序拼接到一个文件中的过程,模块是实现特定功能的一组属性和方法的封装。
利用构造函数封装对象
function web() {
var arr = [];
this.add = function(val) {
arr.push(var)
}
this.toString = function() {
return arr.join('')
}
}
var a = new web();
a.add(1); // [1]
a.toString(); // "1"
a.arr // undefined
复制代码
示例:
var ModuleA = (function(){
// 定义一个对象
var obj = {}
// 在对象内部添加变量和方法
obj.flag = true
obj.myFunc = function(info) {
console.log(info)
};
// 将对象返回
return obj
}
复制代码
if(ModuleA.flag) {
console.log('web')
}
ModuleA.myFunc('webweb')
复制代码
常见的模块化规范:
CommonJS
,AMD
,CMD
,ES6
中的Modules
什么是AMD
,异步模块定义,它是在浏览器端实现模块化开发的规范,可是该规范不是原生js
支持的,使用AMD
规范进行开发的时候须要引入第三方的库函数,就是RequireJS
。
RequireJS
解决了多个js
文件可能有依赖的关系,被依赖的文件须要早于依赖它的文件加载到浏览器;js
加载的时候浏览器会中止页面渲染,加载文件越多,页面就会失去响应时间越长。
CMD
是什么,它是通用模块定义,解决的问题和AMD
同样,不过在模块定义方式和模块加载时机上不一样,CMD
须要额外的引入第三方的库文件SeaJS
。
JavaScript模块化编程
那么什么是模块化呢
将一个项目按照功能划分,理论上一个功能一个模块,互不影响,在须要的时候载入,尽可能遵循高内聚低耦合。
了解CommonJS
CommonJS 是一种思想,本质上是可复用的JavaScript,它导出特定的对象,提供其它程序使用。
使用module.exports
和exports.obj
来导出对象,并在须要它的程序中使用require('module')
加载。
模块化的核心就是:导入和导出
导出:CommonJS
module.exports = {
flag: true,
test(a,b) {
return a+b
},
demo(a,b) {
return a*b
}
}
复制代码
导入:CommonJS
// CommonJS模块
let {test, demo, flag} = require('moduleA');
// =>
let ma = require('moduleA');
let test = ma.test;
let demo = ma.demo;
let flag = ma.flag;
复制代码
由于网站开发愈来愈复杂,js文件又不少,就会出现一些问题:
CommonJS
,定义模块,一个单独的js
文件就是一个模块,每一个模块都有本身单独的做用域,在该模块内部定义的变量,没法被其余模块读取,除了定义为global
对象的属性。
模块的导出:exports
和module.exports
模块的导入:require
node
中,每一个模块内部都有要给本身的module
对象module
对象中,有一个成员exports
也是一个对象exports
对象导出当前方法或变量,也可经过module.exports
导出node
简化了操做,exports
等于module.exports
,至关于var exports = module.exports
es模块的导入和导出
export function add(num1, num2) {
return num1 + num2
}
复制代码
export function accString(param) {
if (param == 0) {
return '关'
}else if(param == 1) {
return '开'
}
}
import {
accString
} from '../../utils'
复制代码
const name = 'web'
export default name
复制代码
export default
一个模块中包含某个功能,若是不但愿给功能命名,可让导入者本身来定:
export default function(){
console.log('web')
}
复制代码
使用:
import myFunc from '../web.js'
myFunc()
复制代码
export default
在同一个模块中,不容许同时存在多个
import
使用
export
指令导出了模块对外提供的接口
import
指令用于导入模块中的内容
import {name, age} from './web.js'
复制代码
经过*
能够导入模块中全部全部的export
变量
import * as web from './web.js'
console.log(web.name);
复制代码
首先:new Vue()
,new
一个Vue
的实例,Observe data
数据查看,init Events
绑定事件,created
执行created
方法,判断是否有el
属性,若是没有,vm.$mount(el)
表示处于未挂载状态,能够手动调用这个方法来挂载。判断是否有template
属性。
若是有el
属性,判断是否有template
属性。
实例化期和加载期 建立期间的生命周期函数:beforeCreate
和 created
,beforeMount
和 mounted
。
beforeCreate
在实例初始化后,数据观测data observer
和event/watcher
事件配置以前被调用。
更新期
运行期间的生命周期函数:beforeUpdate
和 updated
created
实例已经建立完成后被调用。
实例已完成如下的配置:数据观测data observer
,属性和方法的运算,watch/event
事件回调。
挂载阶段还没开始,$el
属性目前不可见。
beforeMount
在挂载开始以前被调用,相关的render
函数首次被调用。mounted
,vm.$el
已经挂载在文档内,对已有dom
节点的操做能够在期间进行。beforeUpdate
数据更新时调用,发生在虚拟dmo
从新渲染和打补丁以前。updated
当这个钩子被调用时,组件dom
已经更新,因此你如今能够执行依赖于dom
的操做。activated
,deactivated
,beforeDestroy
,destroyed
。实例销毁以前调用,vue
实例销毁后调用。
卸载期
销毁期间的生命周期函数:beforeDestroy
和 destroyed
实例生命周期钩子
每一个vue实例在被建立时都要通过一系列的初始化过程,须要设置数据监听,编译模板,将实例挂载到dom
并在数据变化时更新dom
等,同时在这个过程当中也会运行一些叫作生命周期钩子的函数。
用于给用户在不一样阶段添加本身代码的机会。
beforeCreate
,此时的data
是不可见的
data() {
return {
a: 1
}
},
beforeCreate() {
// red
console.log(this.a); // 看不见
}
复制代码
created
实例已经建立完成后被调用,这个时候你看不见你页面的内容,实例已完成表示:数据观测data observer
,属性和方法的运算,watch/event
事件回调。
这个时候挂载阶段还没开始,$el
属性目前不可见。
export default {
data() {
return {
a: 1
}
},
beforeCreate() {
console.log(this.a);
},
created() {
// red
console.log(this.a);
console.log(this.$el);
// 此时data数据里面的a可见,this.$el不可见
}
}
复制代码
beforeMount
在挂载开始以前被调用,相关的render
函数首次被调用。
export default{
data() {
return {
a: 1
}
},
beforeCreate() {
console.log(this.a); // 不可见
},
created() {
console.log(this.a);
console.log(this.$el); // 不可见
},
beforeMount() {
console.log(this.$el); // 不可见
}
}
复制代码
mounted
:
export default {
data() {
return {
a: 1
}
},
mounted() {
console.log(this.$el); // 此时$el 可见
}
}
复制代码
beforeUpdate
钩子,dom
更新以前调用:
beforeUpdate() {
console.log(this.a);
}
// document.getElementById("web").innerHTML
复制代码
updated
钩子,dom
更新以后调用:
updated() {
console.log(this.a);
}
// document.getElementById("web").innerHTML
复制代码
activated
和deactivated
(组件)
activated() {
console.log("组件使用了");
},
deactivated() {
console.log("组件停用了");
Data to Drag},
复制代码
keep-alive
是vue
的内置组件,能在组件切换过程当中将状态保留在内存中,防止重复渲染dom
。
<keep-alive>
包裹动态组件时,会缓存不活动的组件实例,而不会销毁它们。和<transition>
类似,<keep-alive>
是一个抽象组件:它自身不会渲染一个DOM
元素,也不会出如今父组件链中。
当组件在<keep-alive>
内被切换,它的activated
和deactivated
这两个生命周期钩子函数将会被对应指定。
它的使用是由于咱们不但愿组件被从新渲染而影响使用体验,或者是性能,避免屡次渲染下降性能。缓存下来,维持当前得状态。
场景:
keep-alive
生命周期:
初次进入时:created > mounted > activated;退出后触发 deactivated
;再次进入:会触发activated
;事件挂载的方法等,只执行一次的放在mounted
中;组件每次进去执行的方法放在 activated
中。
app.vue
父组件:
<template>
<div>
<button @click="myBtn"> myBtn </button>
<keep-alive>
<range v-if="isShow"></range>
</keep-alive>
</div>
</template>
<script>
import range from './components/range.vue'
export default {
data() {
return {
a: 1,
isShow: true
}
},
methods: {
myBtn() {
this.isShow = !this.isShow
}
},
components: {
range
}
}
</script>
复制代码
beforeDestroy
和destroyed
beeforeDestroy
类型为function
,详细:实例销毁以前调用,在这一步,实例仍然彻底可用。
该钩子在服务器端渲染期间不被调用。
destroyed
类型为function
,详细:vue
实例销毁后调用,调用后,vue
实例指示的全部东西都会解绑定,全部的事件监听器会被移除,全部的子实例也会被销毁。
该钩子在服务器端渲染期间不被调用。
beforeRouteEnter
和beforeRouteLeave
beforeRouteEnter() {
console.log('beforeRouteEnter')
},
beforeRouteLeave() {
console.log('beforeRouteLeave')
}
复制代码
vue路由使用的,路由进去和路由离开的时候添加的。
created() {
console.log('开始执行created钩子函数')
// 获取data数据
console.log('获取created属性'+this.value)
// 获取页面元素
console.log(this.$refs['example'])
this.$nextTick(()=>{
console.log('执行created建立的this.$nextTick()函数')
})
},
mounted() {
console.log('开始执行mounted钩子函数')
// 获取挂载数据
console.log('获取挂载数据--'+this.$refs['example'].innerText)
this.$nextTick(()=>{
console.log('执行mounted建立的this.$nextTick()函数')
})
},
methods: {
// 更新数据
updateDate(){
},
get(){
this.value='更新data内的value属性值'
// 获取页面元素数据
console.log(this.$refs['example').innerText)
this.$nextTick(()=>{
console.log(this.$refs['example'].innerText)
})
}
}
复制代码
var vm=new Vue({})
表示开始建立一个Vue
的实例对象,init events&liftcycle
表示刚初始化了一个vue
空的实例对象,这个时候,对象身上,只有默认的一些生命周期函数和默认事件,其余东西都没有建立,beforeCreate
生命周期函数执行的时候,data
和methods
中的数据都没有初始化。在created
中,data
和methods
都已经被初始化好了,若是要调用methods
中的方法,或者操做data
中的数据,只能在created
中操做。而后vue
开始编辑模板,把vue
代码中的那些指令进行执行,最终在内存中生成一个编译好的最终模板字符串,渲染为内存中的dom
,此时只是在内存中,渲染好了模板,并无把模板挂载到真正的页面中去。beforeMount
函数执行的时候,模板已经在内存中编译好了,可是还没有挂载到页面中去。create vm.$el and replace 'el' with it
这一步是将内存中编译好的模板,真实的替换到浏览器的页面中去。mounted
,只要执行完了mounted
,就表示整个vue
实例已经初始化完了。此时,组件从建立阶段进入到了运行阶段。
beforeUpdate
执行的时候,页面中显示的数据还旧的,而data
数据是最新的,页面还没有和最新的数据保持同步。updated
事件执行的时候,页面和data
数据已经保持同步了,都是新的。virtual dom re-render and patch
执行,先根据data
中最新的数据,在内存中,从新渲染出一份最新的内存dom
树,当最新的内存dom
树被更新以后,会把最新的内存dom
树,从新渲染到真实的页面中,完成数据从data
到view
的跟新。
beforeDestroy
钩子函数执行时,vue
实例就从运行阶段,进入到了销毁阶段。此时的实例仍是可用的阶段,没有真正执行销毁过程。destroyed
函数执行时,组件已经被彻底销毁了,都不可用了。
mvvm
的理解双向绑定的过程
视图view
,路由-控制器Controller
,数据Model
view
->dom
,viewModel
,Model
数据
传统的mvc
指用户操做会请求服务器端路由,路由会调用对应的控制器来处理,控制器会获取数据,将结果返回给前端,让页面从新渲染。
mvvm
,对于传统的前端会将数据手动渲染到页面上,mvvm
模式不须要用户收到操做dom
元素,将数据绑定到viewModel
层上,会自动将数据渲染到页面中,视图变化会通知viewModel
层更新数据。
vue
内部是如何监听message
数据的改变vue
是如何知道要通知哪些人,界面发生刷新核心:
Object.defineProperty
,监听对象属性的改变代码:
Object.keys(obj).forEach(key => {
let value = obj[key]
Object.defineProperty(obj, key, {
set(newValue) {
// 监听改变
value = newValue
},
get() {
return value
}
})
})
obj.name = 'web'
复制代码
发布者订阅者
class Dep {
constructor() {
this.subs = []
}
}
class Watcher {
constructor(name) {
this.name = name;
}
}
复制代码
对象的Object.defindeProperty
中的访问器属性中的get
和set
方法
getter
和setter
,创建watcher
并收集依赖。说明:
watcher
经过回调函数更新view
;observer
观测data
数据,经过get
通知dep
收集watcher
,dep
经过notify()
通知watcher
数据更新,watcher
经过addDep()
收集依赖。
Observer
:用于监听劫持全部data
属性,dep,watcher,view
,Compile
解析el
模板中的指令。
依照下图(参考《深刻浅出vue.js
》)
首先从初始化data
数据开始,使用Observer
监听数据,个体每一个数据属性添加Dep
,而且在Data
,有两个getter
,setter
。在它的getter
过程添加收集依赖操做,在setter
过程添加通知依赖的操做。
在解析指令或者给vue
实例设置watch选项或者调用$watch
时,生成对应的watcher
并收集依赖。
Data
经过Observer
转换成了getter/setter
的形式,来对数据追踪变化。
修改对象的值的时候,会触发对应的setter
,setter
通知以前依赖收集获得的 Dep
中的每个Watcher
,告诉它们值改变了,须要从新渲染视图。
数据双向绑定原理
Object.defineProperty
vue
在初始化数据时,会给data
中的属性使用Object.defineProperty
从新定义全部属性,当页面取到对应属性时,会进行依赖收集,若是属性发生变化会通知相关依赖进行更新操做。initData
初始化用户传入的data
数据,new Observer
将数据进行观测,this.walk(value)
进行对象的处理,defineReactive
循环对象属性定义响应式变化,Object.defineProperty
,使用Object.defineProperty
从新定义数据。
使用使用Object.defineProperty
从新定义数据的每一项。
Object.defineProperty(obj,key,{
enumerable: true,
configurable: true,
get: function reactiveGetter(){
const value=getter?getter.call(obj):val
if(Dep.target){
dep.depend()
if(childOb){
childOb.dep.depend()
if(Array.isArray(value)){
dependArray(value)
}
}
}
return value
},
set: function reactiveSetter(newVal) {
const value=getter?getter.call(obj).val
if(newVal === value || (newVal !== newVal && value !==value)){
return
}
if(process.env.NODE_ENV !== 'production' && customSetter){
customSetter()
}
val = newVal
childOb = !shallow && observe(newVal)
dep.notify()
}
})
复制代码
使用函数劫持的方式,重写了数组的方法,vue
将data
中的数组进行了原型链的重写,指向了本身定义的数组原型方法,这样当调用数组api
时,能够通知依赖跟新,若是数组中包含着引用类型,会对数组中的引用类型再次进行监控。
initData
初始化用户传入的data
数据,new Observer
将数据进行观测,protoAugment(value,arrayMethods)
将数据的原型方法指向重写的原型。
observerArray
深度观察数组中的每一项代码:
if(Array.isArray(value)){
// 判断数组
if(hasProto){
protoAugment(value, arrayMethods)// 改写数组原型方法
}else{
copyAugment(value,arrayMethods,arrayKeys)
}
this.observeArray(value)
//深度观察数组中的每一项
}else{
this.walk(value)
// 从新定义对象类型数据
}
function protoAugment(target, src: Object){
target.__proto__ = src
}
export const arrayMethods = Object.create(arrayProto)
const methodsToPatch=[
'push',
'pop',
'shift',
'unshift',
'splice',
'sort',
'reverse'
]
methodsToPatch.forEach(function (method){
const original = arrayProto[method]
def(arrayMethods, method, function mutator(...args){
const result = original.apply(this.args)
const ob = this.__ob__
let inserted
switch(method) {
case 'push':
case 'unshift':
inserted = args
break
case 'splice':
inserted = args.slice(2)
break
}
if(inserted) ob.observerArray(inserted)
// 对插入的数据再次进行观测
ob.dep.notify()
// 通知视图更新
return result
}
}
observeArray(items: Array<any>) {
for(let i=0, l = items.length; i<1; i++) {
observe(item[i])
// 观测数组中的每一项
}
}
复制代码
若是不采用异步更新,每次更新数据都会对当前组件进行从新渲染,为了性能考虑。
dep.notify()
通知watcher
进行更新操做,subs[i].update()
依次调用watcher
的update
,queueWatcher
将watcher
去重放到队列中,nextTick(flushSchedulerQueue)
异步清空watcher
队列。
微任务高于宏任务先执行
nextTick
方法主要使用了宏任务和微任务,定义了一个异步方法,屡次调用了nextTick
会将方法存入到队列中,经过这个异步方法清空当前队列。
nextTick
方法是异步方法。
原理:nextTick(cb)
调用nextTick
传入cb
,callbacks.push(cb)
将回调存入数组中,timerFunc()
调用timerFunc
,返回promise
支持promise
的写法。
什么是webpack,webpack是一个现代的JavaScript应用的静态模块打包工具。
webpack是前端模块化打包工具
安装webpack须要安装node.js,node.js自带有软件包管理工具npm
全局安装
npm install webpack@3.6.0 -g
复制代码
局部安装
npm install webpack@3.6.0 --save-dev
复制代码
webpack.config.js
固定名文件:
const path = require("path")
module.exports = {
entry: './src/main.js',
output: {
patch: './dist',
filename: ''
},
}
复制代码
package.json
{
"name": 'meetwebpack',
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo ..."
},
"author": "",
"license": "ISC"
}
复制代码
什么是loader
loader
是webpack
中一个很是核心的概念
loader
使用过程:
npm
安装须要使用的loader
webpack.config.js
中的moudules
关键字下进行配置package.json
中定义启动
{
"name": "meetwebpack",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"build": "webpack"
},
"author": "",
"license": "ISC",
"devDependencies": {
"webpack": "^3.6.0"
}
}
复制代码
webpack
的介绍webpack
能够看作是模块打包机,它能够分析你的项目结构,找到JavaScript模块以及其它的一些浏览器不能直接运行的拓展语言,将其打包为合适的格式以供浏览器使用。
能够实现代码的转换,文件优化,代码分割,模块合并,自动刷新,代码校验,自动发布。
安装本地的webpack
webpack webpack-cli -D
复制代码
初始化:
yarn init -y
复制代码
yarn add webpack webpack-cli -D
复制代码
webpack能够进行0配置,它是一个打包工具,能够输出后的结果(Js模块),打包(支持js的模块化)
运行webpack命令打包
npx webpack
复制代码
webpack.config.js
,webpack
是node
写出来的node
的写法:
let path = require('path')
console.log(path.resolve('dist');
module.exports = {
mode: 'development',
// 模式,默认两种,production,development
entry: '' // 入口
output: {
filename: 'bundle.js',
// 打包后的文件名
path: path.resolve(__dirname, 'build'),
// 把相对路径改写为绝对路径
}
}
复制代码
自定义,webpack.config.my.js
使用命令:
npx webpack --config webpack.config.my.js
复制代码
package.json
:
{
"name": 'webpack-dev-1',
"version": "1.0.0",
"main": "index.js",
"license": "MIT",
"scripts": {
"build": "webpack --config webpack.config.my.js"
},
"devDependencies": {
"webpack": "^4.28.3",
"webpack-cli": "^3.2.0"
}
}
复制代码
使用命令:
npm run build
// npm run build -- --config webpack.config.my.js
复制代码
开发服务器的配置
代码:
let path = require('path')
let HtmlWebpackPlugin = require('html-webpack-plugin')
console.log(path.resolve('dist');
module.exports = {
devServer: {
// 开发服务器的配置
port: 3000,
// 看到进度条
progress: true,
contentBase: "./build",
compress: true
},
mode: 'development',
// 模式,默认两种,production,development
entry: '' // 入口
output: {
filename: 'bundle.js',
// 打包后的文件名
path: path.resolve(__dirname, 'build'),
// 把相对路径改写为绝对路径
},
plugins: [
// 数组,全部的webpack插件
new HtmlWebpackPlugin({
template: './src/index.html',
filename: 'index.html',
minify:{
removeAttributeQuotes: true,//删除“”
collapseWhitespace: true, // 变成一行
},
hash: true
})
],
module: {
// 模块
rules: [
// 规则
{test: /\.css$/, use: [{
loader: 'style-loader',
options: {
insertAt: 'top'
}
},'css-loader'] },
]
}
}
复制代码
output: {
filename: 'bundle.[hash:8].js',// 打包文件名后只显示8位
}
复制代码
{
"name": 'webpack-dev-1',
"version": "1.0.0",
"main": "index.js",
"license": "MIT",
"scripts": {
"build": "webpack --config webpack.config.my.js",
"dev": "webpack-dev-server"
},
"devDependencies": {
"webpack": "^4.28.3",
"webpack-cli": "^3.2.0"
}
}
复制代码
yarn add css-loader style-loader -D
复制代码
样式:
style-loader
将模块的导出做为样式添加到dom
中css-loader
解析css
文件后,使用import
加载,而且返回css
代码less-loader
加载和转译less
文件sass-loader
加载和转译sass/scss
文件postcss-loader
使用PostCSS
加载和转译css/sss
文件stylus-loader
加载和转译Stylus
文件style-loader
安装:
npm install style-loader --save-dev
复制代码
用法:
建议将style-loader
与css-loader
结合使用
component.js
import style from './file.css'
复制代码
css-loader
只负责将css文件进行加载style-loader
负责将样式添加到dom
中loader
时,是从右到左代码:
// webpack.config.js
module: {
rules: [
{
test: /\.css$/,
use: ['style-loader', 'css-loader']
}
]
}
复制代码
css
文件处理:style-loader
安装style-loader
npm install --save-dev style-loader
复制代码
style-loader
须要放在css-loader
的前面,webpack
在读取使用的loader
的过程当中,是按照从右向左的顺序读取的。
webpack.config.js
的配置以下:
const path = require('path')
module.exports = {
// 入口:能够是字符串/数组/对象,这里咱们入口只有一个,因此写一个字符串便可。
entry: './src/main.js',
// 出口:一般是一个对象,里面至少包含两个重要属性,path和filename
output:{
path: path.resolve(__dirname, 'dist'), // 注意:path一般是一个绝对路径
filename: 'bundle.js'
},
module: {
rules: {
{
test: /\.css$/,
use: ['style-loader','css-loader']
}
}
}
}
复制代码
webpack
less文件处理安装:
npm install --save-dev less-loader less
复制代码
示例:
将css-loader
,style-loader
,less-loader
链式调用,能够把全部样式当即应用于dom
。
// webpack.config.js
module.exports = {
...
rules: [{
test: /\.less$/,
use: [{
loader: 'style-loader'
},{
loader: 'css-loader'
},{
loader: 'less-loader'
}]
}]
}
复制代码
图片文件处理
css normal
代码:
body {
background: url("../img/test.jpg")
}
复制代码
url-loader
npm install --save-dev url-loader
复制代码
用法
url-loader
功能相似于file-loader
,可是在文件大小低于指定的限制时,能够返回一个DataURL
import img from './image.png'
复制代码
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.(png|jpg|gif)$/,
use: [
{
loader: 'url-loader',
options: {
limit: 8192
}
}
]
}
]
}
}
复制代码
img
,文件要打包到的文件夹
name
,获取图片原来的名字,放在该位置
hash:8
,为了防止图片名称冲突,依然使用hash
,可是咱们只保留8位
ext
,使用图片原来的扩展名
若是但愿es6转成es5,那么就须要使用babel
npm install --save-dev babel-loader@7 babel-core babel-preset-es2015
复制代码
配置webpack.config.js
文件:
{
test: /\.m?js$/,
use: {
loader: 'babel-loader',
options: {
presets: ['es2015']
}
}
}
复制代码
如何在咱们的webpack
环境中集成vue.js
代码:
npm install vue --save
复制代码
runtime-only
代码中,不能够有任何的template
runtime-compiler
代码中,能够有template
由于有compiler
能够用于编译template
spa
(simple age web application
)->vue-router
(前端路由)
.vue
文件封装处理
安装vue-loader
和vue-template-compiler
npm install vue-loader vue-template-compiler --save-dev
复制代码
plugin
是什么?plugin
是插件的意思,一般用于对某个现有的架构进行扩展。webpack
中的插件,是对webpack
现有功能的各类扩展。loader
和plugin
的区别loader
主要用于转换某些类型的模块,它是一个转换器。plugin
是插件,它是对webpack
自己的扩展,是一个扩展器。plugin
的使用过程:npm
安装须要使用的plugins
webpack.config.js
中的plugins
中配置插件webpack.config.js
的文件:
查看bundle.js
文件的头部:
什么是vue cli
,Command-Line Interface
,命令行界面,俗称脚手架,vue cli
是一个官方发布的项目脚手架。使用vue-cli
能够快速搭建vue
开发环境以及对应的webpack
配置。
vue cli
的使用
安装vue
脚手架
npm install -g @vue/cli
复制代码
代码:
vue init webpack vuecli2test
复制代码
Project name
项目名称,不能包含大写Project description
项目描述Author
做者信息Vue build``runtime
Install vue-router``no
是否安装等目录结构详解
build``config
是 webpack
相关配置,node_modules
是依赖的node
相关的模块,src
是写代码地方。 .babelrc
是es代码相关转换配置,.editorconfig
项目文本相关配置,.gitignore``git
仓库忽略的文件夹配置,.postcssrc.js
为css
相关转化的配置。
.editorconfig
前端模块化:
为何使用模块化,简单写js代码带来的问题,闭包引发代码不可复用,本身实现了简单的模块化,es
中模块化的使用:export
和import
。
npm install @vue/cli -g
复制代码
npm clean cache -force
复制代码
vue cli2
初始化:
vue init webpack my-project
复制代码
vue cli3
初始化项目:
vue create my-project
复制代码
箭头函数,是一种定义函数的方式
function
const a = function(){
}
复制代码
const obj = {
b: function() {
},
b() {
}
}
复制代码
const c = (参数列表) => {
}
const c = () => {
}
复制代码
箭头函数参数和返回值
代码:
const sum = (num1, num2) => {
return num1 + num2
}
const power = (num) => {
return num * num
}
const num = (num1,num2) => num1 + num2
复制代码
const obj = {
a() {
setTimeout(function() {
console.log(this); // window
})
setTimeout(()=>{
console.log(this); // obj对象
})
}
}
复制代码
路由,,vue-router
基本使用,vue-router
嵌套路由,vue-router
参数传递,vue-router
导航守卫。
路由是一个网络工程里面的术语,路由就是经过互联的网络把信息从源地址传输到目的地址的活动。
路由器提供了两种机制:路由和转送。路由是决定数据包历来源到目的地的路径,转送将输入端的数据转移到合适的输出端。路由中有一个很是重要的概念叫路由表。路由表本质上就是一个映射表,决定了数据包的指向。
后端路由:后端处理url和页面之间的映射关系。
vue-router
和koa-router
的区别:
vue-router
是前端路由,koa-router
是后端路由。
vue-router
前端路由原理:
前端路由主要模式:hash
模式和history
模式。
路由的概念来源于服务端,在服务端中路由描述的是 URL 与处理函数之间的映射关系。
先后端渲染之争
hash
和html5
的history
前端路由的核心是改变url
,可是页面不进行总体的刷新。单页面,其实spa
最重要的特色就是在先后端分离的基础上加了一层前端路由。就是前端来维护一套路由规则。
url
的hash
url
的hash
是锚点#
,本质上是改变window.location
的href
属性。直接赋值location.hash
来改变href
,可是页面不发生刷新。
html5
的history
模式:pushState
html5
的history
模式:replaceState
html5
的history
模式:go
history.go()
history.back()
等价于history.go(-1)
history.forward()
等价于history.go(1)
安装vue-router
npm install vue-router --save
复制代码
Vue.use(VueRouter)
Vue
实例中挂载建立的路由实例代码:
// 配置路由相关的信息
import VueRouter from 'vue-router'
import vue from 'vue'
import Home from '../components/Home'
import About from '../components/About'
// 经过Vue.use(插件),安装插件
Vue.use(VueRouter)
// 配置路由和组件之间的应用关系
const routes = [
{
path: '/home',
component: Home
},
{
path: '/about',
component: About
}
]
// 建立VueRouter对象
const router = new VueRouter({
routes
})
// 将router对象传入到`Vue`实例
export default router
复制代码
main.js
import Vue from 'vue'
import App from './App'
import router from './router'
Vue.config.productionTip = false
new Vue({
el: '#app',
router,
render: h => h(App)
})
复制代码
使用vue-router
的步骤
<router-link>
和<router-view>
代码:
组件components
// home
<template>
<div>
<h2>我是首页</h2>
</div>
</template>
<script>
export default {
name: 'Home'
}
</script>
<style scoped>
</style>
复制代码
<template>
<div>
<h2>我是关于</h2>
</div>
</template>
<script>
export default {
name: 'Aboout'
}
</script>
<style scoped>
</style>
复制代码
App.vue
<template>
<div id="app">
<router-link to="/home">首页</router-link>
<router-link to="/about">关于</router-link>
<router-view></router-view>
</div>
</div>
<script>
export default {
name: 'App'
}
</script>
<style>
</style>
复制代码
main.js
import Vue from 'vue'
import App from './App'
import router from './router'
Vue.config.productionTip = false
new Vue({
el: '#app',
router,
render: h => h(App)
})
复制代码
路由的偶然值和修改成
history
模式
建立router
实例
代码:
router->index.js
import Vue from 'vue'
import VueRouter from 'vue-router'
// 注入插件
Vue.use(VueRouter)
// 定义路由
const routes = []
// 建立router实例
const router = new VueRouter({
routes
})
// 导出router实例
export default router
复制代码
main.js
代码:
import Vue from 'vue'
import App from './App'
import router from './router'
new Vue({
el: '#app',
router,
render: h=>h(App)
})
复制代码
router->index.js
import Vue from 'vue'
import VueRouter from 'vue-router'
import Home from '../components/home'
import About from '../components/about'
// 注入插件
Vue.use(VueRouter)
// 定义路由
const routes = [
{
path: '/home',
component: Home
},
{
path: '/about',
component: About
}
]
复制代码
使用App.vue
代码
<template>
<div id="app">
<router-link to="/home">首页</router-link>
<router-link to="/about">关于</router-link>
<router-view></router-view>
</div>
</template>
<script>
export default {
name: 'App',
components: {
}
}
复制代码
<router-link>
该标签是一个vue-router
已经内置的组件,它会被渲染成一个<a>
标签<router-view>
该标签会根据当前的路径,动态渲染出不一样的组件。<router-view>
处于同一个等级。<router-view>
挂载的组件,其余内容不会发生改变。路由的默认路径
默认状况下,进入网站的首页,<router-view>
渲染首页的内容,可是默认没有显示首页组件,必须让用户点击才能够。
那么如何让路径默认跳转到首页,而且<router-view>
渲染首页组件呢,只须要配置一个映射就能够:
const routes = [
{
path: '/',
redirect: '/home'
}
]
复制代码
配置解析:在routes
中又配置了一个映射,path
配置的是根路径:/
,redirect
是重定向,就是咱们将根路径重定向到/home
的路径下。
// main.js
const router = new VueRouter({
// 配置路由和组件之间的应用关系
routes,
mode: 'history'
})
复制代码
改变路径的方式:
url
的hash
html5
的history
url
的hash
使用html5
的history
模式:
// 建立router实例
const router = new VueRouter({
routes,
mode: 'history'
})
复制代码
router-link
,使用了一个属性:to
,用于指定跳转的路径。tag
能够指定<router-link>
以后渲染成什么组件。
replace
属性不会留下history
记录,指定replace
的状况下,后退键返回不能返回到上一个页面中。
active-class
属性,当<router-link>
对应的路由匹配成功时,会自动给当前元素设置一个router-link-active
的class
,设置active-class
能够修改默认的名称。
const router = new VueRouter({
routes,
mode: 'history',
linkActiveClass: 'active'
})
复制代码
App.vue
代码:
// app.vue
<template>
<div id="app">
<button @click="linkToHome">首页</button>
<button @click="linkToAbout">关于</button>
<router-view></router-view>
</div>
</template>
<script>
export default {
name: 'App',
methods: {
linkToHome() {
this.$router.push('/home')
},
linkToAbout() {
this.$router.push('/about')
}
}
}
</script>
复制代码
<img :src="imgURL" alt="">
<router-link :to="'/uer/' + userId"> 用户 </router-link>
<script>
export default {
name: 'User',
computed: {
userId() {
return this.$route.params.userId
}
}
}
</sript>
复制代码
const Home = () => import('../components/Home')
const HomeNews = () => import('../components/HomeNews')
const HomeMessage = () => import('../components/HomeMessage')
{
path: '/home',
component: Home,
children: [
{
path: 'news',
component: HomeNews
},
{
path: 'news',
component: HomeMessage
}
]
}
复制代码
<router-link to = "/home/news">新闻</router-link>
<router-link to = "/home/message">信息</router-link>
复制代码
默认选中:
传递参数主要有两种类型,params
和query
params
的类型:
/router/:id
path
后面跟着对应的值/router/123
vue-router
传递参数代码
<router-link :to="{path: '/profile'}">用户</router-link>
复制代码
统一资源定位符
统一资源定位符,统一资源定位器,统一资源定位地址,Url地址等,网页地址。如同在网络上的门牌,是因特网上标准的资源的地址。
userClick() {
this.$router.push('/user/' + this.userId)
}
btnClick() {
this.$router.push({
path: '/user',
query: {
name: 'web',
age: 12,
height: 1.2
}
})
}
复制代码
$route
和$router
是有区别的
获取参数经过$route
对象获取的,在使用vue-router
的应用中,路由对象会被注入每一个组件中,赋值为this.$route
,而且当路由切换时,路由对象会被更新。
<template>
<div>
<p> {{$route.params}} </p>
</div>
</template>
复制代码
query
的类型:
/router
也是普通配置query
的key
做为传递方式router?id=123
,/router?id=abc
$route
和$router
是有区别的
const router = new VueRouter({
routes,
mode: 'history',
linkActiveClass: 'active'
})
复制代码
Vue.config.productionTip = false
Vue.prototype.test = function() {
console.log('test')
}
Vue.prototype.name = 'web'
复制代码
$route
和$router
是有区别的
$router
为VueRouter
实例,想要导航到不一样url
,则使用$router.push
方法。$route
为当前router
跳转对象里面能够获取name
,path
,query
,params
等。vue-router
全局导航
meta:元数据
router.beforeEach((to,from,next) => {
// from 跳转到to
document.title = to.matched[0].meta.title
console.log(to);
next()
})
复制代码
// 后置钩子hook
router.afterEach((to,from) => {
console.log();
})
复制代码
导航守卫:导航表示路由正在发生改变。
vue-router
提供的导航守卫主要用来经过跳转或取消的方式守卫导航。有多种机会植入路由导航过程当中,全局的,单个路由独享的,或者组件级的。
全局守卫
可使用router.beforeEach
,注册一个全局前置守卫:
const router = new VueRouter({..})
router.beforeEach((to,from,nex)=>{
})
复制代码
当一个导航触发时,全局前置守卫按照建立顺序调用。守卫是异步解析执行,此时导航在全部守卫resolve
完以前一直处于等待中。
to:Route
,即将要进入的目标路由对象from:Route
,当前导航正要离开的路由next:Function
,必定要调用该方法来resolve
这个钩子。vue-router-keep-alive
keep-alive
和vue-router
router-view
是一个组件,若是直接被包含在keep-alive
里面,全部路径匹配到的视图组件都会被缓存。
keep-alive
是Vue
内置的一个组件,可使被包含的组件保留状态,或避免从新渲染。
属性:
include
字符串或正则表达式,只有匹配的组件会被缓存exclude
字符串或正则表达式,任何匹配的组件都不会被缓存<keep-alive>
<router-view>
// 全部路径匹配到的视图组件都会被缓存
</router-view>
<keep-alive>
复制代码
Promise
的使用es6
的特性Promise
,它是异步编程的一种解决方案。
定时器的异步事件:
setTimeout(function() {
let data = 'web'
console.log(content)
},1000)
new Promise((resolve, reject) => {
setTimeout(function(){
resolve('web')
reject('error')
},1000)
}).then(data=>{
console.log(data)
}).catch(error=> {
console.log(error)
})
复制代码
Promise
三种状态:
pending
等待状态,好比正在进行网络请求,或定时器没有到时间。fulfill
,知足状态,主动回调resolve
时,而且回调.then()
reject
,拒绝状态,回调reject
时,而且回调.catch()
vuex
是一个专门为vue.js
应用程序开发的状态管理模式
它采用集中式存储管理应用的全部组件的状态,,并以相应的规则保证状态以一种可预测的方式发生变化。
View components -> actions(dispatch方式) -> mutations(commit方式) -> state -> View components
复制代码
Vuex
核心概念5个:
State
,Getters
,Mutation
,Action
,Module
State
单一状态树,单一数据源。
Mutation
状态更新
Vuex
的store
的更新惟一方式,提交Mutation
Mutation
的主要包括两部分:
state
mutation
的定义:
mutations: {
increment(state) {
state.count++
}
}
复制代码
经过mutation
更新
increment: function() {
this.$store.commit('increment')
}
复制代码
参数被称为是mutation
的载荷payload
Vuex
的store
中的state
是响应式的,当state
中的数据发生改变时,Vue
组件会自动更新。
store
中初始化好所需的属性state
中的对象添加新属性时:使用Vue.set(obj,'newObj',123)
Mutation
常量类型
// mutation-types.js
export const UPDATE_INFO = 'UPDATE_INFO'
import Vuex from 'vuex'
import Vue from 'vue'
import * as types from './mutation-types'
Vue.use(Vuex)
const store = new Vuex.Store({
state: {
info: {
name: 'web',
age: 12
}
},
mutations: {
[types.UPDATE_INFO](state, payload) {
state.info = {...state.info, 'height': payload.height
}
}
})
复制代码
<script>
import {UPDATE_INFO} from './store/mutation-types';
export default{
name: 'App',
components: {
},
computed: {
info(){
return this.$store.state.info
}
},
methods: {
updateInfo(){
this.$store.commit(UPDATE_INFO,{height:1.00})
}
}
}
</script>
复制代码
注意:不要再mutation
中进行异步操做,mutation
同步函数,在其中的方法必须时同步方法。
action
的基本定义,若是有异步操做,好比网络请求,
// 不能再mutation中使用异步操做,不能再这里进行异步操做
update(state) {
setTimeout(()=>{
state.info.name = 'web'
},1000)
}
mutations: {
// 方法
[INCREMENT](state){
state.counter++
}
}
复制代码
actions: {
// context:上下文,=》store
<!--aUpdateInfo(context) {-->
<!-- setTimeout(()=>{-->
<!-- state.info.name = 'web'-->
<!-- },1000)-->
<!--}-->
}
复制代码
actions: {
aUpdateInfo(context) {
setTimeout(()=>{
context.commit('updateInfo')
},1000)
}
}
// xx.vue
updateInfo(){
this.$store.dispatch('aUpdateInfo')
}
复制代码
updateInfo(){
<!--this.$store.commit('updateInfo')-->
this.$store.dispatch('aUpdateInfo',{
message: 'web',
success: () => {
console.log('web')
}
})
}
复制代码
aUpdateInfo(context, payload) {
return new Promise((resolve, reject) => {...})
}
复制代码
modules时模块的意思
getters: {
stu(){
},
stuLength(state, getters) {
return getters.stu.length
}
}
复制代码
使用根数据:
getters: {
fullName(state) {
return state.name + '1'
},
fullName1(state, getters) {
return getters.fullName + '2'
},
fullName3(state, getters, rootState) {
return getters.fullName2+rootState.counter
}
}
复制代码
在模块中actions
打印console.log(context)
actions
接收一个context
参数对象,局部状态经过context.state
暴露出来,根节点状态为context.rootState
import mutations from './mutations'
import actions from './actions'
import getters from './getters'
import moduleA from './modules/moduleA'
import Vuex from 'vuex'
import Vue from 'vue'
Vue.use(Vuex)
const state = {
}
const store = new Vuex.Store({
state,
mutations,
actions,
getters,
modules: {
a: moduleA
}
})
export default store
复制代码
axios网络模块的封装
ajax
是基于XMLHttpRequest(XHR)
;jQuery-Ajax
相对于传统的ajax
很是好用。
axios
特色:
XMLHttpRequests
请求node.js
中发送http
请求Promise API
axios
请求方式:
axios(config)
axios.request(config)
axios.get()
axios.delete()
axios.head()
axios.post()
axios.put()
axios.patch()
复制代码
安装
npm install axios --save
复制代码
axios({
// 默认get
url: '',
method: 'get'
}).then(res=>{
console.log(res)
})
复制代码
// import request from "../utils/request.js"
import {request} from './network'
export function getHome() {
return request({
url: '/home/xxx'
})
}
export function getXX(type, page) {
return request({
url: '/home/xx',
params: {
type,
page
}
})
}
复制代码
并发请求
代码:
axios.all([axios({
url: ''
}), axios({
url: '',
params: {
type: '',
page: 1,
}
})]).then(results => {
})
// then(axios.spread((res1,res2)=>{...}))
复制代码
全局配置
axios.defaults.baseURL=''
axios.all ..{
url: '/home'
}
axios.defaults.baseURL = 'https://api.example.com';
axios.defaults.headers.common['Authorization'] = AUTH_TOKEN;
axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';
axios.defaults.baseURL = global.HOST;
复制代码
request.js
import axios from 'axios'
export function request(config,success,failure){
// 建立axios实例
const instance = axios.create({
baseURL: '',
timeout: 5000
})
// 发送网络请求
instance(config)
.then(res=>{
success(res)
})
.catch(err=>{
failure(err)
})
}
复制代码
main.js
import {request} from './xx/request'
request({
url: ''
},res=>{
),err=>{
}
复制代码
也可使用promise
方法,不过自己返回的就是promise
import axios from 'axios'
export function request(config) {
const instance = axios.create({
baseURL: '',
timeout: 2000
})
return instance(config)
}
复制代码
axios
拦截器的使用
// 配置请求和响应拦截
instance.interceptors.request.use(config => {
console.log('request拦截success中')
return config
},err => {
console.log('request拦截failure中')
return err
})
instance.interceptors.response.use(response => {
console.log('response拦截success中')
return response.data
},err => {
console.log('response拦截failure中')
return err
})
复制代码
封装axios
// request.js
import axios from 'axios'
cosnt service = axios.create({
baseURL: process.env.BASE_API,
timeout: 2000
})
service.interceptors.request.use(config=>{
//发请求前作的一些处理,数据转化,配置请求头,设置token,设置loading等
config.data=JSON.stringify(config.data);
config.headers = {
'Content-Type':'application/x-www-form-urlencoded'
}
return config
},error=>{
Promise.reject(error)
})
// 响应拦截器
service.interceptors.response.use(response => {
return response
}, error => {
if (error && error.response) {
switch (error.response.status) {
case 400:
error.message = '错误请求'
break;
case 401:
error.message = '未受权,请从新登陆'
break;
case 403:
error.message = '拒绝访问'
break;
case 404:
error.message = '请求错误,未找到该资源'
window.location.href = "/NotFound"
break;
case 405:
error.message = '请求方法未容许'
break;
case 408:
error.message = '请求超时'
break;
case 500:
error.message = '服务器端出错'
break;
case 501:
error.message = '网络未实现'
break;
case 502:
error.message = '网络错误'
break;
case 503:
error.message = '服务不可用'
break;
case 504:
error.message = '网络超时'
break;
case 505:
error.message = 'http版本不支持该请求'
break;
default:
error.message = `链接错误${error.response.status}`
}
} else {
if (JSON.stringify(error).includes('timeout')) {
Message.error('服务器响应超时,请刷新当前页')
}
error.message('链接服务器失败')
}
Message.error(err.message)
return Promise.resolve(error.response)
})
// 导入文件
export default service
复制代码
封装请求http.js
import request from './request'
const http ={
/**
* methods: 请求
* @param url 请求地址
* @param params 请求参数
*/
get(url,params){
const config = {
methods: 'get',
url:url
}
if(params){
config.params = params
}
return request(config)
},
post(url,params){
const config = {
methods: 'post',
url:url
}
if(params){
config.data = params
}
return request(config)
},
put(url,params){
const config = {
methods: 'put',
url:url
}
if(params){
config.params = params
}
return request(config)
},
delete(url,params){
const config = {
methods: 'delete',
url:url
}
if(params) {
config.params = params
}
return request(config)
}
}
export default http
复制代码
// api.js
import http from '../utils/http'
let resquest = "/xx/request/"
// get请求
export function getListAPI(params){
return http.get(`${resquest}/getList.json`,params)
}
// js
//建立新的axios实例,
const service = axios.create({
baseURL: process.env.BASE_API,
timeout: 3 * 1000
})
复制代码
建立项目:
vue create webMall
npm run serve
复制代码
// .editorconfig
root = true
[*]
charset = utf-8
indent_style=space
indent_size = 2
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
复制代码
项目在
window
下部署
main.js
代码:
import store from './store'
import FastClick from 'fastclick'
import VueLazyLoad from 'vue-lazyload'
import toast from 'components/common/toast'
Vue.config.productionTip = false
// 添加事件总线对象
Vue.prototype.$bus = new Vue()
// 安装toast插件
Vue.use(toast)
// 解决移动端300ms延迟
FastClick.attach(document.body)
// 使用懒加载的插件
Vue.use(VueLazyLoad,{
loading: require('./xx.png')
})
复制代码
windows
安装nginx
,linux
部署,centos
上安装nginx
linux ubuntu
Ubuntu
是一个以桌面应用为主的Linux
操做系统,其名称来自非洲南部祖鲁语或豪萨语的“ubuntu"
一词。
操做系统:Window10 + Centos6.5(虚拟机)
yum install nginx
systemtl start nginx.service
systemctl enable nginx.service
复制代码
经过Xftp将vue项目文件上传至云服务器
使用Xshell链接云服务器
主机就是阿里云上建立的实例的公网ip
输入登陆名和密码,登陆名就是购买服务器时输入的登陆名和密码。
运行npm run build
命令,有一个dist文件夹,这就是vue项目打包后的文件。
nginx安装配置
在Xshell
终端输入命令yum install nginx
,当须要确认时输入”y“
回车。
安装完成后,输入service nginx start
启动nginx
服务。
经过命令nginx -t
查看nginx
所在的安装目录。
在命令行输入命令cd/etc/nginx
切换到nginx
目录下,再输入cat nginx.conf
可查看当前nginx
配置文件。
输入命令 wget https://nodejs.org/dist/v10.8.0/node-v10.8.0-linux-x64.tar.xz
回车,等待安装。
输入命令tar xvf node-v10.8.0-linux-x64.tar.xz
回车进行解压操做。
stop
,prevent
,.enter
,.once
,.native
等,lazy
,number
,trim
等。script
,template
props
,子传父,$emit
npm install
,npm run serve
webStorm
开发vue
在Plugins
安装插件vue.js
2.6.0
版本中,Vue
为具名插槽和做用域插槽引入了一个新的统一的语法 (即 <v-slot>
指令)。它取代了 slot
和 slot-scope
这两个目前已被废弃、还没有移除,仍在文档中的特性。v-slot
用法,分为三类:默认插槽、具名插槽以及做用域插槽。做用域插槽,经过 slot-scope
属性来接受子组件传入的属性集合
代码:
// 子组件
<template>
<div>
<header>
<slot>默认值</slot>
</header>
</div>
</template>
复制代码
任何没有被包裹在带有v-slot
的<template>
中的内容都会被视为默认插槽的内容。当子组件只有默认插槽时,<v-slot>
标签能够直接用在组件上
// 父组件
<template>
<div>
<child>
内容1
<template>内容2</template>
内容3
</child>
<child v-slot="web">
插槽<br>
插槽<br>
</child>
</div>
</template>
复制代码
v-slot
重复定义一样的 name
后只会加载最后一个定义的插槽内容// 子组件
<template>
<div>
<main>
<slot name="main"></slot>
</main>
<footer>
<slot name="footer"></slot>
</footer>
</div>
</template>
复制代码
// 子组件
<template>
<div>
<footer>
<slot name="footer" :user="user" :testBtn="testBtn">
{{user.name}}
</slot>
</footer>
</div>
</template>
<script>
exportdefault {
name: 'child',
data () {
return {
user: {
title: 'web',
name: 'web'
}
};
},
methods:{
testBtn(){
alert('web');
}
}
};
</script>
复制代码
Vue
如何直接调用Component
里的方法
<template>
<div>
<b-component ref="BComponent"></b-component>
</div>
</template>
<script>
import BComponent from './BComponent'
export default {
name: 'A',
data () {
},
components: {
BComponent
},
methods: {
callACompoentFunction () {
this.$refs.BComponent.sayHi()
}
}
}
</script>
<style scoped>
</style>
复制代码
<template>
<div></div>
</template>
<script>
export default {
name: 'B',
data () {
},
methods: {
sayHi () {
console.log('web!')
}
}
}
</script>
<style scoped>
</style>
复制代码
欢迎加我微信Jeskson(xiaoda0423
),拉你进技术群(掘金前端群,达达前端技术社群⑥),长期交流学习。