1、基于MV*模式的框架
(1)Model绑定View
(2)没有控制器
(3)数据驱动,状态管理
2、核心思想
(1)数据驱动:非直接操作节点,是通过变量绑定数据
(2)组件化:抽离公用的代码,形成一个个组件
通过MVVM的数据绑定实现自动同步
(3)模拟双向绑定
<input type="text" name="" id="username" />
<span id="uName"></span>
<script type="text/javascript">
var obj = {};
// 三个参数:1、对象名 2、对象的要定义或修改属性 3、对定义或修改的属性描述
Object.defineProperty(obj, "username", {
get: function() { // 获取该对象属性时执行
console.log("get init");
},
set: function(val) { // 设置该对象属性时执行
document.getElementById("uName").innerHTML = val;
document.getElementById("username").value = val;
}
});
document.getElementById("username").addEventListener("keyup", function(event) {
obj.username = event.target.value;
});
</script>
(4)单文件组件,一个文件由html、js、css组成
<template> 先是template
<div id="app">
<img src="./assets/logo.png">
<router-view/>
</div>
</template>
<script> 这里是js
export default {
name: 'App'
}
</script>
<style> 最后是css, 若写成<style scoped>是确认当前作用域,不会污染别的文件
#app {
font-family: 'Avenir', Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>
3、安装
这里使用npm安装(使用git-bash命令行)
(1)安装node.js
(2)npm官方镜像比较慢,这里使用淘宝NPM镜像
$ npm install -g cnpm --registry=https://registry.npm.taobao.org
(3)安装vue
$ cnpm install vue
(4)全局安装vue-cli
· 成熟的vue项目架构设计
· 本地测试服务器
· 集成打包上线方案
lenovo@DESKTOP-NL309GS MINGW64 /e/workspace/xampp/htdocs/demo
$ cnpm install -g vue-cli 安装vue-cli
lenovo@DESKTOP-NL309GS MINGW64 /e/workspace/xampp/htdocs/demo
$ vue init webpack mall 初始化项目
? Project name (mall) mall
? Project name mall
? Project description (A Vue.js project) mall system
? Project description mall system
? Author snow-small
? Author snow-small
? Vue build standalone
? Install vue-router? (Y/n) Y
? Install vue-router? Yes
? Use ESLint to lint your code? (Y/n) n
? Use ESLint to lint your code? No
? Set up unit tests (Y/n) n
? Set up unit tests No
? Setup e2e tests with Nightwatch? (Y/n) n
? Setup e2e tests with Nightwatch? No
? Should we run `npm install` for you after the project has been created? (reco
? Should we run `npm install` for you after the project has been created? (reco
mmended) no
vue-cli · Generated "mall".
# Project initialization finished!
# ========================
To get started:
cd mall
npm install (or if using yarn: yarn)
npm run dev
Documentation can be found at https://vuejs-templates.github.io/webpack
(5)进入项目,安装依赖
lenovo@DESKTOP-NL309GS MINGW64 /e/workspace/xampp/htdocs/demo
$ cd ./mall
lenovo@DESKTOP-NL309GS MINGW64 /e/workspace/xampp/htdocs/demo/mall
$ cnpm install
(6)运行
lenovo@DESKTOP-NL309GS MINGW64 /e/workspace/xampp/htdocs/demo/mall
$ cnpm run dev 在localhost启动测试服务器
$ cnpm run build 生成上线目录(部署)
(7)成功显示
> mall@1.0.0 dev E:\workspace\xampp\htdocs\demo\mall
> webpack-dev-server --inline --progress --config build/webpack.dev.conf.js
95% emitting DONE Compiled successfully in 3970ms20:07:53
I Your application is running here: http://localhost:8080
4、基础语法
(1)模板语法:
· Mustache语法: {{ msg }}
· Html赋值:v-html = ""
· 绑定属性:v-bind:id = ""
· 使用表达式:{{ ok ? "YES", "NO"}}
· 文本赋值:v-text = ""
· 指令:v-if = ""
· 过滤器:{{ message | caputalize}}和v-bind:id = "rawId|formatId"
(2)Class和Style绑定
v-bind:可以省略成:
· 对象语法:v-bind:class = "{active:isActive, 'text-danger':hasError}"
isActive==true时,显示active
· 数组语法:
<div v-bind:class="activeClass, errorClass">
data: {
activeClass: active,
errorClass: text-danger
}
· style绑定对象语法:v-bind:style="{ color: activeColor, fontSie:fontSize + 'px'}"
<div :style="links"></div>
data: {
links: {
font-size: 12px,
color: #fff
}
}
(3)条件渲染:
· v-if
<a v-if="true"></a>
· v-else
<a v-if="true">aaa</a> if显示的时候,else不显示,
<a v-else>bbb</a>
· v-else-if
· v-show
<a v-show="true"></a> 区别是show是display=block
· v-clock 如果页面刷新太快,未加载出来的地方会同步隐藏相关的代码
(4)vue事件处理器
· v-on:click="greet"或@click="greet"
· v-on:click.stop v-on:click.stop.prevent v-on:click.self v-on:click.once
· v-on:keyup:enter/esc/tab
(5)实例对象
new Vue({
el: '#app', 挂载的对象
template: '<div>{{ fruit }}</div>', 使用的模板
data: {
fruit: 'apple' 绑定的数据
}
});
(6)组件
· 全局组件
<div id="app">
<my-header></my-header>
{{ test }}
</div>
<script type="text/javascript">
Vue.component('my-header', {
template: '<p>this is a my-header(全局组件)</p>'
});
new Vue({
el: '#app',
data: {
test: 'this is a apple'
}
});
</script>
· 局部组件
<div id="app">
<my-header></my-header>
{{ test }}
</div>
<script type="text/javascript">
var myHeader = {
template: '<p>this is a my-header(局部组件)</p>'
};
new Vue({
el: '#app',
data: {
test: 'this is a apple'
},
components: {
'my-header': myHeader
}
});
</script>
当组件名为驼峰时myHeaderAbCd,在<template>里使用的时候:vue1时,要写成<my-header-ab-cd></my-header-ab-cd>,大写要分开;在vue2时,可以写成<myHeaderAbCd></myHeaderAbCd>
· 组件之间的通信
父组件向子组件传递时
<comA number-to-do=11></comA> 父组件,属性大小写不敏感,要用-,值都是string
import comA from './components/a'
components: {
comA: comA
}
在./components/a中的实例选项中 子组件要得到父组件的属性,需要使用props,使用时要转成驼峰形式{{ numberToDo }}
props: ['number-to-do']
或props: {
'number-to-do': [Number, String] 传对象,支持数字、字符型
}
子组件向父组件传递,通过事件传递
在./components/a中
<button @click="emitMyEvent"></button>
methods: {
emitMyEvent () {
this.$emit('my-event', 'this is components a') 在子组件中触发事件,通过$emit触发父组件中的自定义事件,并传参数
}
}
在父组件中
<comA @my-event="getMyEvent"></comA> 父组件中自定义事件,大小写不敏感
methods: {
getMyEvent (params) { 参数值为子组件传来的值,== i get a event this is components a
console.log('i get a event' + params)
}
}
父组件向子组件传递模板
在父组件中
<comA>
<p>11111</p><span>2222</span>
</comA>
在子组件中
<slot></slot> 使用<slot></slot>来接收,父组件的模板 == <p>111</p><span>2222</span>
有具名的slot
子组件
<slot name="header">no header</slot> 有具体名称,值默认为no header
<slot name="footer">no footer</slot>
父组件
<comA>
<p slot="header">xxxx header</p> 使用slot="具体名称"来确认不同的slot
<p slot="footer">xxxx footer</p>
</comA>
(7)v-for使用
数组:
<div id="app">
<p v-for="item in list">{{ item.name }} - {{ item.price }}</p>
</div>
<script type="text/javascript">
new Vue({
el: '#app',
data: {
list: [
{
name: 'apple',
price: 23
},
{
name: 'banana',
price: 24
}
]
}
});
</script>
若是要有序号,在v-for="(item, index) in list",使用时{{ index }}从0开始的序号
对象:
<div id="app">
<p v-for="(value, key) in objList">{{ value }} - {{ key }}</p>
</div>
<script type="text/javascript">
new Vue({
el: '#app',
data: {
objList: {
name: 'apple',
price: 22,
weight: 20
}
}
});
</script>
列表更新:
methods: {
change() {
Vue.set(this.list, 1, { 第一项要改变的列表,第二项第几个数据,三为改变后的值
name: 'orange',
price: 20
})
}
}
(8)表单绑定
<input type="text" v-model="myValue">
<input type="checkbox" v-model="box" value="apple"> 复选框
<input type="checkbox" v-model="box" value="banana">
<input type="checkbox" v-model="box" value="orange">
{{ box }}
data: {
box: []
}
<input type="radio" v-model="box" value="apple"> 单选按钮
<input type="radio" v-model="box" value="banana">
<input type="radio" v-model="box" value="orange">
{{ box }}
<select v-model="section">
<option value="1">1</option>
<option value="2">2</option>
</select>
{{ section }}
data: {
section: null }
v-model.lazy:延迟
v-model.number:整形
v-model.trim:去空格
(9)计算属性
<div id="app">
<input type="text" v-model="myValue">
{{ inputWithoutNumber }}
</div>
<script type="text/javascript">
new Vue({
el: '#app',
data: {
myValue: '',
},
computed: {
inputWithoutNumber () {
return this.myValue.replace(/\d/g, ''); 去掉数字
}
}
});
</script>
(10)属性监听
<div id="app">
<input type="text" v-model="myValue">
</div>
<script type="text/javascript">
new Vue({
el: '#app',
data: {
myValue: '',
},
watch: {
myValue (newValue, oldValue) { 监听myValue
console.log(newValue, oldValue);
}
}
});
</script>
(11)css3过渡动画
<div id="app">
<button @click="show = !show">toggle</button>
<transition name="fade"> 通过transition,name随便取
<p v-show="show">i am show</p>
</transition>
</div>
<script type="text/javascript">
new Vue({
el: '#app',
data: {
show: true
}
});
</script>
<style type="text/css">
.fade-enter-active, .fade-leave-active { v-enter...中的v是上面的name
transition: opacity .5s;
}
.fade.enter, .fade-leave-active {
opacity: 0;
}
</style>
对于多元素动画,<transition mode="out-in">模式是先出后进,默认先进后出,
若多元素标签相同,如<p key="1">i am one</p> <p key="2">i am two</p>,实现一个进一个出,不加key区别的话,不会有动画
(12)js实现动画
<div id="app">
<button @click="show = !show">toggle</button>
<transition
@before-enter="beforeEnter"
@enter="enter"
@leave="leave"
:css="false" > 清除css的影响
<p class="animate-p" v-show="show">i am show</p>
</transition>
</div>
<script type="text/javascript">
new Vue({
el: '#app',
data: {
show: true
},
methods: {
beforeEnter (el) {
$(el).css({
left: '-500px',
opacity: 0
})
},
enter (el, done) {
$(el).animate({
left: 0,
opacity: 1
}, {
duration: 1500,
complete: done 一定要有done
})
},
leave (el, done) {
$(el).animate({
left: '500px',
opacity: 0
}, {
duration: 1500,
complete: done
})
}
}
});
</script>
<style type="text/css">
.animate-p {
position: absolute;
left: 0;
}
</style>
(13)自定义指令
<div id="app">
<p v-color="'red'">this is v-color</p> v-color是自定义指令
</div>
<script type="text/javascript">
new Vue({
el: '#app',
directives: { 定义
color (el, binding) { 当前的元素,绑定的值
el.style.color = binding.value
}
}
});
</script>