点我 button>
div>
1.6.1. 单选按钮
以下实例中演示了单选按钮的双向数据绑定:
Runoob
Google
选中值为: {{ picked }}
选中后,效果如下图所示
1.6.2. select 列表
以下实例中演示了下拉列表的双向数据绑定:
选择一个网站
Runoob
Google
选择的网站是: {{selected}}
选取 Runoob,如下所示:
1.6.3. 修饰符
1.6.3.1. .lazy
在默认情况下, v-model 在 input 事件中同步输入框的值与数据,但你可以添加一个修饰符 lazy ,从而转变为在 change 事件中同步:
1.6.3.2. .number
如果想自动将用户的输入值转为 Number 类型(如果原值的转换结果为 NaN 则返回原值),可以添加一个修饰符 number 给 v-model 来处理输入值:
这通常很有用,因为在 type=“number” 时 HTML 中输入的值也总是会返回字符串类型。
1.6.3.3. .trim
如果要自动过滤用户输入的首尾空格,可以添加 trim 修饰符到 v-model 上过滤输入:
1.6.4. Vue.js 组件
组件(Component)是 Vue.js 最强大的功能之一。
组件可以扩展 HTML 元素,封装可重用的代码。
组件系统让我们可以用独立可复用的小组件来构建大型应用,几乎任意类型的g](vue_res/(vue_res/面都可以抽象为一个组件树:
注册一个全局组件语法格式如下:
Vue.component(tagName, options)
tagName 为组件名,options 为配置选项。注册后,我们可以使用以下方式来调用组件:
1.6.4.1. 全局组件
所有实例都能用全局组件。
1.6.4.2. 局部组件
我们也可以在实例选项中注册局部组件,这样组件只能在这个实例中使用:
1.6.4.3. Prop
prop 是父组件用来传递数据的一个自定义属性。
父组件的数据需要通过 props 把数据传给子组件,子组件需要显式地用 props 选项声明 “prop”:
1.6.4.4. 动态 Prop
类似于用 v-bind 绑定 HTML 特性到一个表达式,也可以用 v-bind 动态绑定 props 的值到父组件的数据中。每当父组件的数据变化时,该变化也会传导给子组件:
以下实例中将 v-bind 指令将 todo 传到每一个重复的组件中:
注意: prop 是单向绑定的:当父组件的属性变化时,将传导给子组件,但是不会反过来。
1.6.4.5. Prop 验证
组件可以为 props 指定验证要求。
为了定制 prop 的验证方式,你可以为 props 中的值提供一个带有验证需求的对象,而不是一个字符串数组。例如:
Vue.component('my-component', {
props: {
// 基础的类型检查 (`null` 和 `undefined` 会通过任何类型验证)
propA: Number,
// 多个可能的类型
propB: [String, Number],
// 必填的字符串
propC: {
type: String,
required: true
},
// 带有默认值的数字
propD: {
type: Number,
default: 100
},
// 带有默认值的对象
propE: {
type: Object,
// 对象或数组默认值必须从一个工厂函数获取
default: function () {
return { message: 'hello' }
}
},
// 自定义验证函数
propF: {
validator: function (value) {
// 这个值必须匹配下列字符串中的一个
return ['success', 'warning', 'danger'].indexOf(value) !== -1
}
}
}
})
当 prop 验证失败的时候,(开发环境构建版本的) Vue 将会产生一个控制台的警告。
type 可以是下面原生构造器:
String
Number
Boolean
Array
Object
Date
Function
Symbol
type 也可以是一个自定义构造器,使用 instanceof 检测。
1.6.4.6. 自定义事件
父组件是使用 props 传递数据给子组件,但如果子组件要把数据传递回去,就需要使用自定义事件!
我们可以使用 v-on 绑定自定义事件, 每个 Vue 实例都实现了事件接口(Events interface),即:
使用 $on(eventName)
监听事件
使用 $emit(eventName)
触发事件
另外,父组件可以在使用子组件的地方直接用 v-on 来监听子组件触发的事件。
以下实例中子组件已经和它外部完全解耦了。它所做的只是触发一个父组件关心的内部事件。
如果你想在某个组件的根元素上监听一个原生事件。可以使用 .native 修饰 v-on 。例如:
data 必须是一个函数
上面例子中,可以看到 button-counter 组件中的 data 不是一个对象,而是一个函数:
data: function () {
return {
count: 0
}
}
这样的好处就是每个实例可以维护一份被返回对象的独立的拷贝,如果 data 是一个对象则会影响到其他实例,如下所示:
1.6.5. Vue.js 自定义指令
除了默认设置的核心指令( v-model 和 v-show ), Vue 也允许注册自定义指令。
下面我们注册一个全局指令 v-focus, 该指令的功能是在页面加载时,元素获得焦点:
我们也可以在实例使用 directives 选项来注册局部指令,这样指令只能在这个实例中使用:
1.6.6. 钩子
1.6.6.1. 钩子函数
指令定义函数提供了几个钩子函数(可选):
bind
: 只调用一次,指令第一次绑定到元素时调用,用这个钩子函数可以定义一个在绑定时执行一次的初始化动作。
inserted
: 被绑定元素插入父节点时调用(父节点存在即可调用,不必存在于 document 中)。
update
: 被绑定元素所在的模板更新时调用,而不论绑定值是否变化。通过比较更新前后的绑定值,可以忽略不必要的模板更新(详细的钩子函数参数见下)。
componentUpdated
: 被绑定元素所在模板完成一次更新周期时调用。
unbind
: 只调用一次, 指令与元素解绑时调用。
1.6.6.2. 钩子函数参数
钩子函数的参数有:
有时候我们不需要其他钩子函数,我们可以简写函数,如下格式:
Vue.directive('runoob', function (el, binding) {
// 设置指令的背景颜色
el.style.backgroundColor = binding.value.color
})
指令函数可接受所有合法的 JavaScript 表达式,以下实例传入了 JavaScript 对象:
1.6.7. Vue.js 路由
Vue.js 路由允许我们通过不同的 URL 访问不同的内容。
通过 Vue.js 可以实现多视图的单页Web应用(single page web application,SPA)。
Vue.js 路由需要载入 vue-router 库
中文文档地址:vue-router文档。
1.6.7.1. 安装
1.6.7.1.1. 1、直接下载 / CDN
https://unpkg.com/vue-router/dist/vue-router.js
1.6.7.1.2. NPM
推荐使用淘宝镜像:
cnpm install vue-router
1.6.7.2. 简单实例
Vue.js + vue-router 可以很简单的实现单页应用。
是一个组件,该组件用于设置一个导航链接,切换不同 HTML 内容。 to 属性为目标地址, 即要显示的内容。
以下实例中我们将 vue-router 加进来,然后配置组件和路由映射,再告诉 vue-router 在哪里渲染它们。代码如下所示:
< script src = " https://unpkg.com/vue/dist/vue.js" > script>
< script src = " https://unpkg.com/vue-router/dist/vue-router.js" > script>
< div id = " app" >
< h1> Hello App! h1>
< p>
< router-link to = " /foo" > Go to Foo router-link>
< router-link to = " /bar" > Go to Bar router-link>
p>
< router-view> router-view>
div>
const Foo = { template: 'foo
' }
const Bar = { template: 'bar
' }
const routes = [
{ path: '/foo' , component: Foo } ,
{ path: '/bar' , component: Bar }
]
const router = new VueRouter ( {
routes
} )
const app = new Vue ( {
router
} ) . $mount ( '#app' )
点击过的导航链接都会加上样式 class =“router-link-exact-active router-link-active” 。
1.6.7.3. 相关属性
接下来我们可以了解下更多关于 的属性。
1.6.7.3.1. to
表示目标路由的链接。 当被点击后,内部会立刻把 to 的值传到 router.push(),所以这个值可以是一个字符串或者是描述目标位置的对象。
Home
Home
Home
Home
Home
User
Register
1.6.7.3.2. replace
设置 replace 属性的话,当点击时,会调用 router.replace() 而不是 router.push(),导航后不会留下 history 记录。
1.6.7.3.3. append
设置 append 属性后,则在当前 (相对) 路径前添加基路径。例如,我们从 /a 导航到一个相对路径 b,如果没有配置 append,则路径为 /b,如果配了,则为 /a/b
1.6.7.3.4. tag
有时候想要
渲染成某种标签,例如
。 于是我们使用 tag
prop 类指定何种标签,同样它还是会监听点击,触发导航。
foo
foo
1.6.7.3.5. active-class
设置 链接激活时使用的 CSS 类名。可以通过以下代码来替代。
Router Link 1
Router Link 2
注意这里 class 使用 active_class="_active" 。
1.6.7.3.6. exact-active-class
配置当链接被精确匹配的时候应该激活的 class。可以通过以下代码来替代。
Router Link 1
Router Link 2
1.6.7.3.7. event
声明可以用来触发导航的事件。可以是一个字符串或是一个包含字符串的数组。
Router Link 1
以上代码设置了 event 为 mouseover ,及在鼠标移动到 Router Link 1 上时导航的 HTML 内容会发生改变。
1.6.7.4. NPM 路由实例
接下来我们演示了一个使用 npm 简单的路由实例,开始前,请先下载该实例源代码:
路由实例
你也可以在 Github 上下载:https://github.com/chrisvfritz/vue-2.0-simple-routing-example
下载完后,解压该目录,重命名目录为 vue-demo,vu 并进入该目录,执行以下命令:
# 安装依赖,使用淘宝资源命令 cnpm
cnpm install
# 启动应用,地址为 localhost:8080
cnpm run dev
如果你需要发布到正式环境可以执行以下命令:
cnpm run build
执行成功后,访g](vue_res/ttp://localhost:8080 即可看到如下界面:
1.6.8. Vue.js Ajax(axios)
1.6.8.1. test
Vue.js 2.0 版本推荐使用 axios 来完成 ajax 请求。
Axios 是一个基于 Promise 的 HTTP 库,可以用在浏览器和 node.js 中。
Github开源地址: https://github.com/axios/axios
1.6.8.1.1. 安装方法
使用 cdn:
或
使用 npm:
$ npm install axios
使用 bower:
$ bower install axios
使用 yarn:
$ yarn add axios
1.6.8.1.2. GET 方法
我们可以简单的读取 JSON 数据:
new Vue({
el: '#app',
data () {
return {
info: null
}
},
mounted () {
axios
.get('https://www.runoob.com/try/ajax/json_demo.json')
.then(response => (this.info = response))
.catch(function (error) { // 请求失败处理
console.log(error);
});
}
})
使用 response.data 读取 JSON 数据:
GET 方法传递参数格式如下:
// 直接在 URL 上添加参数 ID=12345
axios.get('/user?ID=12345')
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
// 也可以通过 parmas 设置参数:
axios.get('/user', {
params: {
ID: 12345
}
})
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
1.6.8.1.3. POST 方法
new Vue({
el: '#app',
data () {
return {
info: null
}
},
mounted () {
axios
.post('https://www.runoob.com/try/ajax/json_demo.json')
.then(response => (this.info = response))
.catch(function (error) { // 请求失败处理
console.log(error);
});
}
})
POST 方法传递参数格式如下:
axios.post('/user', {
firstName: 'Fred', // 参数 firstName
lastName: 'Flintstone' // 参数 lastName
})
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
1.6.8.1.4. 执行多个并发请求
function getUserAccount() {
return axios.get('/user/12345');
}
function getUserPermissions() {
return axios.get('/user/12345/permissions');
}
axios.all([getUserAccount(), getUserPermissions()])
.then(axios.spread(function (acct, perms) {
// 两个请求现在都执行完成
}));
1.6.8.1.5. axios API
可以通过向 axios 传递相关配置来创建请求。
axios(config)
// 发送 POST 请求
axios({
method: 'post',
url: '/user/12345',
data: {
firstName: 'Fred',
lastName: 'Flintstone'
}
});
// GET 请求远程图片
axios({
method:'get',
url:'http://bit.ly/2mTM3nY',
responseType:'stream'
})
.then(function(response) {
response.data.pipe(fs.createWriteStream('ada_lovelace.jpg'))
});
axios(url[, config])
// 发送 GET 请求(默认的方法)
axios('/user/12345');
1.6.8.1.6. 请求方法的别名
为方便使用,官方为所有支持的请求方法提供了别名,可以直接使用别名来发起请求:
axios.request(config)
axios.get(url[, config])
axios.delete(url[, config])
axios.head(url[, config])
axios.post(url[, data[, config]])
axios.put(url[, data[, config]])
axios.patch(url[, data[, config]])
**注意:**在使用别名方法时, url、method、data 这些属性都不必在配置中指定。
1.6.8.1.7. 并发
处理并发请求的助手函数:
axios.all(iterable)
axios.spread(callback)
1.6.8.1.8. 创建实例
可以使用自定义配置新建一个 axios 实例:
axios.create([config])
const instance = axios.create({
baseURL: 'https://some-domain.com/api/',
timeout: 1000,
headers: {'X-Custom-Header': 'foobar'}
});
1.6.8.1.9. 实例方法
以下是可用的实例方法。指定的配置将与实例的配置合并:
axios#request(config)
axios#get(url[, config])
axios#delete(url[, config])
axios#head(url[, config])
axios#post(url[, data[, config]])
axios#put(url[, data[, config]])
axios#patch(url[, data[, config]])
1.6.8.1.10. 请求配置项
下面是创建请求时可用的配置选项,注意只有 url 是必需的。如果没有指定 method,请求将默认使用 get 方法。
{
// `url` 是用于请求的服务器 URL
url: "/user",
// `method` 是创建请求时使用的方法
method: "get", // 默认是 get
// `baseURL` 将自动加在 `url` 前面,除非 `url` 是一个绝对 URL。
// 它可以通过设置一个 `baseURL` 便于为 axios 实例的方法传递相对 URL
baseURL: "https://some-domain.com/api/",
// `transformRequest` 允许在向服务器发送前,修改请求数据
// 只能用在 "PUT", "POST" 和 "PATCH" 这几个请求方法
// 后面数组中的函数必须返回一个字符串,或 ArrayBuffer,或 Stream
transformRequest: [function (data) {
// 对 data 进行任意转换处理
return data;
}],
// `transformResponse` 在传递给 then/catch 前,允许修改响应数据
transformResponse: [function (data) {
// 对 data 进行任意转换处理
return data;
}],
// `headers` 是即将被发送的自定义请求头
headers: {"X-Requested-With": "XMLHttpRequest"},
// `params` 是即将与请求一起发送的 URL 参数
// 必须是一个无格式对象(plain object)或 URLSearchParams 对象
params: {
ID: 12345
},
// `paramsSerializer` 是一个负责 `params` 序列化的函数
// (e.g. https://www.npmjs.com/package/qs, http://api.jquery.com/jquery.param/)
paramsSerializer: function(params) {
return Qs.stringify(params, {arrayFormat: "brackets"})
},
// `data` 是作为请求主体被发送的数据
// 只适用于这些请求方法 "PUT", "POST", 和 "PATCH"
// 在没有设置 `transformRequest` 时,必须是以下类型之一:
// - string, plain object, ArrayBuffer, ArrayBufferView, URLSearchParams
// - 浏览器专属:FormData, File, Blob
// - Node 专属: Stream
data: {
firstName: "Fred"
},
// `timeout` 指定请求超时的毫秒数(0 表示无超时时间)
// 如果请求话费了超过 `timeout` 的时间,请求将被中断
timeout: 1000,
// `withCredentials` 表示跨域请求时是否需要使用凭证
withCredentials: false, // 默认的
// `adapter` 允许自定义处理请求,以使测试更轻松
// 返回一个 promise 并应用一个有效的响应 (查阅 [response docs](#response-api)).
adapter: function (config) {
/* ... */
},
// `auth` 表示应该使用 HTTP 基础验证,并提供凭据
// 这将设置一个 `Authorization` 头,覆写掉现有的任意使用 `headers` 设置的自定义 `Authorization`头
auth: {
username: "janedoe",
password: "s00pers3cret"
},
// `responseType` 表示服务器响应的数据类型,可以是 "arraybuffer", "blob", "document", "json", "text", "stream"
responseType: "json", // 默认的
// `xsrfCookieName` 是用作 xsrf token 的值的cookie的名称
xsrfCookieName: "XSRF-TOKEN", // default
// `xsrfHeaderName` 是承载 xsrf token 的值的 HTTP 头的名称
xsrfHeaderName: "X-XSRF-TOKEN", // 默认的
// `onUploadProgress` 允许为上传处理进度事件
onUploadProgress: function (progressEvent) {
// 对原生进度事件的处理
},
// `onDownloadProgress` 允许为下载处理进度事件
onDownloadProgress: function (progressEvent) {
// 对原生进度事件的处理
},
// `maxContentLength` 定义允许的响应内容的最大尺寸
maxContentLength: 2000,
// `validateStatus` 定义对于给定的HTTP 响应状态码是 resolve 或 reject promise 。如果 `validateStatus` 返回 `true` (或者设置为 `null` 或 `undefined`),promise 将被 resolve; 否则,promise 将被 rejecte
validateStatus: function (status) {
return status >= 200 && status < 300; // 默认的
},
// `maxRedirects` 定义在 node.js 中 follow 的最大重定向数目
// 如果设置为0,将不会 follow 任何重定向
maxRedirects: 5, // 默认的
// `httpAgent` 和 `httpsAgent` 分别在 node.js 中用于定义在执行 http 和 https 时使用的自定义代理。允许像这样配置选项:
// `keepAlive` 默认没有启用
httpAgent: new http.Agent({ keepAlive: true }),
httpsAgent: new https.Agent({ keepAlive: true }),
// "proxy" 定义代理服务器的主机名称和端口
// `auth` 表示 HTTP 基础验证应当用于连接代理,并提供凭据
// 这将会设置一个 `Proxy-Authorization` 头,覆写掉已有的通过使用 `header` 设置的自定义 `Proxy-Authorization` 头。
proxy: {
host: "127.0.0.1",
port: 9000,
auth: : {
username: "mikeymike",
password: "rapunz3l"
}
},
// `cancelToken` 指定用于取消请求的 cancel token
// (查看后面的 Cancellation 这节了解更多)
cancelToken: new CancelToken(function (cancel) {
})
}
1.6.8.1.11. 响应结构
axios请求的响应包含以下信息:
{
// `data` 由服务器提供的响应
data: {},
// `status` HTTP 状态码
status: 200,
// `statusText` 来自服务器响应的 HTTP 状态信息
statusText: "OK",
// `headers` 服务器响应的头
headers: {},
// `config` 是为请求提供的配置信息
config: {}
}
使用 then 时,会接收下面这样的响应:
axios.get("/user/12345")
.then(function(response) {
console.log(response.data);
console.log(response.status);
console.log(response.statusText);
console.log(response.headers);
console.log(response.config);
});
在使用 catch
时,或传递 rejection callback 作为 then
的第二个参数时,响应可以通过 error
对象可被使用。
1.6.8.1.12. 配置的默认值
你可以指定将被用在各个请求的配置默认值。
全局的 axios 默认值:
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';
自定义实例默认值:
// 创建实例时设置配置的默认值
var instance = axios.create({
baseURL: 'https://api.example.com'
});
// 在实例已创建后修改默认值
instance.defaults.headers.common['Authorization'] = AUTH_TOKEN;
1.6.8.1.13. 配置的优先顺序
配置会以一个优先顺序进行合并。这个顺序是:在 lib/defaults.js 找到的库的默认值,然后是实例的 defaults 属性,最后是请求的 config 参数。后者将优先于前者。这里是一个例子:
// 使用由库提供的配置的默认值来创建实例
// 此时超时配置的默认值是 `0`
var instance = axios.create();
// 覆写库的超时默认值
// 现在,在超时前,所有请求都会等待 2.5 秒
instance.defaults.timeout = 2500;
// 为已知需要花费很长时间的请求覆写超时设置
instance.get('/longRequest', {
timeout: 5000
});
1.6.8.1.14. 拦截器
在请求或响应被 then 或 catch 处理前拦截它们。
// 添加请求拦截器
axios.interceptors.request.use(function (config) {
// 在发送请求之前做些什么
return config;
}, function (error) {
// 对请求错误做些什么
return Promise.reject(error);
});
// 添加响应拦截器
axios.interceptors.response.use(function (response) {
// 对响应数据做点什么
return response;
}, function (error) {
// 对响应错误做点什么
return Promise.reject(error);
});
如果你想在稍后移除拦截器,可以这样:
var myInterceptor = axios.interceptors.request.use(function () {/*...*/});
axios.interceptors.request.eject(myInterceptor);
可以为自定义 axios 实例添加拦截器。
var instance = axios.create();
instance.interceptors.request.use(function () {/*...*/});
错误处理:
axios.get('/user/12345')
.catch(function (error) {
if (error.response) {
// 请求已发出,但服务器响应的状态码不在 2xx 范围内
console.log(error.response.data);
console.log(error.response.status);
console.log(error.response.headers);
} else {
// Something happened in setting up the request that triggered an Error
console.log('Error', error.message);
}
console.log(error.config);
});
可以使用 validateStatus 配置选项定义一个自定义 HTTP 状态码的错误范围。
axios.get('/user/12345', {
validateStatus: function (status) {
return status < 500; // 状态码在大于或等于500时才会 reject
}
})
1.6.8.1.15. 取消
使用 cancel token 取消请求。
Axios 的 cancel token API 基于cancelable promises proposal
可以使用 CancelToken.source 工厂方法创建 cancel token,像这样:
var CancelToken = axios.CancelToken;
var source = CancelToken.source();
axios.get('/user/12345', {
cancelToken: source.token
}).catch(function(thrown) {
if (axios.isCancel(thrown)) {
console.log('Request canceled', thrown.message);
} else {
// 处理错误
}
});
// 取消请求(message 参数是可选的)
source.cancel('Operation canceled by the user.');
还可以通过传递一个 executor 函数到 CancelToken 的构造函数来创建 cancel token:
var CancelToken = axios.CancelToken;
var cancel;
axios.get('/user/12345', {
cancelToken: new CancelToken(function executor(c) {
// executor 函数接收一个 cancel 函数作为参数
cancel = c;
})
});
// 取消请求
cancel();
注意 :可以使用同一个 cancel token 取消多个请求。
1.6.8.1.16. 请求时使用 application/x-www-form-urlencoded
axios 会默认序列化 JavaScript 对象为 JSON。 如果想使用 application/x-www-form-urlencoded 格式,你可以使用下面的配置。
浏览器
在浏览器环境,你可以使用 URLSearchParams API:
const params = new URLSearchParams();
params.append('param1', 'value1');
params.append('param2', 'value2');
axios.post('/foo', params);
URLSearchParams 不是所有的浏览器均支持。
除此之外,你可以使用 qs 库来编码数据:
const qs = require('qs');
axios.post('/foo', qs.stringify({ 'bar': 123 }));
// Or in another way (ES6),
import qs from 'qs';
const data = { 'bar': 123 };
const options = {
method: 'POST',
headers: { 'content-type': 'application/x-www-form-urlencoded' },
data: qs.stringify(data),
url,
};
axios(options);
1.6.8.1.17. Node.js 环境
在 node.js里, 可以使用 querystring 模块:
const querystring = require('querystring');
axios.post('http://something.com/', querystring.stringify({ foo: 'bar' }));
当然,同浏览器一样,你还可以使用 qs 库。
1.6.8.1.17.1. Promises
axios 依赖原生的 ES6 Promise 实现而被支持。
如果你的环境不支持 ES6 Promise,你可以使用 polyfill。
1.6.8.1.17.2. TypeScript支持
axios 包含 TypeScript 的定义。
import axios from "axios";
axios.get("/user?ID=12345");
1.6.9. Vue.js Ajax(vue-resource)
Vue 要实现异步加载需要使用到 vue-resource 库。
Vue.js 2.0 版本推荐使用 axios 来完成 ajax 请求。
1.6.9.1. Get 请求
以下是一个简单的 Get 请求实例,请求地址是一个简单的 txt 文本:
1.6.9.1.1. 实例
window.onload = function(){ var vm = new Vue({ el:’#box’, data:{ msg:‘Hello World!’, }, methods:{ get:function(){ //发送get请求 this.$http.get(’/try/ajax/ajax_info.txt’).then(function(res){ document.write(res.body); },function(){ console.log(‘请求失败处理’); }); } } }); }
尝试一下 »
如果需要传递数据,可以使用 this.$http.get(‘get.php’,{params : jsonData}) 格式,第二个参数 jsonData 就是传到后端的数据。
this.$http.get('get.php',{params : {a:1,b:2}}).then(function(res){
document.write(res.body);
},function(res){
console.log(res.status);
});
1.6.9.2. post 请求
post 发送数据到后端,需要第三个参数 {emulateJSON:true} 。
emulateJSON 的作用: 如果Web服务器无法处理编码为 application/json 的请求,你可以启用 emulateJSON 选项。
1.6.9.2.1. 实例
window.onload = function(){ var vm = new Vue({ el:’#box’, data:{ msg:‘Hello World!’, }, methods:{ post:function(){ //发送 post 请求 this.$http.post(’/try/ajax/demo_test_post.php’,{name:“菜鸟教程”,url:“http://www.runoob.com”},{emulateJSON:true}).then(function(res){ document.write(res.body); },function(res){ console.log(res.status); }); } } }); }
尝试一下 »
demo_test_post.php 代码如下:
1.6.9.3. 语法 & API
你可以使用全局对象方式 Vue.http 或者在一个 Vue 实例的内部使用 this.$http来发起 HTTP 请求。
// 基于全局Vue对象使用http
Vue.http.get('/someUrl', [options]).then(successCallback, errorCallback);
Vue.http.post('/someUrl', [body], [options]).then(successCallback, errorCallback);
// 在一个Vue实例内使用$http
this.$http.get('/someUrl', [options]).then(successCallback, errorCallback);
this.$http.post('/someUrl', [body], [options]).then(successCallback, errorCallback);
vue-resource 提供了 7 种请求 API(REST 风格):
get(url, [options])
head(url, [options])
delete(url, [options])
jsonp(url, [options])
post(url, [body], [options])
put(url, [body], [options])
patch(url, [body], [options])
除了 jsonp 以外,另外 6 种的 API 名称是标准的 HTTP 方法。
options 参数说明:
参数
类型
描述
url
string
请求的目标URL
body
Object
, FormData
, string
作为请求体发送的数据
headers
Object
作为请求头部发送的头部对象
params
Object
作为URL参数的参数对象
method
string
HTTP方法 (例如GET,POST,…)
timeout
number
请求超时(单位:毫秒) (0
表示永不超时)
before
function(request)
在请求发送之前修改请求的回调函数
progress
function(event)
用于处理上传进度的回调函数 ProgressEvent
credentials
boolean
是否需要出示用于跨站点请求的凭据
emulateHTTP
boolean
是否需要通过设置X-HTTP-Method-Override
头部并且以传统POST方式发送PUT,PATCH和DELETE请求。
emulateJSON
boolean
设置请求体的类型为application/x-www-form-urlencoded
通过如下属性和方法处理一个请求获取到的响应对象:
属性
类型
描述
url
string
响应的 URL 源
body
Object
, Blob
, string
响应体数据
headers
Header
请求头部对象
ok
boolean
当 HTTP 响应码为 200 到 299 之间的数值时该值为 true
status
number
HTTP 响应码
statusText
string
HTTP 响应状态
方法
类型
描述
text()
约定值
以字符串方式返回响应体
json()
约定值
以格式化后的 json 对象方式返回响应体
blob()
约定值
以二进制 Blob 对象方式返回响应体
1.6.10. Vue.js 响应接口
Vue 可以添加数据动态响应接口。
例如以下实例,我们通过使用 w a t c h 属 性 来 实 现 数 据 的 监 听 , watch 属性来实现数据的监听, w a t c h 属 性 来 实 现 数 据 的 监 听 , watch 必须添加在 Vue 实例之外才能实现正确的响应。
实例中通过点击按钮计数器会加 1。setTimeout 设置 10 秒后计算器的值加上 20 。
1.6.10.1. 实例
尝试一下 »
Vue 不允许在已经创建的实例上动态添加新的根级响应式属性。
Vue 不能检测到对象属性的添加或删除,最好的方式就是在初始化实例前声明根级响应式属性,哪怕只是一个空值。
如果我们需要在运行过程中实现属性的添加或删除,则可以使用全局 Vue,Vue.set 和 Vue.delete 方法。
1.6.10.2. Vue.set
Vue.set 方法用于设置对象的属性,它可以解决 Vue 无法检测添加属性的限制,语法格式如下:
Vue.set( target, key, value )
参数说明:
target: 可以是对象或数组
key : 可以是字符串或数字
value: 可以是任何类型
1.6.10.3. 实例
计数器: {{ products.id }}
点我
在以上实例中,使用以下代码在开始时创建了一个变量 myproduct:
var myproduct = {"id":1, name:"book", "price":"20.00"};
该变量在赋值给了 Vue 实例的 data 对象:
var vm = new Vue({ el: '#app', data: { counter: 1, products: myproduct } });
如果我们想给 myproduct 数组添加一个或多个属性,我们可以在 Vue 实例创建后使用以下代码:
查看控制台输出:
如上图看到的,在产品中添加了数量属性 qty,但是 get/set 方法只可用于 id,name 和 price 属性,却不能在 qty 属性中使用。
我们不能通过添加 Vue 对象来实现响应。 Vue 主要在开始时创建所有属性。 如果我们要实现这个功能,可以通过 Vue.set 来实现:
1.6.10.4. 实例
计数器: {{ products.id }}
点我
从控制台输出的结果可以看出 get/set 方法可用于qty 属性。
1.6.10.5. Vue.delete
Vue.delete 用于删除动态添加的属性 语法格式:
Vue.delete( target, key )
参数说明:
target: 可以是对象或数组
key : 可以是字符串或数字
1.6.10.6. 实例
计数器: {{ products.id }}
点我
#### 编辑文本实例
##### 文本编辑
点击指定文本编辑内容:
#### 订单列表实例
##### 订单列表
创建一个订单列表,并计算总价:
Services
{{service.name}} {{service.price | currency}}
Total: {{total() | currency}}
// 自定义过滤器 “currency”. Vue.filter(‘currency’, function (value) { return ‘$’ + value.toFixed(2); });
var demo = new Vue({ el: ‘#main’, data: { // 定义模型属性 the model properties. The view will loop // 视图将循环输出数组的数据 services: [ { name: ‘Web Development’, price: 300, active:true },{ name: ‘Design’, price: 400, active:false },{ name: ‘Integration’, price: 250, active:false },{ name: ‘Training’, price: 220, active:false } ] }, methods: { toggleActive: function(s){ s.active = !s.active; }, total: function(){
var total = 0;
this.services.forEach(function(s){
if (s.active){
total+= s.price;
}
});
return total;
}
}
});
#### 搜索页面实例
##### 搜索页面
在输入框输入搜索内容,列表显示配置的列表:
{{article.title}}
var demo = new Vue({ el: ‘#main’, data: { searchString: “”,
// 数据模型,实际环境你可以根据 Ajax 来获取
articles: [
{
"title": "What You Need To Know About CSS Variables",
"url": "https://www.runoob.com/css/css-tutorial.html",
"image": "https://static.runoob.com/images/icon/css.png"
},
{
"title": "Freebie: 4 Great Looking Pricing Tables",
"url": "https://www.runoob.com/html/html-tutorial.html",
"image": "https://static.runoob.com/images/icon/html.png"
},
{
"title": "20 Interesting JavaScript and CSS Libraries for February 2016",
"url": "https://www.runoob.com/css3/css3-tutorial.html",
"image": "https://static.runoob.com/images/icon/css3.png"
},
{
"title": "Quick Tip: The Easiest Way To Make Responsive Headers",
"url": "https://www.runoob.com/css3/css3-tutorial.html",
"image": "https://static.runoob.com/images/icon/css3.png"
},
{
"title": "Learn SQL In 20 Minutes",
"url": "https://www.runoob.com/sql/sql-tutorial.html",
"image": "https://static.runoob.com/images/icon/sql.png"
},
{
"title": "Creating Your First Desktop App With HTML, JS and Electron",
"url": "https://www.runoob.com/js/js-tutorial.html",
"image": "https://static.runoob.com/images/icon/html.png"
}
]
},
computed: {
// 计算数学,匹配搜索
filteredArticles: function () {
var articles_array = this.articles,
searchString = this.searchString;
if(!searchString){
return articles_array;
}
searchString = searchString.trim().toLowerCase();
articles_array = articles_array.filter(function(item){
if(item.title.toLowerCase().indexOf(searchString) !== -1){
return item;
}
})
// 返回过来后的数组
return articles_array;;
}
}
});
#### 切换不同布局实例
##### 切换不同布局
点击右上角的按钮来切换不同页面布局:
{{a.title}}
### 1). el
指定dom标签容器的选择器 Vue就会管理对应的标签及其子标签
### 2). data
对象或函数类型 指定初始化状态属性数据的对象 vm也会自动拥有data中所有属性 页面中可以直接访问使用 数据代理: 由vm对象来代理对data中所有属性的操作(读/写)
### 3). methods
包含多个方法的对象 供页面中的事件指令来绑定回调 回调函数默认有event参数, 但也可以指定自己的参数 所有的方法由vue对象来调用, 访问data中的属性直接使用this.xxx
### 4). computed
包含多个方法的对象 对状态属性进行计算返回一个新的数据, 供页面获取显示 一般情况下是相当于是一个只读的属性 利用set/get方法来实现属性数据的计算读取, 同时监视属性数据的变化 如何给对象定义get/set属性 在创建对象时指定: get name () {return xxx} / set name (value) {} 对象创建之后指定: Object.defineProperty(obj, age, {get(){}, set(value){}})
### 5). watch
包含多个属性监视的对象 分为一般监视和深度监视 xxx: function(value){} xxx : { deep : true, handler : fun(value) } 另一种添加监视方式: vm.$watch(‘xxx’, function(value){})
## 4. 过渡动画
```vue
利用vue去操控css的transition/animation动画
模板: 使用包含带动画的标签
css样式
.fade-enter-active: 进入过程, 指定进入的transition
.fade-leave-active: 离开过程, 指定离开的transition
.xxx-enter, .xxx-leave-to: 指定隐藏的样式
编码例子
.xxx-enter-active, .xxx-leave-active {
transition: opacity .5s
}
.xxx-enter, .xxx-leave-to {
opacity: 0
}
hello
1.7. 生命周期
vm/组件对象
生命周期图
主要的生命周期函数(钩子)
created() / mounted(): 启动异步任务(启动定时器,发送ajax请求, 绑定监听)
beforeDestroy(): 做一些收尾的工作
1.8. 自定义过滤器
1.8.1. 理解
对需要显示的数据进行格式化后再显示
1.8.2. 编码
1). 定义过滤器
Vue.filter(filterName, function(value[,arg1,arg2,...]){
// 进行一定的数据处理
return newValue
})
2). 使用过滤器
{{myData | filterName}}
{{myData | filterName(arg)}}
1.9. vue内置指令
v-text/v-html: 指定标签体
* v-text : 当作纯文本
* v-html : 将value作为html标签来解析
v-if v-else v-show: 显示/隐藏元素
* v-if : 如果vlaue为true, 当前标签会输出在页面中
* v-else : 与v-if一起使用, 如果value为false, 将当前标签输出到页面中
* v-show: 就会在标签中添加display样式, 如果vlaue为true, display=block, 否则是none
v-for : 遍历
* 遍历数组 : v-for="(person, index) in persons"
* 遍历对象 : v-for="value in person" $key
v-on : 绑定事件监听
* v-on:事件名, 可以缩写为: @事件名
* 监视具体的按键: @keyup.keyCode @keyup.enter
* 停止事件的冒泡和阻止事件默认行为: @click.stop @click.prevent
* 隐含对象: $event
v-bind : 强制绑定解析表达式
* html标签属性是不支持表达式的, 就可以使用v-bind
* 可以缩写为: :id='name'
* :class
* :class="a"
* :class="{classA : isA, classB : isB}"
* :class="[classA, classB]"
* :style
:style="{color : color}"
v-model
* 双向数据绑定
* 自动收集用户输入数据
ref : 标识某个标签
* ref='xxx'
* 读取得到标签对象: this.$refs.xxx
1.10. 自定义指令
1.10.1. 1). 注册全局指令
Vue.directive('my-directive', function(el, binding){
el.innerHTML = binding.value.toUpperCase()
})
1.10.2. 2). 注册局部指令
directives : {
'my-directive' : function(el, binding) {
el.innerHTML = binding.value.toUpperCase()
}
}
1.10.3. 3). 使用指令
1.11. 9.实现一个脚手架(vue-cli)创建的一个简单 to do list 实例。
完整项目下载:
Download
下载后进入项目目录执行 npm install 命令导入依赖模块。
g](vue_res/下命令启动项目:
npm run dev
此项目端口号设为 6060。
项目目录结构:
src/App.vue 文件代码:
src/store.js 实现存储,即刷新数据不消失:
const STORAGE_KEY='todos-vuejs'
export default {
fetch:function(){
return JSON.parse(window.localStorage.getItem(STORAGE_KEY)||'[]');
},
save:function(items){
window.localStorage.setItem(STORAGE_KEY,JSON.stringify(items))
}
}
2. vuex是什么
2.1. 1.vuex
github站点: https://github.com/vuejs/vuex
在线文档: https://vuex.vuejs.org/zh-cn/
简单来说: 对应用中组件的状态进行集中式的管理(读/写)
2.2. 状态自管理应用
state: 驱动应用的数据源
view: 以声明方式将state映射到视图
actions: 响应在view上的用户输入导致的状态变化(包含n个更新状态的方法)
2.3. 多组件共享状态的问题
多个视图依赖于同一状态
来自不同视图的行为需要变更同一状态
以前的解决办法
* 将数据以及操作数据的行为都定义在父组件
* 将数据以及操作数据的行为传递给需要的各个子组件(有可能需要多级传递)
vuex就是用来解决这个问题的
2.4. vuex的核心概念
2.4.1. state
vuex管理的状态对象
它应该是唯一的
const state = {
xxx: initValue
}
2.4.2. mutations
包含多个直接更新state的方法(回调函数)的对象
谁来触发: action中的commit('mutation名称')
只能包含同步的代码, 不能写异步代码
const mutations = {
yyy (state, data) {
// 更新state的某个属性
}
}
2.4.3. actions
包含多个事件回调函数的对象
通过执行: commit()来触发mutation的调用, 间接更新state
谁来触发: 组件中: $store.dispatch('action名称') // 'zzz'
可以包含异步代码(定时器, ajax)
const actions = {
zzz ({commit, state}, data1) {
commit('yyy', data2)
}
}
2.4.4. getters
包含多个计算属性(get)的对象
谁来读取: 组件中: $store.getters.xxx
const getters = {
mmm (state) {
return ...
}
}
2.4.5. modules
包含多个module
一个module是一个store的配置对象
与一个组件(包含有共享数据)对应
2.4.6. 向外暴露store对象
export default new Vuex.Store({
state,
mutations,
actions,
getters
})
2.4.7. 组件中:
import {mapGetters, mapActions} from 'vuex'
export default {
computed: mapGetters(['mmm'])
methods: mapActions(['zzz'])
}
{{mmm}} @click="zzz(data)"
2.4.8. 映射store
import store from './store'
new Vue({
store
})
2.4.9. store对象
1.所有用vuex管理的组件中都多了一个属性$store, 它就是一个store对象
2.属性:
state: 注册的state对象
getters: 注册的getters对象
3.方法:
dispatch(actionName, data): 分发action
2.5. 将vuex引到项目中
2.5.1. 下载: npm install vuex --save
2.5.2. 使用vuex
1.store.js
import Vuex from 'vuex'
export default new Vuex.Store({
state,
mutations,
actions,
getters,
modules
})
2.main.js
import store from './store.js'
new Vue({
store
})
3. VueSource准备
3.1. vueSource
1.[].slice.call(lis): 将伪数组转换为真数组
2.node.nodeType: 得到节点类型
3.Object.defineProperty(obj, propertyName, {}): 给对象添加/修改属性(指定描述符)
configurable: true/false 是否可以重新define
enumerable: true/false 是否可以枚举(for..in / keys())
value: 指定初始值
writable: true/false value是否可以修改存取(访问)描述符
get: 函数, 用来得到当前属性值
set: 函数, 用来监视当前属性值的变化
4.Object.keys(obj): 得到对象自身可枚举的属性名的数组
5.DocumentFragment: 文档碎片(高效批量更新多个节点)
6.obj.hasOwnProperty(prop): 判断prop是否是obj自身的属性
3.2. 数据代理(MVVM.js)
1.通过一个对象代理对另一个对象中属性的操作(读/写)
2.通过vm对象来代理data对象中所有属性的操作
3.好处: 更方便的操作data中的数据
4.基本实现流程
1). 通过Object.defineProperty()给vm添加与data对象的属性对应的属性描述符
2). 所有添加的属性都包含getter/setter
3). 在getter/setter内部去操作data中对应的属性数据
3.3. 模板解析(compile.js)
1.模板解析的关键对象: compile对象
2.模板解析的基本流程:
1). 将el的所有子节点取出, 添加到一个新建的文档fragment对象中
2). 对fragment中的所有层次子节点递归进行编译解析处理
* 对表达式文本节点进行解析
* 对元素节点的指令属性进行解析
* 事件指令解析
* 一般指令解析
3). 将解析后的fragment添加到el中显示
3.解析表达式文本节点: textNode.textContent = value
1). 根据正则对象得到匹配出的表达式字符串: 子匹配/RegExp.$1
2). 从data中取出表达式对应的属性值
3). 将属性值设置为文本节点的textContent
4.事件指令解析: elementNode.addEventListener(事件名, 回调函数.bind(vm))
v-on:click="test"
1). 从指令名中取出事件名
2). 根据指令的值(表达式)从methods中得到对应的事件处理函数对象
3). 给当前元素节点绑定指定事件名和回调函数的dom事件监听
4). 指令解析完后, 移除此指令属性
5.一般指令解析: elementNode.xxx = value
1). 得到指令名和指令值(表达式)
2). 从data中根据表达式得到对应的值
3). 根据指令名确定需要操作元素节点的什么属性
* v-text---textContent属性
* v-html---innerHTML属性
* v-class--className属性
4). 将得到的表达式的值设置到对应的属性上
5). 移除元素的指令属性
3.4. 数据劫持–>数据绑定
< div id = " app" >
< ul v-for = " value in object" >
< label>
{{ value[0] }}
label>
< input type = " text" :placeholder = " value[1]" >
ul>
div>
< script>
new Vue ( {
el: '#app' ,
data: {
object: {
"HeartBeatTime" : [
"心跳周期时长" ,
"11" ,
"分钟"
] ,
"RetransmissionCounts" : [
"重传次数" ,
"22" ,
"次"
] ,
"SearchNetTime" : [
"搜网周期时长" ,
"33" ,
"分钟"
]
}
}
} )
script>
body>
html>
1.数据绑定(model==>View):
1). 一旦更新了data中的某个属性数据, 所有界面上直接使用或间接使用了此属性的节点都会更新(更新)
2.数据劫持
1). 数据劫持是vue中用来实现数据绑定的一种技术
2). 基本思想: 通过defineProperty()来监视data中所有属性(任意层次)数据的变化, 一旦变化就去更新界面
3.四个重要对象
1). Observer
* 用来对data所有属性数据进行劫持的构造函数
* 给data中所有属性重新定义属性描述(get/set)
* 为data中的每个属性创建对应的dep对象
2). Dep(Depend)
* data中的每个属性(所有层次)都对应一个dep对象
* 创建的时机:
* 在初始化define data中各个属性时创建对应的dep对象
* 在data中的某个属性值被设置为新的对象时
* 对象的结构
{
id, // 每个dep都有一个唯一的id
subs //包含n个对应watcher的数组(subscribes的简写)
}
* subs属性说明
* 当一个watcher被创建时, 内部会将当前watcher对象添加到对应的dep对象的subs中
* 当此data属性的值发生改变时, 所有subs中的watcher都会收到更新的通知, 从而最终更新对应的界面
3). Compile
* 用来解析模板页面的对象的构造函数(一个实例)
* 利用compile对象解析模板页面
* 每解析一个表达式(非事件指令)都会创建一个对应的watcher对象, 并建立watcher与dep的关系
* complie与watcher关系: 一对多的关系
4). Watcher
* 模板中每个非事件指令或表达式都对应一个watcher对象
* 监视当前表达式数据的变化
* 创建的时机: 在初始化编译模板时
* 对象的组成
{
vm, //vm对象
exp, //对应指令的表达式
cb, //当表达式所对应的数据发生改变的回调函数
value, //表达式当前的值
depIds //表达式中各级属性所对应的dep对象的集合对象
//属性名为dep的id, 属性值为dep
}
5). 总结: dep与watcher的关系: 多对多
* 一个data中的属性对应对应一个dep, 一个dep中可能包含多个watcher(模板中有几个表达式使用到了属性)
* 模板中一个非事件表达式对应一个watcher, 一个watcher中可能包含多个dep(表达式中包含了几个data属性)
* 数据绑定使用到2个核心技术
* defineProperty()
* 消息订阅与发布
4.双向数据绑定
1). 双向数据绑定是建立在单向数据绑定(model==>View)的基础之上的
2). 双向数据绑定的实现流程:
* 在解析v-model指令时, 给当前元素添加input监听
* 当input的value发生改变时, 将最新的值赋值给当前表达式所对应的data属性
4. vue脚手架
4.1. vue-cli
用来创建vue项目的工具包
创建项目:
npm install -g vue-cli
vue init webpack VueDemo
开发环境运行:
cd VueDemo
npm install
npm run dev
生产环境打包发布
npm run build
npm install -g serve
serve dist
http://localhost:5000
4.2. eslint
用来做项目编码规范检查的工具
基本原理: 定义了很多规则, 检查项目的代码一旦发现违背了某个规则就输出相应的提示信息
有相应的配置, 可定制检查
4.3. 组件化编程
vue文件包含3个部分
组件化编码的基本流程
1). 拆分界面, 抽取组件
2). 编写静态组件
3). 编写动态组件
初始化数据, 动态显示初始化界面
实现与用户交互功能
组件通信的5种方式
props
vue的自定义事件
pubsub第三方库
slot
vuex(后面单独讲)
props:
父子组件间通信的基本方式
属性值的2大类型:
一般: 父组件-->子组件
函数: 子组件-->父组件
隔层组件间传递: 必须逐层传递(麻烦)
兄弟组件间: 必须借助父组件(麻烦)
vue自定义事件
子组件与父组件的通信方式
用来取代function props
不适合隔层组件和兄弟组件间的通信
pubsub第三方库(消息订阅与发布)
适合于任何关系的组件间通信
slot
通信是带数据的标签
注意: 标签是在父组件中解析
vuex
多组件共享状态(数据的管理)
组件间的关系也没有限制
功能比pubsub强大, 更适用于vue项目
4.4. ajax
相关库:
vue-resource: vue插件, 多用于vue1.x
axios: 第三方库, 多用于vue2.x
vue-resource使用
// 引入模块
import VueResource from 'vue-resource'
// 使用插件
Vue.use(VueResource)
// 通过vue/组件对象发送ajax请求
this.$http.get('/someUrl').then((response) => {
// success callback
console.log(response.data) //返回结果数据
}, (response) => {
// error callback
console.log(response.statusText) //错误信息
})
axios使用
// 引入模块
import axios from 'axios'
// 发送ajax请求
axios.get(url)
.then(response => {
console.log(response.data) // 得到返回结果数据
})
.catch(error => {
console.log(error.message)
})
4.5. vue-router
vue用来实现SPA的插件
使用vue-router
1. 创建路由器: router/index.js
new VueRouter({
routes: [
{ // 一般路由
path: '/about',
component: about
},
{ // 自动跳转路由
path: '/',
redirect: '/about'
}
]
})
2. 注册路由器: main.js
import router from './router'
new Vue({
router
})
3. 使用路由组件标签:
Go to XXX
编写路由的3步
1. 定义路由组件
2. 映射路由
3. 编写路由2个标签
嵌套路由
children: [
{
path: '/home/news',
component: news
},
{
path: 'message',
component: message
}
]
向路由组件传递数据
params:
props:
缓存路由组件
路由的编程式导航
this.$router.push(path): 相当于点击路由链接(可以返回到当前路由界面)
this.$router.replace(path): 用新路由替换当前路由(不可以返回到当前路由界面)
this.$router.back(): 请求(返回)上一个记录路由