开发者学堂课程【高校精品课-上海交通大学 -互联网应用开发技术:Vue 2】学习笔记,与课程紧密联系,让用户快速学习知识。
课程地址:https://developer.aliyun.com/learning/course/76/detail/15749
Vue 2
内容介绍
一、Vue
二、答疑
一、Vue
下列代码特点为 style 与 class 可动态绑定
Object Syntax
<div
v-bind:style="{ color: activeColor, fontsize: fontsize +px'}”>
</div>
data:{
[activeColor: 'red',
fontsize: 30
}
<div v-bind:style="styleObject"></div>
data:{
styleObject:{
color: 'red',
fontsize:'13px'
}
}
v-if 根据 awesome 的值决定展示的是什么,条件展示。
v-if
<h1 v-if="awesome">Vue is awesome!</h1>
<h1 v-if="awesome">Vue is awesome!</h1>
<h1 v-else>oh no </h1>
如果值是 true 显示 Now you see me,false 显示 Now you don't
v-else
<div v-if="Math.random() > 0.5">
Now you see me
</div>
<div v-else>
Now you don't
</div>
多个 else-if 绑定,如果是A、B、C选择不同的值,否则显示 Not A/B/C
v-else-if
<div v-if="type === 'A'"> A </div>
<div v-else-if="type === 'B'"> B </div>
<div v-else-if="type === 'c'"> C </div>
<div v-else> Not A/B/C </div>
loginType 是否为 username,如果是显示 Username,输入 Enter your username,看到 Username Enter your username。
v-if 和 v-else 凑成一对,如果显示不是 Username,看到 Email Happen。
v-if 和 v-else 都是由 label 和 input 构成,可根据 loginType === 'username'表达式的值,呈现出不同的东西。不管怎样呈现,最终只有一个 label 和 input。
Controlling Resusable Elements with key
<template v-if="loginType === 'username'">
<label>Username</label>
<input placeholder="Enter your username"></template>
<template v-else>
<label>Email</label>
<input placeholder="Enter your email address">
</template>
loginType 是否为 username,如果是显示 Username。loginType在 data 里声明,输入 Username 的界面
<script>
var watchExampleVM = new Vue({
el:'#example',
data: {
loginType: 'username'
}
改掉 username 后,不等于 username,出现 Email。此类型里只能看到一个 label 和 input
v-show 按条件呈现,看结果看呈现的是什么。v-if 与 v-show 之间的差异,v-if 真的根据条件做判断,v-show 的值根据 ok 来做,没有真正的做判断。v-if 要确保事件监听器和子节点在条件表达式块里做切换时直接摧毁,切换显示时重新建设。v-show 不摧毁,对象一直在,前端看不见。用 v-if 最好不与 v-for 合起来用,自身问题,不推荐使用。
v-show
<h1 v-show="ok">Hello!</h1>
v-for 循环便利集合里的东西,呈现 li 的样子。传递给 data 里的parent Message Parent 部分,在每个 items 里复用。有若干条,Parent 部分被复用,后面显示索引和每一项加 message。
Mapping an Array to Elements with v-for
<ul id="example-1">
<li v-for="item in items">{{ item.message }}
</li>
</ul>
var example1=new Vue({
el:'#example-1',
data:{
parentMessage:’Parent’,
items:[
{ message: 'Foo'},
{ message: 'Bar'}
]
}
})
执行效果,Parent 消息被复用。Parent 在 v-for 循环里,但被复用。Parent 来自 parentMessage,不是来自 item 的东西。重复,内容一样,变化是后面 item.message。
v-for 给 object
如果 v-for 一次给 object,拿到 object 后,在 object 里取值、名字和索引。title、author、publishedAt 是名字,How to do lists in Vue、
Jane Doe、2016-04-10是值。对象里键值对里没有 object 层封装,data 里放 title、author、publishedAt,key 不一样,用 v-for 很难绘制出来。v-for 循环绘制出 title、author、publishedAt 封装到 obje
ct,取 object 的值、名字和 index,按照 index、name、value 方式呈现。
v-for with an Object
<ul id="example">
<li v-for= "(value, name, index) in object">
{{ index }} .{{ name }} : {{ value }}
</li>
</ul>
var example1 = new Vue({
el:'#example',
data:{
object:{
title: 'How to do lists in Vue',
author: 'Jane Doe',
publishedAt:'2016-04-10"
}
}
})
呈现效果,把 title、author、publishedAt 三个不同的键值对依次放到一个 list,用 v-for。没有 object 封装不容易用 v-for 画。
0.title:How to do lists in Vue
1.author:Jane Doe
2.publishedAt:2016-04-10
用 v-for 绘一个对象,对象里键值对看起来完全不同,键和值都不相同,用一个 v-for 绘制出来。
数组
数组操作,向里面追加东西,弹出东西等,reverse 逆转排序。
- push()
- pop()
- shift()
- unshift()
- splice()
- sort()
- reverse()
- Demo 4: app4.todos.push({text: 'Learn React'})
Demo 4里有三本书,如果要追加一本书。用脚本堆加元素,呈现第三本书,不能直接放,用一个方法放。
<script>
var app4 =new Vue({
el:'#app-4',
data:{
todos:[
{ text: 'Learn JavaScript'},
{ text: 'Learn Vue'},
{ text: 'Build something awesome' }
]
}
数组里的元素
可通过过滤的方式,产生想要的东西。告诉可以过滤的东西,给一个函数。函数是 filter 的一个标准, item 里的 message 匹配/Foo/形式。
example1.items = example1.items.filter(function (item) {
return item.message.match(/Foo/)
})
只有
item 的 text 是 Learn Vue,拿出来,符合要求,其它过滤。
-Demo4:
app4.todos = app4.todos.filter(function (item) {
return item.text.match('Learn Vue')
Vue漏洞
Vue 不能直接用索引设置item里的某一个等于新值,此写法写后在页面不能直接呈现。
vm.items[index0fItem] = newValue
在 React 里通过 SetState 实现,SetState 无论如何都触发页面重绘制动作。Vue 里没有执行 SetState 类似操作,修改值,自动刷界面。Vue 里对 length 做直接修改,vm.items.length = newLength
和 vm.items[index0fItem] = newValue 两种情况不做相应的修改,不是 reactive,随便改后,页面的值不发生变化,是数组类型以此方式修改带来的问题。
var vm =new Vue({
data:{
items: ['a', 'b', 'c'] }
})
vm.items[1] = 'x' // is NOT reactive
vm.items.length = 2 // is NOT reactive
Vue 定义 item 数组,里面有a,b,c。如果把b改为x,写脚本放入,不是 reactive。如果前端某一地方重现 reactive 的值a,b,c,经过vm.items[1] = 'x' // is NOT reactive代码执行后,值仍然是a,b,c。
Caveats
var vm = new Vue({
data:{
items: ['a', 'b', 'c'] }
})
vm.items[1] = 'x' // is NOT reactive
用 Vue 的 set 方法,Vue.set(vm.items, indexofItem, newValue),三个参数。集合类的某一位置东西替换为vm.items, indexofItem, newValue 值。在 React 里通过 SetState 实现,Vue 里不用显示写类似代码,在小地方没有解决。
// Vue.set
Vue.set(vm.items, indexofItem, newValue)
// Array.prototype.splice
vm.items.splice(index0fItem, 1, newValue)
// instance.set
vm.$set(vm.items, indexofItem, newValue)
长度设完后,不是 reactive,应该用 splice 设长度替换。
vm.items.length = 2 // is NOT reactive
vm.items.splice(newLength)
定义变量,用 Vue 构建。Vue 对象里的 data 等于1,直接定义,其它地方改变a的值,某个地方显示a的值,a值刷新为2。如果不放到 vm 的 data 里定义,直接在外面输 vm.b = 2,vm.b 不是reactive。如果要显示 vm.b,改为3,值不变,仍然是2。
var vm = new Vue({
data:{
a:1
}
}) // `vm.a` is now reactive
vm.b = 2 // `vm.b` is NOT reactive
Vue.set(vm.userProfile, 'age', 27)
vm.$set(vm.userProfile, 'age', 27)
Object.assign(vm.userProfile, {
age: 27,
favoriteColor: 'Vue Green’
})
vm.userProfile = 0bject.assign({},vm.userProfile,{
age: 27,
favoriteColor: 'Vue Green’
})
漏洞是 Vue 做一次封装,不像 React 明确调用 SetState。Vue 有些地方做不到,希望显示去做。Set 数组里的元素、splice 重新设长度,希望 Vue 搞不定的,人为搞,显示的通过代码搞。Vue 全部封装好,用非常简单。如果没封装好,比每次调用 SetState 方便。分不清哪些需要调用,哪些不需要调用,可能是个坑,写代码时可能碰到坑,回头看是否属于此类漏洞,没有被刷新。
显示集合时,可用筛选的方法显示。定义对象里有一个集合[ 1, 2, 3, 4, 5 ],v-for 显示列表时,只想显示集合中的偶数。偶数不需要直接存,是计算出的属性,每次访问时计算。Number 变,基本值变。拿 number 做过滤,过滤前提给一个过滤函数。对集合中元素进行操作,每个原词每次调用都赋给 number,看 number 除以2余数,是否等于0。如果等于0,在偶数的集合里。每次绘制时,把偶数拿出来显示,v-for 每次只显示一个数字。
<li v-for="n in evenNumbers">{{ n }}</li>
data:{
numbers: [ 1, 2, 3, 4, 5 ]
},
computed: {
evenNumbers:function(){
return this.numbers.filter(function (number) {
return number % 2 === 0
})
}
计算奇偶数时,number % 2=0,是一种方法。如果取所有奇数,用number % 2=1方法,非常危险。所有偶数% 2一定等于0,所有奇数% 2不一定等于1,有可能等于-1。取所有奇数,用return number % 2 === 0方法,取反,不是return number % 2 === 1。JS、C++、Java每种语言实现不同,约定可能是余数,余数必须和被除数同符号,负数除完,余数应该是1。
数据是二位数字,把数字分为前一半和后一半,取偶数。使用computed 函数,参数 numbers computed 属性,even 有函数参数,参数用 set 传递做过滤,可将偶数过滤。没有用 computed,使用 methods。Filter 对集合里的元素过滤,集合实际上只有两个元素,分别是一个数组。放入的 number 不确定,为解决此问题写两层循环,sets 里每次取出一个元素 set,取第一个或第二个元素,循环两次,取不同数组,每次取出的元素放入 set。不是二位数组,是一位数组,numbers 出来效果。v-for 可以嵌套使用,把一个二位数组拆开,做显示。
<ul v-for="set in sets">
<li v-for="n in even(set)">{{ n }}</li>
</ul>
data:{
sets:[[ 1, 2, 3, 4, 5 1,[6,7,8, 9,10]]},
methods:{
even:function(numbers){
return numbers.filter(function (number) {
return number % 2 === 0
})
}
v-for 控制可以 for each 循环,in 的目标不是对象或集合类,是具体的数字。默认情况,n在小于10的正整数范围所有的数字,小于10正整数范围内做处理。代码改为<div> <span v-for="n in 10">{{ n }} </span> </div>,依旧输出1-10的偶数。
<div> <span v-for="n in 10">{{ n }} </span> </div>
data:{
sets:[[ 1,2,3,4,5 ],[6,7,8,9,10]]
},
methods:{
even:function(numbers){
return numbers.filter(function (number) {
return number % 2 === 0
})
}
v-for 可以用 for each 方式便利对象中的内容,对象本身可以是定义的某个其它的构建。构建内容,div 中有一个按钮,增加一个新的待办项。v-on:submit 是按钮,组织默认的行为,调用 addNewTodo函数实现。显示 Add a todo 内容,输入框 v-model,输入新的待办是什么,用 newTodoText 绑定。写完后点 Add 按钮,整个 form被提交。Label 后跟一个输入框,输入框后跟一个按钮,按按钮,数据与 newTodoText 绑定。
Form 写完后在一个 div 里,显示:开头无序的列表,列表内容从v-for 画 todos 里的东西,显示 id、title。如果有 v-on 叫做 remove,把内容删掉。
<div id="todo-list-example">
<form v-on:submit.prevent="addNewTodo">
<label for="new-todo">Add a todo</label>
<input
v-model="newTodoText"
id="new-todo"
placeholder="E.g. Feed the cat"
<button>Add</button>
</form>
<ul>
<li
is="todo-item"
v-for="(todo, index) in todos"
v-bind:key="todo.id"
v-bind:title="todo.title"
v-on:remove="todos.splice(index, 1)" >
</li>
</ul>
</div>
下列代码说明 todo-item 是什么,template 里与 title 绑定,点击后,产生 remove 动作。
Vue.component('todo-item', {
template:'\
<li>\
{{ title }}\
<button v-on:click="$emit(\'remove\')">Remove</button>\
</li>\ ',
props: ['title']
})
整个 Vue 画 todo-list-example 页面,开始 newTodoText 插入东西为空,三个待办事项。如果插入下一个元素,一个变量记住,下一个元素的id是什么。addNewTodo 与前面 addNewTodo 绑定,调用 addNewTodo 在 todos 数组里,追加一个新元素 push。Id 当前可用的最后一个值4,引用4后++,先引用后+,值变为5。title是 newTodoText,一开始为空。前面输入框里填的内容与newTodoT
Ext 绑定,取输入框内的内容作为新的 title,整个 Vue 里没有SetSta
te,相当于 todos 值发生变化,状态发生变化,页面重绘,新的值被呈现,插入后 newTodoText 恢复为空。
new Vue({
el:'#todo-list-example’
data: {
newTodoText:‘ ’,
todos:[
{ id: 1, title: 'Do the dishes', },
{ id: 2, title: 'Take out the trash', }
{ id: 3, title: 'Mow the lawn'} ],
nextTodoId:4
},
methods:{
addNewTodo:function(){
this.todos.push({
id:this.nextTodoId++,
title:this.newTodoText
})
this.newTodoText=”
}
}
执行,输入吃饭,Add 后到最底下,上面内容被清空
Add a todo E.g. Feed the cat Add
Do the dishes Remove
Take out the trash Remove
Mow the lawn Remove
吃饭 Remove
Add 完后清空,状态发生变化,又重绘一次,与 input 绑定。值发生变化,变为空,值是占位符,本身的值为空。占位符的值是写入的,如果为空,显示占位值,用 v-for 和 Component 操作新生成 todo.t
itle。每个后面有一个 Remove,Remove 一下消失。画每个 li 时要id 和 title,当前条的 key 与 id 绑定,key 本身没有呈现。title 是 todo.title,remove 是当前索引,v-表示一个按钮,remove 是后面跟的按钮,按 remove 后触发一个 remove 动作。
Button 产生 remove 动作,remove 动作是 Vue 自动做的。
Remove 按钮是 Vue 的按钮,不是标本按钮,触发动作时激发一个remove 动作,Vue 帮助做。
整个 li 用构建画图时,v-for 里操作 todos 列表里的内容,列表内画出的东西在 todo-item 里,todo-item 显示内容和 remove、butt
on。
监听事件
Button 有一个点击动作,动作不调其它的东西,把 counter 做+1的操作。Counter 从 new Vue 里来,定义 Vue 时给一个 data,data 的 counter 是0。有 button 后每次显示1,每次点 counter值发生变化。按钮点了多少次与 counter 绑定,counter 发生变化,状态被重绘,重新显示内容。
<div id="example-1">
<button v-on:click="counter += 1">Add 1</button>
<p>The button above has been clicked {{ counter }} times.</p >
</div>
var example1 = new Vue({
el:'#example-1', data:{
counter: 0
}
})
Click 动作变复杂,写一个函数,函数可带参数。函数与 div 配起来的 Vue 实例里找对应的函数,say 函数有一个参数 message,弹出警告框,弹出值。点上面 say hi,点里面 say what。
<div id="example-3">
<button v-on:click="say('hi')">Say hi</button>
<button v-on:click="say('what')">Say what</button>
</div>
new Vue({
el:'#example-3',
methods:{
say:function(message){
alert(message)
}
}
})
点击后用 warn 方法,warn 方法有两个参数,一条信息和事件。点事件本身,点完按钮后有一些默认的行为。如果事件被触发,默认行为禁掉,弹一个对话框,对话框显示 message。Li把当时产生事件的现场带来,通过 event 可知 event 里的属性,用属性做进一步处理。
<button v-on:click=
"warn('Form cannot be submitted yet.', $event)">
Submit
</button>
methods:{
warn:function (message, event){
// now we have access to the native event
if(event){
event.preventDefault()
}
alert(message)
}
}
事件是 click、submit等,上面可带事件的修饰符.stop 点击事件不向下传播。点击 submit 应该把页面提交,刷新页面,告诉 prevent不做工作。click、submit 有自身的事件或属性,可标明事件应该如何处理,可通过修饰符告诉事件向下处理的链条应该怎样组装或截断,stop 属于截断,prevent 表示不调用出默认行为,重新加载出页面等。
<!-- the click event's propagation will be stopped-->
<av-on:click.stop="doThis"></ a>
<!-- the submit event will no longer reload the page-->
<form v-on:submit.prevent="onSubmit"></form>
<!-- modifiers can be chained-->
<a v-on:click.stop.prevent="doThat"></ a>
<!-- just the modifier-->
<form v-on:submit.prevent></form>
<!-- use capture mode when adding the event listener-->
<!-- i.e. an event targeting an inner element is handled here-->
<!-- before being handled by that element-->
<div v-on:click.capture="doThis">...</div>
按键修饰符,有键按下时抬起,键是回车键,要做什么。键按下,抬起,向下翻页键应该做什么。按键和事件的修饰符类似,指click在哪个目标执行。按键如果有按键弹起,键可做进一步修饰,限定在某一种事件响应。13是回车,按回车,做动作,否则不做。
<!-- only call`vm.submit()` when the`key` is`Enter`-->
<input v-on:keyup.enter="submit">
<input v-on:keyup.page-down="onPageDown">
Key Code
<input v-on:keyup.13="submit">
按ctrl、keyup键分别调用doSomething、clear函数。
<!-- Alt + C-->
<input v-on:keyup.alt.67="clear">
<!-- ctrl+Click-->
<div v-on:click.ctrl="doSomething">Do something</div>
输入 form 希望拿到用户的输入,用v-model和变量进行绑定,绑input 一行文本,textarea 多行文本。绑多行文本,将来输入值有很多行,包括回车。可绑 Checkbox,input 里不是文本框,是一个Checkbox 复选框,复选框的值与 checked 变量绑定,label 显示checked 的值 true 或 false。
Text
<input v-model="message" placeholder="edit me">
<p>Message is: {{ message }}</p >
Multiline text
<span>Multiline message is:</span>
<p style="white-space: pre-line;">{{ message }}</p >
<br>
<textarea v-model="message" placeholder="add multiple lines">
</textarea>
Checkbox
<input type="checkbox" id ="checkbox" v-model ="checked">
<label for ="checkbox">{{ checked }}</label>
例子中有若干个 checkbox,三项构成复选框的组合,分别与checked
Names 绑定,checkedNames 定义是一个数组,点击后被选中后进入数组。显示 name 时,显示所有被选中的名字。点一下,选中进去,再点从里面删除。三个复选框上做点击的动作,数组的值都会发生变化。数组值发生变化,checkedNames 的值重绘。选择时,显示被选中的东西。
<div id='example-3'>
<input type="checkbox" id="jack" value="Jack" v-model="checked
Names"><label for="iack">Jack</label>
<input type="checkbox" id="john" value="John"v-model="checked
Names"><label for="iohn">John</label>
<input type="checkbox" id="mike" value="Mike"v-model="checked
Names"><label for="mike">Mike</label>
<br>
<span>Checked names: {{ checkedNames }}</span>
</div>
new Vue({
el:'#example-3',
data:{
checkedNames:[]
}
})
Radio button 可绑定,Radio button 合起来一个意思。单选按钮只能选一个,一个值是 One,一个值是 Two,都与 picked 绑定。单选按钮选一个,显示 picked 的值,抓 One 或 Two。
<input type="radio" id="one" value="One" v-model="picked">
<label for="one">One</label>
<br>
<input type="radio" id="two" value="Two" v-model="picked">
<label for="two">Two</label>
<br>
<span>Picked: {{ picked }}</span>
选择框有A、B、C三个选项,选一个,选中的值与 selected 绑定,显示 selected,selected 值开始为空。选什么选项,selected 都是A、B、C中的某一个,一旦改变,重绘,可看到选中的结果。
<select v-model="selected">
<option disabled value="">Please select one</option>
<option>A</option>
<option>B</option>
<option>C</option>
</select>
<span>Selected: {{ selected }}</span>
new Vue({
el: '...',
data:{
selected:‘ ’
}
})
Single Select 是单选,Multiple Select 是多选。在 select 不做声明时,默认是单选,加 multiple 是多选。代码本身没有任何差异,可能选中多个值在 selected 显示。
<select v-model="selected"multiple
<option disabled value="">Please select one</option>
<option>A</option>
<option>B</option>
<option>C</option>
</select>
<span>Selected: {{ selected }}</span>
new Vue({
el: '...',
data:{
selected:‘ ’
}
})
选项本身是动态加载出的,selected 开始为A。Options 文本分别是One、Two、Three,值为A、B、C。用 v-for 绘制 options,对 options每个文本进行绘制。绑定值 option.value,显示是 One、Two、Three,选中对应的值是A、B、C,选中显示的结果是A、B、C之一。动态绑定的选项,显示的文本与最后的值不同。
<select v-model="selected">
<option v-for="option in options" v-bind:value="option.value">
{{ option.text }}
</option>
</select>
<span>Selected: {{ selected }}</span>
new Vue({
el:'...‘,
data:{
selected:'A'
options:[
{ text: 'One', value: 'A' },
{ text: 'Two', value: 'B' },
{ text: 'Three', value: 'c'} ]
}
})
例子
第一行选中为 true,不选为 false。第二行选多个,选不同的选项,下面值发生变化。One 和 Two两个能选中一个,下面是单选A、B、C。再下面多选,选中A,按CTRL再选。最下面选择值 One、Two、Three,选择后的值显示A、B、C。前端类型的输入大概为此类型,组装起来。
一些属性放到 option,用 select 或 input 展示,v-for 对 options的每个元素进行处理,显示内容。显示 selected,selected 初值显示再 selected,每次进行处理时,控件与 v-model selected 绑定在一起,每选中一个,select 值发生变化,代表 Vue 对象 selected值发生变化。变化触发 Vue 重绘页面,把 selected 内容替换。重绘页面 Vue 与 React 一样,不会把整个页面替换,替换页面发生变化的部分。Selected 被替换,前面的文本等不变。
<select v-model="selected">
<option v-for="option in options" v-bind:value="option.value">
{{ option.text }}
</option>
</select>
<span>Selected: {{ selected }}</span>
new Vue({
el:'...‘,
data:{
selected:'A'
options:[
{ text: 'One', value: 'A' },
{ text: 'Two', value: 'B' },
{ text: 'Three', value: 'c'} ]
}
})
前面展示的例子中,所有东西挂在一个页面,只改一个值,只重绘一个地方,其它不变。所有文本框、复选框、单选框都是此工作逻辑,显示内容是 data 里的一个条目,data 里的条目操作时修改值,值被修改,触发页面的重绘。React 只是名字,表示含义是对用户的动作有相应的响应,响应在前端完成。此角度 Vue 与 React 非常像,Vue 封装的更好。
值绑定用 v-model 的方式,checkbox、radio、select options 等等绑定。绑定的值是静态定义好后选择绑定。
<!-- `picked` is a string "a" when checked-->
<input type="radio" v-model="picked" value="a">
<!-- `toggle` is either true or false-->
<input type="checkbox" v-model="toggle">
<!--`selected` is a string "abc" when the first option is selected -->
<selectv-model="selected">
<option value="abc">ABC</option>
</select>
选项本身的值发生变化,动态绑定。绑的内容根据传来的数据,数据可以发生变化。
属性,修饰 v-model 的修饰符,比较复杂,lazy 发生变化后做修改
input 在里面输问题,如果没有 lazy 输入a、b、c,msg 不断发生变化。加入 lazy 后,不在输入时 msg 直接发生变化,一次性决定回车后改写值。好处是不用频繁修改 msg,修改触发其它的动作,判断问题是否是一个问题等。如果没有需求,输入一次判断一次,可用 lazy。
Number 在文本框内输入0123,本质上是一个文本,想要输入的数字,需要明确说清楚,是一个数字。
Trim 输入文本,中间打很多回车,输入abc,应该将前面回车和后面回车剔除,直接返abc。
lazy
<!-- synced after "change" instead of "input"-->
<input v-model.lazy="msg">
.number
<input v-model.number="age" type="number">
.trim
<input v-model.trim="msg">
创建构建像在 React 里创建 class,用 component 创建构建,当作 button 使用的名字 button-counter,可带数据和模板,button-c
ounter 是标签。声明渲染是按钮,做点击动作时 count做++,按钮显示内容是已经点过多少次。button-counter 引用控件,用控件显示创建一个 Vue 对象,创建到 components-demo。
做 new Vue({ el: '#components-demo'}),整个 Vue 图例里,整个文档有个根。
控件创建实例,按计数器按钮,+1.
<div id="components-demo">
<button-counter></button-counter>
</div>
<script>
// Define a new component called button-counter
Vue.component('button-counter', {
data: function(){
return {
count: 0
}
},
template: '<button v-on:click=" count++" >
You clicked me {{ count }} times.</button>'
})
new Vue({ el: '#components-demo'})
</script>
控件被复用,类实例出很多对象,可连续展示三个按钮,表示计数值,向上+。变为可复用的按钮,data 必须写成函数的形式,不能直接写data count= 0,必须写成函数的形式。做复用,必须做此设计。
Reusing Components
<div id=" components-demo">
<button-counter></button-counter>
<button-counter></button-counter>
<button-counter></button-counter>
</div>
data Must Be a Function
data:function(){
return {
count: 0
},
定义 blog-post 控件,有 props title,画出模板是h3,显示 title。三个属性,title 分别是 My journey with Vue、Blogging with Vue、Why Vue is so fun
创建 blog-post 实例与前面不同,前面创建后不做任何其它处理。创建后传 title 参数,看起来与 React 创建相同。
Passing Data to Child Components with Props
Vue.component('blog-post',{
props: ['title'],
template: '<h3>{{ title }}</h3>‘
})
<div id="blog-demo">
<blog-post title="My journey with Vue"></blog-post>
<blog-post title="Blogging with Vue"></blog-post>
<blog-post title="Why Vue is so fun"></blog-post>
</div>
new Vue({el:'#blogs-demo'})
上面三个标签看起来只是 title 不同,下面 blog-post 用 v-for 画。blog-post 对传递 posts 的每个 post 都执行模板的替换动作,dat
a 里 posts,把 Vue 控件与 blog-post-demo 关联,取 posts 的每个 post,画 blog-post。画时拿 post.title 绑定到 title,blog-post显示 title 时取到 post 一条条的 title,代码看起来更像面向对象的代码。
Vue.component('blog-post',{
props:['title'],
template: '<h3>{{ title }}</h3>'
})
<div id="blog-post-demo">
<blog-post
v-for="post in posts"
v-bind:key="post.id"
v-bind:title="post.title"
></blog-post></div>
new Vue({
el:'#blog-post-demo',
data:{
posts:[
{id: 1, title: 'My journey with Vue'},
{id: 2, title: 'Blogging with Vue'},
{id: 3, title: 'Why Vue is so fun'}
]
}
})
三条语句如下,一种是第一种方式,第二种按底下方式写。两种方式不同,效果相同。
My journey with Vue
Blogging with Vue
Why Vue is so fun
My journey with Vue
Blogging with Vue
Why Vue is so fun
My journey with Vue
Enlarge text
Blogging with Vue
Enlarge text
Why Vue is so fun
Enlarge text
Error! Something bad happened.
单根元素,每个控件必须有一个单一根。Div 是类,类里显示属性等。
<div class="blog-post">
<h3>{{ title }}</h3>
<div v-html="content"></div>
</div>
<blog-post // error-prone
v-for="post in posts"
v-bind:key="post.id"
v-bind:title="post.title"
v-bind:content="post.content"
v-bind:publishedAt="post.publishedAt" v-bind:comments="post.comments"
></blog-post>
页面剩下的部分,在 li 里每个 title 里有一个按钮 Enlarge text,点一下文本尺寸变大。
Post 里显示 title,有一个 Vue 的按钮,有一些预定义的方法,包括remove enlarge-text,把 div 文本扩大,超出范围不管。
Vue.component('blog-post-event', {
props: ['post'],
template:'
<div class="blog-post">
<h3>{{ post.title }}</h3>
<button v-on:click="$emit(\'enlarge-text\')">
Enlarge text
</button>
<div v-html="post.content"></div>
</div>’
})
初始尺寸,依次画三个数的内容。
<div id="blog-posts-events-demo">
<div :style="{ fontsize: postFontsize + 'em'}">
<blog-post-event
v-for="post in posts"
v-bind:key="post.id"
v-bind:post="post"
v-on:enlarge-text="postFontsize += 0.1'
></blog-post-event>
</div>
</div>
new Vue({
el:'#blog-posts-events-demo'
data:{
posts:[
{id: 1, title: 'My journey with Vue'},
{id: 2, title: 'Blogging with Vue'},
{id: 3, title: 'why Vue is so fun'},
],
postFontsize:1
}
})
触发动作时,有一个参数可控制每次可扩大多少,可带第二次参数。
Vue.component('blog-post-event', {
props: ['post'],
template:'
<div class="blog-post">
<h3>{{ post.title }}</h3>
<button v-on:click="$emit(\'enlarge-text\', 0.1)">
Enlarge text
</button>
<div v-html="post.content"></div>
</div>’})
拿 v-model 绑定 searchText,当前输入框与 searchText 进行绑定。不用 v-model,当前值与 searchText 绑定,有输入时 searchText等于当前正在产生输入动作事件的文本框里的值,用 v-model 更简单。不用 v-model,要用 v-bind 和 v-on 组合实现上面的逻辑。
<input v-model="searchText">
=>
<input
v-bind:value="searchText"
v-on:input="searchText = $event.target.value'
>
Vue.component('custom-input', {
props: ['value'],
template:`
<input
v-bind:value="value"
v-on:input="$emit('input', $event.target.value)" >
})
<custom-input y-model="searchText"></custom-input>
定义一个 alert-box,模板是有一个加粗的字 Error,Error 后显示Something bad happened.
alert-box 显示加粗的 Error,中间加的内容填到槽里。允许在compo
nent 里定义 slot 槽,给标签写东西留位置,插入。合起来是 Error!Something bad happened.
<alert-box> Something bad happened. </alert-box>
Vue.component('alert-box',{
template:`
<div class="demo-alert-box">
<strong>Error!</strong>
<slot></slot>
</div>`
})
掌握核心集与 React 做对比。每个项目单独安装一个 node_modul
es不再存在。
依赖很多包,不知道导入哪些包,把包做处理,用 webpack 做处理。只需告诉需要用哪个包。包再用到哪个包,自动帮助下载,一直找到所有依赖的B包,不再依赖外面其它包为止。
Webpack 主要两个文件,最主要是 webpack.config.js,写进所有的依赖。
Vue 例子,直接用现成的东西,Vue Table Dynamic 已经做好东西,只是在工程里用。
Vue 店里安装相应的插件,创建 Vue 工程。
插件升级,旧版本不能使用,需要卸载后装新版本。
Package.json 有些脚本,依赖关系。依赖关系在建 Vue 时帮助打入,比如 Vue 的东西。
框起来的要用 Vue Table Dynamic,idea 里直接输名字,输前面后面自动出现,可找匹配的。打三角符号出现版本,选择最新版本。版本本身比较早,0.1版本。如果自己有可直接下载打包到工程,自己安装写最下面代码
webpack 里所有的 index 都嵌入编译的 build.js
<!DOCTYPE html>
<html>
<head>
<meta charset"utf-8">
<meta content="width=device-widthinitial-scale=1,
user-scalableno"namem"viewport">
<link relm"shortcut icon" typemimage/x-icon href=favicon.png>
<title>Vue Table Dynamic</title>
</head>
<body>
<div id="app"></div>
<script src="/dist/build.js"></script>
</body>
</html>
Index.js 与 React 一样,创建 Vue 在页面 app 位置。单根元素,放一个写进的东西,剩下的在 app 里写东西。
import Vue from 'vue'
import App from './App.vue'
import'./assets/css/flex.css
// dev
// import VueTableDynamic from"../../src/index.js
// prod
import VueTableDynamic from 'vue-table-dynamic
Vue.use(VueTableDynamic)
Vue.config.productionTip=false
//eslint-disable-next-line no-new
new Vue({
el:'#app',
render:h => h(App)
})
代码有几个文件,Home 主页、侧边栏、按钮。
页面切换,Vue 里切换叫做 Vue Router 和 React Router 关系一样,与 Vue.js 是两个东西。
Vue Router 主页面有 Home、About、User,点击其中一个,下面又包含三个,来回切换。Vue Router 和 React Router 非常像
所有的前端框架,基本上设计原理都一样。构建化和声明式渲染,构建化让前端的代码变得更好维护,声明式渲染让代码响应用户的动作,根据用户的动作动态改变显示的内容。构建化和声明式渲染是核心思想,比较重要。要学习设计的思维,设计前端时要考虑界面如何构建化,识别构建,构建之间的组合关系。用 Vue 或 React 是具体的选择问题,思想相同。Vue 和 React 是两个最主流的框架,实现简单的数据浏览、搜索。
二、答疑
用的 js 开发的包,文件获取不是 webpack 完成的。包管器负责文件下载,放到列表里。Webpack 负责按照依赖文件打包到一起,文件获取是 ntl 等完成,后端可下载和打包,webpack 只有打包功能。不一定必须要 node_modules 去其它地方解析包,只要找到就可以。
文档如下
不用每次都安装 node_modules,直接使用软连接即可:
windows使用 mklink /inode_modules
%APPDATA%\Roaming\npmnode_modules
linux使用
Is -snode_modules %APPDATA%Roaming\npm\node_
modules
nodeis中packageison中的依赖必须每个项目都有自己的node_mo
Dules 文件夹,无法在多个项目之间共用一套 node_modules(像Java中的Maven)。
依赖管理是每个现代语言的标配。依赖管理和打包工具是两个概念,npm 是依赖管理,webpack 是打包工具。
在 Java 中,maven既能实现依赖管理又能实现打包。
依赖管理是构建一个有向无环图。项目A依赖项目B,项目B依赖项目C,项目依赖A时,依赖管理工具会自动让项目依赖B和C。
要想构建有向无环图,最关键的是要将项目转化为有向无环图中的结点。项目有 description,作者信息,版本信息等额外信息。
依赖管理最难解决的问题是版本问题。库A依赖库B,库C也依赖库B,库A和库C所依赖的库B不是同一版本,如果库B的两个版本不兼容是无解的问题。
下面Java,Python,Node三种语言中的依赖管理。
·Java 中的 Maven 仓库在开发者电脑上是全局的,所有项目的依赖都集中存放在本地仓库中。每个项目都有 pom.xml 指明依赖本地仓库中的哪些库。
·Python 中的 pip 跟 maven 很像,在开发者电脑上也是集中存放包,但是不存在版本问题。电脑上每个 python 库都只有一个版本。依赖某个库时,无需指明版本号,可直接引用包的名称。
Node 中的依赖不写 package.json,依赖的是全局的库;如果写package.json,会把所有依赖下载到 node_modules 文件夹。
前端用 webpack 很便利,自己找依赖很麻烦。